运行 MCP 服务器:python-sdk 中 `mcp.run()` 的传输选择、参数详解与 CLI 工具链

📅 发布时间:2026/9/21 15:26:33
运行 MCP 服务器:python-sdk 中 `mcp.run()` 的传输选择、参数详解与 CLI 工具链
人工智能MCP 服务MCP Clients【免费下载链接】python-sdkThe official Python SDK for Model Context Protocol servers and clients项目地址https://gitcode.com/gh_mirrors/pythonsd/python-sdk点击查看免费下载mcp.run()是 python-sdk 中启动 MCP 服务器的统一入口唯一需要做的决策就是传输transport——服务器与客户端之间的字节如何流动。本文将围绕该入口完整讲解stdio、streamable-http、sse三种传输的取舍与配置参数并结合仓库源码src/mcp/server/mcpserver/server.py印证默认值、调用链与约束最后带读者掌握mcp dev、mcp run、mcp install、mcp version四个 CLI 命令的实战用法。选择传输一个决定三种选项传输决定了字节如何在你和客户端之间移动它是运行服务器时唯一需要做的架构决策。python-sdk 提供三种传输取舍关系如下表传输是什么何时使用stdio宿主把你的文件作为子进程启动通过它的 stdin 和 stdout 通信本地服务器。默认选项。streamable-http一个监听端口的真实 HTTP 服务器任何需要部署的场景sse更老的 HTTP 传输不要用警告SSE 已在 2025-03-26 协议修订中被 Streamable HTTP 取代。mcp.run(transportsse)仍然可用并保留自己的sse_path和message_path参数但它只是为尚未迁移的客户端保留的兼容通道不要在其上构建任何新东西。从源码看MCPServer.run()只接受stdio、sse、streamable-http三种字面量遇到其他值直接抛出ValueError(fUnknown transport: {transport})随后按传输分别转入run_stdio_async、run_sse_async、run_streamable_http_async三个异步实现见 src/mcp/server/mcpserver/server.py。mcp.run()同步阻塞的启动入口文档示例 docs_src/run/tutorial001.py 展示了最精简的服务器from mcp.server import MCPServer mcp MCPServer(Bookshop) mcp.tool() def search_books(query: str) - str: Search the catalog by title or author. return fFound 3 books matching {query!r}. if __name__ __main__: mcp.run()这段代码揭示了run()的三个关键事实run()是同步的它会阻塞block执行直到服务器整个生命周期结束。它内部通过anyio.run(...)驱动对应的异步实现见 src/mcp/server/mcpserver/server.py因此调用方不需要async环境。不传任何参数时传输为stdio。调用必须放在if __name__ __main__:之下。原因很实际所有加载你服务器的方式mcp dev、mcp run、mcp install、你的测试都会**导入import**这个文件这个保护能防止一次导入意外变成一台正在运行的服务器。这一点有测试用例直接验证tests/docs_src/test_run.py 通过Client(tutorial001.mcp)直接以内存方式导入并调用search_books证明导入不会启动服务器、服务器可以在内存中提供服务。stdio本地子进程无需任何配置stdio 传输没有任何需要配置的东西。宿主把你的文件作为子进程启动向它的 stdin 写入请求、从 stdout 读取响应。你可以自己运行试试python server.py结果是什么都不打印而且进程不返回——它在 stdin 上等待宿主先开口。你从来没有指定端口因为根本没有端口。这也意味着 stdout 就是线缆the wire其行为细节值得注意服务期间SDK 会把这条线缆迁移到私有描述符上并把刷入flushstdout的输出子进程写入继承来的 stdout、带刷新的print()重定向到 stderr防止污染数据流但服务开始前刷入 stdout 的输出包装脚本的 echo、导入期未缓冲的 print仍会落到线缆上服务期间留在缓冲区、直到解释器退出时才冲刷的print()同样如此对于你真正需要的输出正确的工具是logging模块——它的 handler 会把每条记录实时冲刷到 stderr。完整方案见 日志处理。亲手试一试mcp devuv run mcp dev server.pyMCP Inspector 做的事情与真实宿主完全一致把server.py启动为子进程通过 stdio 连接它。你没有给它端口因为它根本不需要端口。Streamable HTTP一行代码把服务器挂到端口上若要让同一个服务器监听端口只需在run()里指定传输及其参数。文档示例 docs_src/run/tutorial002.pyfrom mcp.server import MCPServer mcp MCPServer(Bookshop) mcp.tool() def search_books(query: str) - str: Search the catalog by title or author. return fFound 3 books matching {query!r}. if __name__ __main__: mcp.run(transportstreamable-http, port3001)这一行run(transportstreamable-http, port3001)会构建一个 Starlette 应用并用 uvicorn 提供服务。客户端连接到http://127.0.0.1:3001/mcp。从源码看run_streamable_http_async正是先调用self.streamable_http_app(...)组装 Starlette 应用再以uvicorn.Config(starlette_app, hosthost, portport, ...)启动服务见 src/mcp/server/mcpserver/server.py。传输专属参数全部传给run()每种传输都有自己的关键字参数且全部作为run()的参数传递。Streamable HTTP 的完整参数如下默认值均已从源码确认见 src/mcp/server/mcpserver/server.py参数作用默认值host/port在哪里监听127.0.0.1和8000streamable_http_pathMCP 端点路径/mcpjson_responseTrue用单个 JSON 体应答每个 POST而非 SSE 流Falsestateless_httpTrue每个请求一个全新传输不做会话追踪Falsemax_request_body_size最大可接受请求体字节数4 MiBsession_idle_timeout旧代会话无在途请求时服务器关闭它之前的空闲秒数1800None禁用max_sessions单进程同时持有的旧代会话数10 000None解除限制event_store/retry_interval/transport_security可恢复性与 DNS-rebinding 防护部署到 localhost 之外时再考虑几个参数需要展开说明json_responseTrue请求体的 JSON 只容得下响应本身因此中途回调客户端的工具ctx.elicit()、sampling 采样在这一支路上会抛出NoBackChannelError绑定在途调用的通知ctx.report_progress()的进度、单次调用的日志消息会被丢弃独立的GET流仍然可以送达与调用无关的通知。max_request_body_size默认 4 MiB更大的请求在解析或创建会话之前就直接收到 HTTP 413。只有当合法 MCP 消息确实超过该体积时才需要调大。session_idle_timeout/max_sessions默认值在 src/mcp/server/streamable_http_manager.py 中定义为DEFAULT_SESSION_IDLE_TIMEOUT: Final 30 * 60即 1800 秒和DEFAULT_MAX_SESSIONS: Final 10_000属于旧代legacy会话管理范畴详见 旧代客户端与会话生命周期。transport_security与 DNS-rebinding 防护相关在 部署与扩展 页面有专门讲解。易错点传输参数属于run()不属于MCPServer(...)警告传输参数传给run()而不是MCPServer(...)。构造函数描述你的服务器是什么——名称、版本、指令run()描述它如何被服务。搞反了Python 会在 MCP 介入之前就报错TypeError: MCPServer.__init__() got an unexpected keyword argument port这一错误行为同样被测试锁定tests/docs_src/test_run.py 显式验证向MCPServer(Bookshop, port3001)传入port会抛出unexpected keyword argument port。何时突破run()走向 ASGIrun()是捷径。一旦需要更多能力——把服务器挂载进已有应用、单进程跑两个服务器、为浏览器客户端配置 CORS——就需要自己组装 ASGI 应用并交给任意 ASGI 宿主运行。相关指南见 添加到已有应用。另外需要注意run()的 HTTP 路径在pragma: no cover标注下说明其核心逻辑以应用组装函数streamable_http_app/sse_app的形式暴露便于测试与复用。服务器设置与传输无关的构造器参数有两项运行相关配置与传输无关它们是构造器参数。文档示例 docs_src/run/tutorial003.pyfrom mcp.server import MCPServer mcp MCPServer(Bookshop, log_levelDEBUG) mcp.tool() def search_books(query: str) - str: Search the catalog by title or author. return fFound 3 books matching {query!r}. if __name__ __main__: mcp.run()log_level在MCPServer(...)构造的瞬间交给logging.basicConfig()。它配置的是根rootlogger所以设定的级别不仅作用于 SDK 的 logger也作用于你自己的 logger。默认INFO。源码中构造后立即调用configure_logging(self.settings.log_level)见 src/mcp/server/mcpserver/server.py类型限定为DEBUG | INFO | WARNING | ERROR | CRITICAL同文件 L116。debug转发给 HTTP 传输构建出的 Starlette 应用。默认False。两者最终都会落到mcp.settings上运行时可以读取回来。测试 tests/docs_src/test_run.py 验证了默认值组合tutorial001未传参得到log_level INFO、debug is False而tutorial003传log_levelDEBUG得到log_level DEBUG。mcp命令[cli]附加组件提供的命令行工具安装 SDK 的[cli]附加组件extra会在此之上提供一个小型命令行工具。四个子命令各司其职。mcp dev在 MCP Inspector 下运行uv run mcp dev server.py uv run mcp dev server.py --with pandas --with numpy uv run mcp dev server.py --with-editable .--with把包添加到它构建的环境里--with-editable以可编辑模式把你的包本身安装进该环境。该命令需要PATH中有npx——Inspector 是 Node.js 应用。源码中dev命令会解析文件与对象名、导入服务器、拼装 uv 命令然后执行npx modelcontextprotocol/inspector见 src/mcp/cli/cli.py找不到 npx 时会明确报错并退出。mcp run直接执行服务器文件mcp run导入文件找到服务器对象模块级的mcp、server或app并调用它的run()uv run mcp run server.py uv run mcp run server.py:bookshop:后缀用于对象名不是mcp、server、app时的指定方式。这里你的if __name__ __main__:块永远不会执行——mcp run自己调用run()且它唯一转发的选项是--transport见 src/mcp/cli/cli.py通过server.run(**kwargs)仅把transport放入 kwargs。mcp install注册到 Claude Desktopuv run mcp install server.py --name Bookshop uv run mcp install server.py -v API_KEYabc123 -f .env-v KEYVALUE和-f .env会把环境变量记录到该条注册项中。Claude Desktop 会在自己的独立进程中启动你的服务器——你的 shell 环境在那里并不存在所以密钥类配置必须显式注入。Claude Desktop 是唯一认识mcp install的宿主其他宿主Claude Code、Cursor、VS Code在自己各自的配置文件中接受同样的启动命令每个宿主的接法见 连接到真实宿主。mcp version查看已安装 SDK 版本uv run mcp version输出已安装 SDK 的版本号源码通过importlib.metadata.version(mcp)读取见 src/mcp/cli/cli.py。提示mcp dev和mcp run只认识MCPServer。如果你用低层Server构建服务器就需要自己运行它详见 低层 Server。要点回顾传输是字节抵达你服务器的方式stdio用于本地子进程streamable-http用于端口SSE 已被取代。mcp.run()负责选择传输不传参数时是stdio且调用会阻塞。每个传输选项host、port、streamable_http_path、……都是run()的参数永远不会是MCPServer(...)的参数。把run()放在if __name__ __main__:之下所有加载你服务器的方式都会先导入该文件。log_level和debug是构造器参数最终落到mcp.settings。mcp dev用于 Inspectormcp run用于执行文件mcp install用于 Claude Desktopmcp version用于查看版本。传输永远不会改变你的服务器是什么本页三个示例文件暴露的是完全相同的工具。这一不变量由测试 tests/docs_src/test_run.py 验证——三个不同运行方式的客户端看到的list_tools()结果完全一致。当run()本身成为瓶颈时把服务器放进已存在的应用下一步是 添加到已有应用使用真实主机名、多 worker 部署见 部署与扩展若部分客户端仍停留在 2025-11-25 或更早的协议版本请阅读 服务旧代客户端。赞分享人工智能MCP 服务MCP Clients【免费下载链接】python-sdkThe official Python SDK for Model Context Protocol servers and clients项目地址https://gitcode.com/gh_mirrors/pythonsd/python-sdk点击查看免费下载相关推荐在 python-sdk 中运行 MCP 服务器mcp.run()、传输方式与 mcp 命令行详解在 python sdk 中运行 MCP 服务器 mcp.run 、传输方式与 mcp 命令行详解 mcp.run 是 MCPModel Context P人工智能MCP 服务MCP Clients使用 mcp.run() 启动 MCP 服务器python-sdk 传输方式选择与 mcp 命令行实战使用 mcp.run 启动 MCP 服务器python sdk 传输方式选择与 mcp 命令行实战 本指南聚焦 Model Context Protocol人工智能MCP 服务MCP Clientspython-sdk 服务器启动指南mcp.run()、传输层选择与 mcp 命令行实战python sdk 服务器启动指南 mcp.run 、传输层选择与 mcp 命令行实战 本文围绕官方 Python SDK 中“运行 MCP 服务器”这一核人工智能MCP 服务MCP Clients上一篇3分钟美化你的CasaOS传统应用图标自定义全攻略下一篇揭秘gh_mirrors/examples113/examplesNode.js开发者不容错过的实战项目解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考