Error Handling & Resource Limits
Relevant source files
The following files were used as context for generating this wiki page:
Error handling and resource management are central to the security-first architecture of the MCP Server Code Execution Mode bridge. The system utilizes a rootless container-based sandbox to enforce strict isolation, preventing unauthorized resource consumption or host system access. This design ensures that even if untrusted code generates errors or attempts to exceed limits, the host environment remains protected and stable.
The bridge implements multi-layered resource constraints, including memory caps, PID limits, CPU quotas, and execution timeouts. Error handling is structured to capture failures at various stages—initialization, container runtime, and code execution—providing detailed feedback to the Model Context Protocol (MCP) client while maintaining secure boundaries.
Resource Constraints and Sandbox Isolation
The system enforces isolation through the RootlessContainerSandbox class, which translates configuration settings into specific container runtime arguments (Podman or Docker). These limits prevent "denial of service" attacks from sandboxed code by capping memory and process creation.
Sandbox Resource Matrix
The following table summarizes the primary resource limits applied to every code execution request:
| Constraint | Environment Variable | Default Value | Sandbox Enforcement |
|---|---|---|---|
| Memory | MCP_BRIDGE_MEMORY | 512m | --memory |
| PIDs | MCP_BRIDGE_PIDS | 128 | --pids-limit |
| CPU | MCP_BRIDGE_CPUS | Host Default | --cpus |
| Timeout | MCP_BRIDGE_TIMEOUT | 30s | Host-side asyncio.wait_for |
| Storage | N/A | 64m/128m | tmpfs mounts for /tmp and /workspace |
Sources: mcp_server_code_execution_mode.py:127-133, mcp_server_code_execution_mode.py:539-563, README.md:464-477
Filesystem and Network Security
Beyond hardware resources, the sandbox restricts environment capabilities:
- Read-Only Root: The container filesystem is mounted as read-only (
--read-only) to prevent permanent modification of the base image. - Network Isolation: The sandbox is completely disconnected from the network (
--network none). - Privilege Drop: All Linux capabilities are dropped (
--cap-drop ALL) and new privileges are blocked (no-new-privileges). - Unprivileged User: Code runs as UID
65534:65534.
Sources: mcp_server_code_execution_mode.py:543-568, ARCHITECTURE.md:144-153
Execution Error Handling Flow
The bridge categorizes errors into three primary types: SandboxError, SandboxTimeout, and McpError. When an error occurs during the run_python tool call, the bridge captures the stdout and stderr generated up to the point of failure and returns them in a structured CallToolResult.
The diagram shows the logic flow from tool invocation to the various error exit points.
Sources: mcp_server_code_execution_mode.py:1255-1314, HISTORY.md:73-86
Detailed Error Classes
- SandboxError: A general exception raised when the sandbox fails to start, communication with the container is lost, or the container runtime (Podman/Docker) is unavailable. mcp_server_code_execution_mode.py:270-275
- SandboxTimeout: A specialized error occurring when the execution exceeds the
timeoutparameter (max 120s). Upon timeout, the host terminates the container process. mcp_server_code_execution_mode.py:289-290, mcp_server_code_execution_mode.py:756-764 - McpError: Used for protocol-level failures, such as requesting non-existent resources or invalid parameters during tool discovery. mcp_server_code_execution_mode.py:1225-1232
Stdio and Stream Filtering
To keep the LLM context lean and avoid noise, the bridge implements stream filtering for stdout and stderr.
Noise Filtering Logic
The bridge filters out benign errors that often occur with chatty MCP clients, such as blank lines causing JSON parse errors. In the PersistentMCPClient, a filtered reader ignores specific "Invalid JSON: EOF while parsing a value" errors when the input value is a newline.
Sources: mcp_server_code_execution_mode.py:465-475, mcp_server_code_execution_mode.py:1203-1220
Output Transformation
Execution results are processed by _build_response_payload, which:
- Splits output into lines.
- Filters out "noise" (e.g., empty strings or
()tokens). - Trims empty fields from the structured payload to reduce token consumption.
Sources: mcp_server_code_execution_mode.py:347-360, mcp_server_code_execution_mode.py:421-450
Implementation of Timeouts and Cleanup
The bridge manages container lifecycles to ensure resources are not leaked after errors or successful completions.
Timeout Enforcement
Timeout management happens on the host side using asyncio.wait_for. If the sandbox stdout task does not complete within the specified timeframe, the host kills the process.
# mcp_server_code_execution_mode.py:756-764
try:
await asyncio.wait_for(stdout_task, timeout=timeout)
except asyncio.TimeoutError as exc:
process.kill()
await process.wait()
raise SandboxTimeout(
f"Execution timed out after {timeout}s",
stdout="".join(stdout_chunks),
stderr="".join(stderr_chunks),
) from exc
Runtime Idle Management
For Podman environments, the bridge includes a _shutdown_task that stops the Podman machine after a period of inactivity, defined by MCP_BRIDGE_RUNTIME_IDLE_TIMEOUT (default 300s). This ensures background VM resources are released when not in use.
Sources: mcp_server_code_execution_mode.py:612-624, ARCHITECTURE.md:68-71
Error Handling Summary Table
| Failure Scenario | Logic Applied | Result to Client |
|---|---|---|
| Invalid Server Requested | _lookup_server raises MCPError | Server 'name' is not available |
| Code Timeout | asyncio.wait_for triggers process.kill() | CallToolResult with status: timeout |
| Sandbox Crash | Process exit code checked via SandboxResult | CallToolResult with status: error + exitCode |
| Invalid JSON Input | Monkey-patched _handle_message ignores noise | No error returned (benign) |
| Memory Limit Hit | Container OOM killer terminates process | SandboxError with captured stderr |
Sources: mcp_server_code_execution_mode.py:917-918, mcp_server_code_execution_mode.py:1270-1300, GUIDE.md:387-393
Conclusion
The error handling and resource limit system provides a robust defense-in-depth strategy. By shifting execution to an unprivileged, rootless container with hard-coded resource caps, the bridge ensures that code execution is not only flexible but inherently safe. The multi-stage error capturing and stream filtering further enhance this by providing actionable feedback to LLM agents while maintaining minimal context overhead.