RU

Run Python MCP Server with Deno Pyodide

Run Python code securely on an MCP server using Deno and Pyodide sandboxed tool calls.

Quick Install
npx -y @main/mcp-run-python

Overview

This MCP (Model Context Protocol) server runs Python code inside a browser-style Pyodide WebAssembly runtime while the host process is Deno. It exposes sandboxed tool calls so models or other orchestrators can request short-lived Python execution without giving access to the host system. The combination of Deno + Pyodide provides a single-process, memory-limited environment with deterministic startup and an HTTP-based MCP interface.

This server is useful when you need to execute untrusted or semi-trusted Python snippets from an LLM or automation pipeline, run small computations or data transforms, or offer a Python “tool” backed by a model orchestration platform. It focuses on isolation (no arbitrary host process spawning), configurable time and memory limits, and simple HTTP endpoints that implement the MCP tool-call pattern.

Features

  • Sandboxed Python execution using Pyodide (WebAssembly) inside Deno
  • MCP-compatible tool call endpoints for integrating with model orchestrators
  • Configurable timeouts and memory limits per request
  • Optional micropip support to install pure-Python wheels at runtime (PyPI)
  • Simple HTTP JSON API for executing snippets, evaluating expressions, and returning structured results
  • Docker-ready and runnable with a single Deno command for local development

Installation / Configuration

Prerequisites:

  • Deno (v1.30+ recommended)
  • Docker (optional, for containerized deployment)

Clone the repository and run with Deno:

git clone https://github.com/pydantic/pydantic-ai.git
cd pydantic-ai/mcp-run-python
deno run --allow-net --allow-read --unstable main.ts

Notes:

  • --allow-net is required so the server can open its HTTP listening socket (and to fetch Pyodide assets if not bundled).
  • Avoid granting file or environment access unless you explicitly need them. The runtime executes user code inside Pyodide and does not run arbitrary host processes.

Run with Docker:

# Build
docker build -t mcp-run-python:latest .

# Run (example)
docker run -p 8080:8080 \
  -e PORT=8080 \
  -e PYODIDE_VERSION=0.23.2 \
  --memory=512m \
  mcp-run-python:latest

Configuration environment variables (examples):

VariableDefaultDescription
PORT8080HTTP port the MCP server listens on
PYODIDE_VERSIONlatestPyodide release to load (if dynamic)
MAX_EXEC_MS5000Per-request execution timeout in milliseconds
MAX_MEMORY_MB256Memory cap per Pyodide worker (best-effort)

If the repo bundles Pyodide assets, the server can be started without network access; adjust the startup flags accordingly.

Available Tools / Resources

The server exposes one or more MCP tool endpoints that you can call via HTTP. Typical tool names and their purpose:

  • python.exec — execute a Python script. Returns stdout, stderr, and execution metadata.
  • python.eval — evaluate a Python expression and return the serialized result.
  • python.install — (optional) install a pure-Python wheel via micropip inside Pyodide.

Example request schema (JSON):

{
  "tool": "python.exec",
  "args": {
    "code": "import sys\nprint('Hello from Pyodide')\n",
    "timeout_ms": 3000
  }
}

Responses include an exit code-like status, captured stdout/stderr, and any JSON-serializable result.

Check the project’s README or the /openapi.json (if provided) for the precise endpoint paths and schema.

Use Cases

  1. LLM tool integration (MCP)

    • Use this server as a Python tool for an LLM orchestrator. When the model wants to run code, it issues an MCP tool call; the server runs the snippet in Pyodide and returns outputs back to the model, preventing direct access to the host environment.
  2. Secure code evaluation in web services

    • Offer a restricted “code sandbox” endpoint where users can submit short scripts for data parsing, small computations, or testing, without running arbitrary processes on the server.
  3. Data transformation pipeline step

    • Embed simple Python-based transforms in a larger ML/ETL pipeline where steps are defined by model-driven logic. Time limits and memory caps avoid long-running resource hogs.

Concrete curl example:

curl -X POST http://localhost:8080/tool \
  -H "Content-Type: application/json" \
  -d '{
    "tool": "python.exec",
    "args": {
      "code": "print(sum(range(10)))",
      "timeout_ms": 2000
    }
  }'

Python client example:

import requests, json

payload = {
  "tool": "python.exec",
  "args": {"code": "x = 1+1\nprint(x)\n", "timeout_ms": 2000}
}
r = requests.post("http://localhost:8080/tool", json=payload)
print(r.json())

Security & Best Practices

  • Treat the Pyodide sandbox as a strong-but-not-perfect barrier: it prevents direct OS-level access but be conservative about what you return to callers and how you allow package installation.
  • Enforce strict timeouts and memory caps to avoid denial-of-service from expensive computations.
  • Run the server with minimal host permissions; prefer containerized deployment and limit container privileges.
  • Log and monitor usage patterns to detect misuse.

Resources

  • GitHub repository: https://github.com/pydantic/pydantic-ai/tree/main/mcp-run-python
  • Pyodide documentation: https://pyodide.org
  • Deno manual: https://deno.land/manual

For exact API shapes, startup scripts, and bundled configuration, see the repository’s README and source files in the mcp-run-python directory.