Skip to main content
Glama

MCP Server Code Execution Mode

by elusznik
ARCHITECTURE.md7.22 kB
# MCP Server Code Execution Mode Architecture ## Overview The bridge runs user-supplied Python inside a **rootless container** and proxies host-managed MCP servers into that sandbox when requested. Legacy in-process and RLIMIT-based prototypes remain in `archive/` for reference but are no longer used by the application. ## High-Level Flow ``` ┌───────────────────────────┐ │ MCP Client (e.g. Claude) │ └──────────────┬────────────┘ │ JSON-RPC over stdio ▼ ┌───────────────────────────┐ │ main.py / mcp_server_code_execution_mode │ │ - Exposes run_python tool │ │ - Validates input │ │ - Loads MCP servers │ └──────────────┬────────────┘ │ Async subprocess + JSON stdio bridge ▼ ┌───────────────────────────┐ │ Rootless container runtime│ │ (podman or docker rootless)│ │ - Read-only rootfs │ │ - Tmpfs work dir │ │ - No network │ │ - No Linux capabilities │ └──────────────┬────────────┘ │ ▼ ┌───────────────────────────┐ │ python:3.12-slim image │ │ - Runs async entrypoint │ │ - Executes provided code │ │ - Calls mcp_<alias> tools │ └───────────────────────────┘ ``` Each execution request receives a fresh container and a temporary `/ipc` mount that carries the generated sandbox entrypoint; JSON-framed messages over stdio mediate MCP tool access through the host. ## Components - **`main.py`**: Thin entry point that launches `mcp_server_code_execution_mode.main()` so the module can be registered as an MCP server. - **`mcp_server_code_execution_mode.py`**: Implements the MCP server, persistent MCP client pool, JSON RPC handlers, request validation, and container lifecycle management. - **`PersistentMCPClient`**: Keeps stdio sessions to discovered MCP servers alive across invocations, avoiding repeated cold starts and shutting down cleanly when the bridge stops. - **`SandboxInvocation`**: Builds per-execution metadata, writes the generated entrypoint into `/ipc`, injects `MCP_AVAILABLE_SERVERS`, and services JSON-RPC requests from the sandbox via `handle_rpc`. - **Runtime helpers**: The generated entrypoint exposes `mcp.runtime` helpers (`discovered_servers`, `list_servers`, `describe_server`, `list_loaded_server_metadata`) so sandboxed code can enumerate options before loading additional tools. - **Container runtime**: Either `podman` or rootless `docker` must be available in the user namespace. Runtime discovery prefers the value from the `MCP_BRIDGE_RUNTIME` environment variable. - **Podman machine management**: When using Podman, the bridge automatically starts the Podman machine if not running and shuts it down after `MCP_BRIDGE_RUNTIME_IDLE_TIMEOUT` seconds of inactivity (default 300s/5min). - **Legacy prototypes (`archive/`)**: Historical in-process experiments are retained for reference; see `HISTORY.md` for context on their retirement. ## Request Lifecycle 1. MCP client invokes the `run_python` tool with code, optional timeout, and an optional list of MCP server names. 2. The bridge discovers server definitions (Claude Code config files and `~/.config/mcp/servers/*.json`, with legacy Claude Desktop paths as fallbacks) and boots persistent MCP clients for the requested servers. 3. `SandboxInvocation` creates a temporary `/ipc` directory, writes the generated `entrypoint.py`, ensures the runtime can mount it, and exports `MCP_AVAILABLE_SERVERS` with serialized tool metadata. 4. The container launches `python -u /ipc/entrypoint.py`; the entrypoint rewires stdio into JSON frames, installs `mcp_servers`/`mcp_<alias>` proxies, and uses an asyncio reader on stdin to receive host RPC responses while supporting top-level `await`. 5. The container executes the user code with network disabled, read-only filesystem, tmpfs workspace, dropped capabilities, and user `65534:65534`. Memory, PID, and CPU limits are derived from environment variables, and `--no-new-privileges` is enforced. 6. The bridge consumes JSON frames from stdout/stderr, routes MCP requests via `SandboxInvocation.handle_rpc`, enforces the timeout, and translates exit codes and errors into MCP responses. 7. Temporary IPC assets are cleaned up and MCP clients remain warm for future calls. ## Configuration Environment variables allow most execution parameters to be tuned without code changes: | Variable | Purpose | Default | |----------|---------|---------| | `MCP_BRIDGE_RUNTIME` | Force container runtime (`podman` or `docker`) | auto-detect | | `MCP_BRIDGE_IMAGE` | Container image to run | `python:3.12-slim` | | `MCP_BRIDGE_TIMEOUT` | Default timeout (seconds) | 30 | | `MCP_BRIDGE_MAX_TIMEOUT` | Hard timeout ceiling | 120 | | `MCP_BRIDGE_MEMORY` | Memory limit passed to `--memory` | 512m | | `MCP_BRIDGE_PIDS` | PID limit for `--pids-limit` | 128 | | `MCP_BRIDGE_CPUS` | CPU quota for `--cpus` | host default | | `MCP_BRIDGE_CONTAINER_USER` | UID:GID inside container | 65534:65534 | | `MCP_BRIDGE_RUNTIME_IDLE_TIMEOUT` | Auto-shutdown delay for Podman machine (seconds) | 300 | ## Security Posture - **Rootless execution**: The container runtime operates entirely within the invoking user namespace; no privileged helpers are required. - **Ephemeral filesystem**: Only tmpfs mounts are writable, preventing the code from persisting data on the host. - **Capability drop**: With no capabilities and no-new-privileges set, the process cannot escalate privileges inside the container. - **Network disabled**: Requests cannot reach external services or internal hosts. - **Resource limits**: Memory, PID, and CPU caps prevent abusive resource use. - **MCP mediation**: All MCP traffic traverses the host RPC server, keeping audit visibility and allowing future policy enforcement. ## Current Limitations - Automated end-to-end tests for the container layer are not bundled because they would require a runtime and image download during test runs. - Observability is limited to basic logging; structured events and metrics remain future work. - Runtime discovery stops at the first available binary; richer diagnostics and configurability are desired. ## Extensibility Notes - Additional policy checks (e.g. allowlists/denylists) can be added inside `SandboxRPCServer._dispatch` before forwarding MCP calls. - Alternative images can be supplied through `MCP_BRIDGE_IMAGE` provided they contain Python 3 and accept `python -` to execute code from stdin. - Additional hardening (e.g. seccomp profiles or AppArmor) can be layered by injecting runtime-specific arguments once the chosen container runtime is known.

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/elusznik/mcp-server-code-execution-mode'

If you have feedback or need assistance with the MCP directory API, please join our Discord server