mcp-run-python


Namemcp-run-python JSON
Version 0.0.21 PyPI version JSON
download
home_pageNone
SummaryModel Context Protocol server to run Python code in a sandbox.
upload_time2025-09-04 02:02:46
maintainerNone
docs_urlNone
authorSamuel Colvin
requires_python>=3.10
licenseNone
keywords
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            <div align="center">
  <h1>MCP Run Python</h1>
</div>
<div align="center">
  <a href="https://github.com/pydantic/mcp-run-python/actions/workflows/ci.yml?query=branch%3Amain"><img src="https://github.com/pydantic/mcp-run-python/actions/workflows/ci.yml/badge.svg?event=push" alt="CI"></a>
  <a href="https://pypi.python.org/pypi/mcp-run-python"><img src="https://img.shields.io/pypi/v/mcp-run-python.svg" alt="PyPI"></a>
  <a href="https://github.com/pydantic/mcp-run-python"><img src="https://img.shields.io/pypi/pyversions/mcp-run-python.svg" alt="versions"></a>
  <a href="https://github.com/pydantic/mcp-run-python/blob/main/LICENSE"><img src="https://img.shields.io/github/license/pydantic/mcp-run-python.svg" alt="license"></a>
  <a href="https://logfire.pydantic.dev/docs/join-slack/"><img src="https://img.shields.io/badge/Slack-Join%20Slack-4A154B?logo=slack" alt="Join Slack" /></a>
</div>
<br/>
<div align="center">
  MCP server to run Python code in a sandbox.
</div>
<br/>

