MCP 运行 Python
MCP Run Python 包是一个 MCP 服务器,允许智能体在安全的沙盒环境中执行 Python 代码。它使用 Pyodide 在带有 Deno 的 JavaScript 环境中运行 Python 代码,将执行与主机系统隔离。
特性
- 安全执行:在沙盒化的 WebAssembly 环境中运行 Python 代码
- 包管理:自动检测并安装所需的依赖项
- 完整结果:捕获标准输出、标准错误和返回值
- 异步支持:正确运行异步代码
- 错误处理:提供详细的错误报告以供调试
安装
从 npx 切换到 deno
我们之前将 mcp-run-python 作为 npm 包分发,以便通过 npx 使用。我们现在推荐使用 deno,因为它提供了更好的沙盒化和安全性。
MCP Run Python 服务器作为一个 JSR 包 分发,可以直接使用 deno run 运行。
deno run \
-N -R=node_modules -W=node_modules --node-modules-dir=auto \
jsr:@pydantic/mcp-run-python [stdio|streamable_http|sse|warmup]
其中
-N -R=node_modules -W=node_modules(--allow-net --allow-read=node_modules --allow-write=node_modules的别名) 允许网络访问以及对./node_modules的读写权限。这些是必需的,以便 Pyodide 可以下载和缓存 Python 标准库和包。--node-modules-dir=auto告诉 deno 使用本地的node_modules目录stdio使用 Stdio MCP 传输协议 运行服务器 — 适合作为本地子进程运行streamable_http使用 Streamable HTTP MCP 传输协议 运行服务器 — 将服务器作为 HTTP 服务器运行,以便在本地或远程连接。这支持有状态的请求,但不需要客户端像 SSE 那样保持有状态的连接。sse使用 SSE MCP 传输协议 运行服务器 — 将服务器作为 HTTP 服务器运行,以便在本地或远程连接warmup将运行一个最小的 Python 脚本来下载和缓存 Python 标准库。这也用于检查服务器是否正常运行。
在客户端文档中描述了如何将 jsr:@pydantic/mcp-run-python 与 Pydantic AI 一起使用。
直接使用
除了将此服务器与 Pydantic AI 一起使用外,它还可以连接到其他 MCP 客户端。为清楚起见,在此示例中,我们使用 Python MCP 客户端直接连接。
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
code = """
import numpy
a = numpy.array([1, 2, 3])
print(a)
a
"""
server_params = StdioServerParameters(
command='deno',
args=[
'run',
'-N',
'-R=node_modules',
'-W=node_modules',
'--node-modules-dir=auto',
'jsr:@pydantic/mcp-run-python',
'stdio',
],
)
async def main():
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
tools = await session.list_tools()
print(len(tools.tools))
#> 1
print(repr(tools.tools[0].name))
#> 'run_python_code'
print(repr(tools.tools[0].inputSchema))
"""
{'type': 'object', 'properties': {'python_code': {'type': 'string', 'description': 'Python code to run'}}, 'required': ['python_code'], 'additionalProperties': False, '$schema': 'https://json-schema.fullstack.org.cn/draft-07/schema#'}
"""
result = await session.call_tool('run_python_code', {'python_code': code})
print(result.content[0].text)
"""
<status>success</status>
<dependencies>["numpy"]</dependencies>
<output>
[1 2 3]
</output>
<return_value>
[
1,
2,
3
]
</return_value>
"""
如果发生异常,status 将是 install-error 或 run-error,并且 return_value 将被替换为 error,其中将包含回溯和异常消息。
依赖项
依赖项在代码运行时安装。
依赖项可以通过以下两种方式之一来定义
从导入中推断
如果没有元数据,依赖项会从代码中的导入语句中推断出来,如上文示例所示。
内联脚本元数据
如 PEP 723 中所引入,此处有解释,并由 uv 推广——依赖项可以在文件顶部的注释中定义。
这允许使用代码中未导入的依赖项,并且更加明确。
from mcp import ClientSession
from mcp.client.stdio import stdio_client
# using `server_params` from the above example.
from mcp_run_python import server_params
code = """\
# /// script
# dependencies = ["pydantic", "email-validator"]
# ///
import pydantic
class Model(pydantic.BaseModel):
email: pydantic.EmailStr
print(Model(email='hello@pydantic.dev'))
"""
async def main():
async with stdio_client(server_params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
result = await session.call_tool('run_python_code', {'python_code': code})
print(result.content[0].text)
"""
<status>success</status>
<dependencies>["pydantic","email-validator"]</dependencies>
<output>
email='hello@pydantic.dev'
</output>
"""
它还允许为非二进制包固定版本(Pyodide 对其支持的二进制包,如 pydantic 和 numpy,只支持单一版本)。
例如,您可以将依赖项设置为
# /// script
# dependencies = ["rich<13"]
# ///
日志记录
MCP Run Python 支持将 Python 执行过程中的 stdout 和 stderr 作为 MCP 日志消息 发出。
要发出日志,您必须在连接到服务器时设置日志级别。默认情况下,日志级别设置为最高级别 emergency。
目前,由于 Python MCP 客户端存在一个 bug,无法演示此功能,请参阅 modelcontextprotocol/python-sdk#201。