Code is executed using [Pyodide](https://pyodide.org) in [Deno](https://deno.com/) and is therefore isolated from
the rest of the operating system.

## Features

- **Secure Execution**: Run Python code in a sandboxed WebAssembly environment
- **Package Management**: Automatically detects and installs required dependencies
- **Complete Results**: Captures standard output, standard error, and return values
- **Asynchronous Support**: Runs async code properly
- **Error Handling**: Provides detailed error reports for debugging

_(This code was previously part of [Pydantic AI](https://github.com/pydantic/pydantic-ai) but was moved to a separate repo to make it easier to maintain.)_

## Usage

To use this server, you must have both Python and [Deno](https://deno.com/) installed.

The server can be run with `deno` installed using `uvx`:

```bash
uvx mcp-run-python [-h] [--version] [--port PORT] [--deps DEPS] {stdio,streamable-http,example}
```

where:

- `stdio` runs the server with the
  [Stdio MCP transport](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#stdio) — suitable for
  running the process as a subprocess locally
- `streamable-http` runs the server with the
  [Streamable HTTP MCP transport](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#streamable-http) -
  suitable for running the server as an HTTP server to connect locally or remotely. This supports stateful requests, but
  does not require the client to hold a stateful connection like SSE
- `example` will run a minimal Python script using `numpy`, useful for checking that the package is working, for the code
  to run successfully, you'll need to install `numpy` using `uvx mcp-run-python --deps numpy example`

## Usage with Pydantic AI

Then you can use `mcp-run-python` with Pydantic AI:

```python
from pydantic_ai import Agent
from pydantic_ai.mcp import MCPServerStdio
from mcp_run_python import deno_args_prepare

import logfire

logfire.configure()
logfire.instrument_mcp()
logfire.instrument_pydantic_ai()

server = MCPServerStdio('uvx', args=['mcp-run-python@latest', 'stdio'], timeout=10)
agent = Agent('claude-3-5-haiku-latest', toolsets=[server])


async def main():
    async with agent:
        result = await agent.run('How many days between 2000-01-01 and 2025-03-18?')
    print(result.output)
    #> There are 9,208 days between January 1, 2000, and March 18, 2025.w

if __name__ == '__main__':
    import asyncio
    asyncio.run(main())
```

## Usage in codes as an MCP server

First install the `mcp-run-python` package:

```bash
pip install mcp-run-python
# or
uv add mcp-run-python
```

With `mcp-run-python` installed, you can also run deno directly with `prepare_deno_env` or `async_prepare_deno_env`


```python
from pydantic_ai import Agent
from pydantic_ai.mcp import MCPServerStdio
from mcp_run_python import async_prepare_deno_env

import logfire

logfire.configure()
logfire.instrument_mcp()
logfire.instrument_pydantic_ai()


async def main():
    async with async_prepare_deno_env('stdio') as deno_env:
        server = MCPServerStdio('deno', args=deno_env.args, cwd=deno_env.cwd, timeout=10)
        agent = Agent('claude-3-5-haiku-latest', toolsets=[server])
        async with agent:
            result = await agent.run('How many days between 2000-01-01 and 2025-03-18?')
        print(result.output)
        #> There are 9,208 days between January 1, 2000, and March 18, 2025.w

if __name__ == '__main__':
    import asyncio
    asyncio.run(main())
```

**Note**: `prepare_deno_env` can take `deps` as a keyword argument to install dependencies.
As well as returning the args needed to run `mcp_run_python`, `prepare_deno_env` creates a new deno environment
and installs the dependencies so they can be used by the server.

## Usage in code with `code_sandbox`

`mcp-run-python` includes a helper function `code_sandbox` to allow you to easily run code in a sandbox.

```py
from mcp_run_python import code_sandbox

code = """
import numpy
a = numpy.array([1, 2, 3])
print(a)
a
"""

async def main():
    async with code_sandbox(dependencies=['numpy']) as sandbox:
        result = await sandbox.eval(code)
        print(result)


if __name__ == '__main__':
    import asyncio

    asyncio.run(main())
```

Under the hood, `code_sandbox` runs an MCP server using `stdio`. You can run multiple code blocks with a single sandbox.

## Logging

MCP Run Python supports emitting stdout and stderr from the python execution as [MCP logging messages](https://github.com/modelcontextprotocol/specification/blob/eb4abdf2bb91e0d5afd94510741eadd416982350/docs/specification/draft/server/utilities/logging.md?plain=1).

For logs to be emitted you must set the logging level when connecting to the server. By default, the log level is set to the highest level, `emergency`.

## Dependencies

`mcp_run_python` uses a two step process to install dependencies while avoiding any risk that sandboxed code can
edit the filesystem.

* `deno` is first run with write permissions to the `node_modules` directory and dependencies are installed, causing wheels to be written to ``
* `deno` is then run with read-only permissions to the `node_modules` directory to run untrusted code.

Dependencies must be provided when initializing the server so they can be installed in the first step.

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "mcp-run-python",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.10",
    "maintainer_email": null,
    "keywords": null,
    "author": "Samuel Colvin",
    "author_email": "Samuel Colvin <samuel@pydantic.dev>",
    "download_url": "https://files.pythonhosted.org/packages/66/e0/dba9a1fdb5e5173ee29fb6cf55cdfbf03b45a43f7d8d6bd3c3d398031507/mcp_run_python-0.0.21.tar.gz",
    "platform": null,
    "description": "<div align=\"center\">\n  <h1>MCP Run Python</h1>\n</div>\n<div align=\"center\">\n  <a href=\"https://github.com/pydantic/mcp-run-python/actions/workflows/ci.yml?query=branch%3Amain\"><img src=\"https://github.com/pydantic/mcp-run-python/actions/workflows/ci.yml/badge.svg?event=push\" alt=\"CI\"></a>\n  <a href=\"https://pypi.python.org/pypi/mcp-run-python\"><img src=\"https://img.shields.io/pypi/v/mcp-run-python.svg\" alt=\"PyPI\"></a>\n  <a href=\"https://github.com/pydantic/mcp-run-python\"><img src=\"https://img.shields.io/pypi/pyversions/mcp-run-python.svg\" alt=\"versions\"></a>\n  <a href=\"https://github.com/pydantic/mcp-run-python/blob/main/LICENSE\"><img src=\"https://img.shields.io/github/license/pydantic/mcp-run-python.svg\" alt=\"license\"></a>\n  <a href=\"https://logfire.pydantic.dev/docs/join-slack/\"><img src=\"https://img.shields.io/badge/Slack-Join%20Slack-4A154B?logo=slack\" alt=\"Join Slack\" /></a>\n</div>\n<br/>\n<div align=\"center\">\n  MCP server to run Python code in a sandbox.\n</div>\n<br/>\n\nCode is executed using [Pyodide](https://pyodide.org) in [Deno](https://deno.com/) and is therefore isolated from\nthe rest of the operating system.\n\n## Features\n\n- **Secure Execution**: Run Python code in a sandboxed WebAssembly environment\n- **Package Management**: Automatically detects and installs required dependencies\n- **Complete Results**: Captures standard output, standard error, and return values\n- **Asynchronous Support**: Runs async code properly\n- **Error Handling**: Provides detailed error reports for debugging\n\n_(This code was previously part of [Pydantic AI](https://github.com/pydantic/pydantic-ai) but was moved to a separate repo to make it easier to maintain.)_\n\n## Usage\n\nTo use this server, you must have both Python and [Deno](https://deno.com/) installed.\n\nThe server can be run with `deno` installed using `uvx`:\n\n```bash\nuvx mcp-run-python [-h] [--version] [--port PORT] [--deps DEPS] {stdio,streamable-http,example}\n```\n\nwhere:\n\n- `stdio` runs the server with the\n  [Stdio MCP transport](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#stdio) \u2014 suitable for\n  running the process as a subprocess locally\n- `streamable-http` runs the server with the\n  [Streamable HTTP MCP transport](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#streamable-http) -\n  suitable for running the server as an HTTP server to connect locally or remotely. This supports stateful requests, but\n  does not require the client to hold a stateful connection like SSE\n- `example` will run a minimal Python script using `numpy`, useful for checking that the package is working, for the code\n  to run successfully, you'll need to install `numpy` using `uvx mcp-run-python --deps numpy example`\n\n## Usage with Pydantic AI\n\nThen you can use `mcp-run-python` with Pydantic AI:\n\n```python\nfrom pydantic_ai import Agent\nfrom pydantic_ai.mcp import MCPServerStdio\nfrom mcp_run_python import deno_args_prepare\n\nimport logfire\n\nlogfire.configure()\nlogfire.instrument_mcp()\nlogfire.instrument_pydantic_ai()\n\nserver = MCPServerStdio('uvx', args=['mcp-run-python@latest', 'stdio'], timeout=10)\nagent = Agent('claude-3-5-haiku-latest', toolsets=[server])\n\n\nasync def main():\n    async with agent:\n        result = await agent.run('How many days between 2000-01-01 and 2025-03-18?')\n    print(result.output)\n    #> There are 9,208 days between January 1, 2000, and March 18, 2025.w\n\nif __name__ == '__main__':\n    import asyncio\n    asyncio.run(main())\n```\n\n## Usage in codes as an MCP server\n\nFirst install the `mcp-run-python` package:\n\n```bash\npip install mcp-run-python\n# or\nuv add mcp-run-python\n```\n\nWith `mcp-run-python` installed, you can also run deno directly with `prepare_deno_env` or `async_prepare_deno_env`\n\n\n```python\nfrom pydantic_ai import Agent\nfrom pydantic_ai.mcp import MCPServerStdio\nfrom mcp_run_python import async_prepare_deno_env\n\nimport logfire\n\nlogfire.configure()\nlogfire.instrument_mcp()\nlogfire.instrument_pydantic_ai()\n\n\nasync def main():\n    async with async_prepare_deno_env('stdio') as deno_env:\n        server = MCPServerStdio('deno', args=deno_env.args, cwd=deno_env.cwd, timeout=10)\n        agent = Agent('claude-3-5-haiku-latest', toolsets=[server])\n        async with agent:\n            result = await agent.run('How many days between 2000-01-01 and 2025-03-18?')\n        print(result.output)\n        #> There are 9,208 days between January 1, 2000, and March 18, 2025.w\n\nif __name__ == '__main__':\n    import asyncio\n    asyncio.run(main())\n```\n\n**Note**: `prepare_deno_env` can take `deps` as a keyword argument to install dependencies.\nAs well as returning the args needed to run `mcp_run_python`, `prepare_deno_env` creates a new deno environment\nand installs the dependencies so they can be used by the server.\n\n## Usage in code with `code_sandbox`\n\n`mcp-run-python` includes a helper function `code_sandbox` to allow you to easily run code in a sandbox.\n\n```py\nfrom mcp_run_python import code_sandbox\n\ncode = \"\"\"\nimport numpy\na = numpy.array([1, 2, 3])\nprint(a)\na\n\"\"\"\n\nasync def main():\n    async with code_sandbox(dependencies=['numpy']) as sandbox:\n        result = await sandbox.eval(code)\n        print(result)\n\n\nif __name__ == '__main__':\n    import asyncio\n\n    asyncio.run(main())\n```\n\nUnder the hood, `code_sandbox` runs an MCP server using `stdio`. You can run multiple code blocks with a single sandbox.\n\n## Logging\n\nMCP Run Python supports emitting stdout and stderr from the python execution as [MCP logging messages](https://github.com/modelcontextprotocol/specification/blob/eb4abdf2bb91e0d5afd94510741eadd416982350/docs/specification/draft/server/utilities/logging.md?plain=1).\n\nFor logs to be emitted you must set the logging level when connecting to the server. By default, the log level is set to the highest level, `emergency`.\n\n## Dependencies\n\n`mcp_run_python` uses a two step process to install dependencies while avoiding any risk that sandboxed code can\nedit the filesystem.\n\n* `deno` is first run with write permissions to the `node_modules` directory and dependencies are installed, causing wheels to be written to ``\n* `deno` is then run with read-only permissions to the `node_modules` directory to run untrusted code.\n\nDependencies must be provided when initializing the server so they can be installed in the first step.\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Model Context Protocol server to run Python code in a sandbox.",
    "version": "0.0.21",
    "project_urls": {
        "Changelog": "https://github.com/pydantic/mcp-run-python/releases",
        "Homepage": "https://github.com/pydantic/mcp-run-python",
        "Source": "https://github.com/pydantic/mcp-run-python"
    },
    "split_keywords": [],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "0e3dfad699dcb312f91f6a7fc4509c74b0cba8ddd8e2b6f0fd75e8d4b1436d91",
                "md5": "08615d5e070f72feb5add8955bb20675",
                "sha256": "18b8bc4129e7b5be084904c5bbfb7fc7d1caae9f84fb2d84aa194180e732dc09"
            },
            "downloads": -1,
            "filename": "mcp_run_python-0.0.21-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "08615d5e070f72feb5add8955bb20675",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10",
            "size": 26103,
            "upload_time": "2025-09-04T02:02:44",
            "upload_time_iso_8601": "2025-09-04T02:02:44.961719Z",
            "url": "https://files.pythonhosted.org/packages/0e/3d/fad699dcb312f91f6a7fc4509c74b0cba8ddd8e2b6f0fd75e8d4b1436d91/mcp_run_python-0.0.21-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "66e0dba9a1fdb5e5173ee29fb6cf55cdfbf03b45a43f7d8d6bd3c3d398031507",
                "md5": "21bb3dc328a020b4149b81fc794111a2",
                "sha256": "1ea77501b7bccb637192186adf7fc2048e21ee0c1c515de9e35c0c2f61916c04"
            },
            "downloads": -1,
            "filename": "mcp_run_python-0.0.21.tar.gz",
            "has_sig": false,
            "md5_digest": "21bb3dc328a020b4149b81fc794111a2",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.10",
            "size": 23296,
            "upload_time": "2025-09-04T02:02:46",
            "upload_time_iso_8601": "2025-09-04T02:02:46.120889Z",
            "url": "https://files.pythonhosted.org/packages/66/e0/dba9a1fdb5e5173ee29fb6cf55cdfbf03b45a43f7d8d6bd3c3d398031507/mcp_run_python-0.0.21.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-09-04 02:02:46",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "pydantic",
    "github_project": "mcp-run-python",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "mcp-run-python"
}
        
Elapsed time: 1.03169s