【免费下载链接】python-sdk
The official Python SDK for Model Context Protocol servers and clients
导读:本文基于官方 Python SDK(即本仓库 python-sdk,v2 稳定版文档线)的首页指南,带你从零搭建一个完整的 MCP 服务器:用两个带类型注解的 Python 函数同时暴露工具(tool)与模板资源(resource),通过
mcp dev配合 MCP Inspector 交互式验证,并深入源码与测试,理解"类型注解即协议"背后的自动 JSON Schema、序列化与校验机制。读完本文,你将掌握 MCP 服务器的最小可运行范式、CLI 开发工具链,以及如何用内存客户端为服务器编写自动化测试。
MCP 与官方 Python SDK 是什么
Model Context Protocol(MCP) 让应用可以用标准化的方式为 LLM 提供上下文,把"提供上下文"这件事与"和 LLM 对话"本身彻底解耦。本仓库就是这个协议的官方 Python SDK,基于它你可以:
- 构建 MCP 服务器:向任意 MCP 主机(如 Claude Desktop、MCP Inspector)暴露工具(tools)、资源(resources)和提示词(prompts);
- 构建 MCP 客户端:连接任意 MCP 服务器;
- 打通全部标准传输方式:stdio、Streamable HTTP 与 SSE。
本文对应的原文页面位于 i18n/ja/pages/index.md(英文原版为 docs/index.md),属于 v2(当前稳定发布系列)文档线的入口页。所有示例代码均来自仓库中真实存在、并被测试套件逐行验证的 docs_src/index/tutorial001.py。
环境要求与安装
SDK 要求 Python 3.10 及以上(见 pyproject.toml 中的 requires-python = ">=3.10")。
使用 uv(推荐)或 pip 安装,并带上 [cli] extra,以获得 mcp 命令行工具:
# 使用 uv
uv add "mcp[cli]"
# 使用 pip
pip install "mcp[cli]"
[cli] extra 会安装 mcp 命令(开发时强烈建议安装),各依赖项的用途可参考 安装指南。CLI 的入口实现位于 src/mcp/cli/cli.py,它基于 Typer 构建了 mcp 命令组;如果缺少 typer,程序会直接提示 pip install 'mcp[cli]'。
最小服务器:一个文件、两个函数
新建文件 server.py,内容如下(即 docs_src/index/tutorial001.py 的原文):
from mcp.server import MCPServer
mcp = MCPServer("Demo")
@mcp.tool()
def add(a: int, b: int) -> int:
"""Add two numbers."""
return a + b
@mcp.resource("greeting://{name}")
def greeting(name: str) -> str:
"""Greet someone by name."""
return f"Hello, {name}!"
就这么点代码,它已经是一个完整的 MCP 服务器,对外暴露:
- 一个工具
add:接收两个整数,返回它们的和; - 一个模板化资源
greeting://{name}:{name}是 RFC 6570 URI 模板变量,读取时按需填充。
从源码看 MCPServer 都做了什么
MCPServer 定义于 src/mcp/server/mcpserver/server.py,构造时会自动完成大量底层工作:
- 内部维护
ToolManager、ResourceManager、PromptManager三个管理器(见MCPServer.__init__),并把这些管理器绑定到低层Server的各请求处理器上(on_list_tools、on_call_tool、on_read_resource、on_list_resource_templates等),也就是把"协议层请求"映射到"你的函数"; @mcp.tool()装饰器把函数注册进ToolManager,name参数缺省时直接用函数名;@mcp.resource("greeting://{name}")装饰器在 server.py 内部通过UriTemplate.parse解析模板:URI 含{...}变量即注册为模板资源,并要求模板变量与函数参数一一对应(不匹配会直接抛出ValueError);无变量则注册为静态资源,此时函数不允许声明参数。
也就是说,"协议处理"这一层完全由 SDK 替你完成,你只需要写业务函数。
运行:mcp dev 与 MCP Inspector
在项目目录下执行:
uv run mcp dev server.py
这会启动你的服务器,并自动打开 MCP Inspector——一个用于交互式测试服务器的图形界面,按终端打印出的 URL 访问即可。
mcp dev 背后发生了什么
看 src/mcp/cli/cli.py 中 dev 命令的实现,它做了三件事:
- 导入服务器模块:
_import_server会把文件所在目录临时加入sys.path,按mcp、server、app的顺序在模块中查找MCPServer实例(也支持server.py:my_server这种file:object语法指定对象名); - 收集依赖:读取服务器对象上的
dependencies属性(MCPServer构造参数之一),与--with/--with-editable选项合并,构建uv run --with ... mcp run server.py形式的启动命令; - 拉起 Inspector:调用
npx @modelcontextprotocol/inspector启动这个 Node.js 应用并把服务器作为其子进程接入。
因此注意:Inspector 是 Node.js 应用,mcp dev 需要你的 PATH 中存在 npx。如果找不到 npx,CLI 会明确报错提示安装 Node.js/npm 或重启终端。
其他常用 CLI 命令
mcp 命令组还提供了(均见 src/mcp/cli/cli.py):
mcp run server.py:直接运行服务器,可选-t/--transport(stdio、sse、streamable-http);它负责导入并调用server.run(),依赖由你自行保证;mcp install server.py:把服务器安装进 Claude Desktop 应用,支持--name、--with、--env-var KEY=VALUE、--env-file .env等参数,环境变量写入后保留,仅在显式给出新值时更新;mcp version:打印当前安装的mcp包版本。
试运行:调用工具与读取资源
调用工具
在 Inspector 中打开 Tools 面板,给 add 传 a=1、b=2,返回:
3
注意,Inspector 的输入表单(一个必填的整数输入框 a、另一个 b)是从你的类型注解自动生成的。Claude 或其他任何 MCP 主机也会这样做。
读取资源
打开 Resources 面板,读取 greeting://World:
Hello, World!
为什么不用写任何样板代码:类型注解即协议
回到 server.py,细看你没有写的东西:
- 没有 JSON Schema:
a: int, b: int本身就是 schema; - 没有请求解析、序列化、校验代码;
- 没有任何协议处理代码。
你只写了两个带类型注解和 docstring 的 Python 函数,其余全部由 SDK 接管。
源码级的原理印证
- 参数模型生成:在 src/mcp/server/mcpserver/utilities/func_metadata.py 的
func_metadata()中,SDK 用inspect.signature读取函数签名,为每个参数构建 Pydantic 字段,并通过create_model动态生成<函数名>Arguments模型;该模型的 JSON Schema 即对外发布的工具input_schema。这正是"a: int, b: int就是 schema"的实现来源。该模块还会把无注解参数按字符串处理、对与BaseModel属性冲突的参数名自动加 alias、校验参数名不能以_开头等。 - 参数容错解析:
pre_parse_json()会尝试把字符串形式的 JSON(如["a","b","c"])预先解析回真实类型——这是为了兼容 Claude Desktop 等主机喜欢把 JSON 当字符串传的习性。 - 结果转换:工具返回值经
convert_result()统一转换为CallToolResult(文本内容包装成TextContent;dict/模型等非字符串结果会 JSON 序列化后放入文本块,并同步生成structured_content)。 - 同步函数自动跑在线程池:
call_fn()对同步函数使用anyio.to_thread.run_sync执行,避免阻塞事件循环,因此同步/异步函数可以混用。 - 资源模板:读取
greeting://World时,ResourceManager用 URI 模板匹配出name=World,调用greeting函数,结果按text/plain返回,与 tests/docs_src/test_index.py 中断言的TextResourceContents(uri="greeting://World", mime_type="text/plain", text="Hello, World!")完全一致。
用内存客户端验证:无需端口与子进程的测试
SDK 允许客户端直接"钻进"服务器对象,不必走任何网络传输。仓库为首页示例配套的测试 tests/docs_src/test_index.py 完整覆盖了上面的两个功能:
import pytest
from mcp import Client
from server import mcp
@pytest.mark.anyio
async def test_add() -> None:
async with Client(mcp) as client:
result = await client.call_tool("add", {"a": 1, "b": 2})
assert result.structured_content == {"result": 3}
@pytest.mark.anyio
async def test_greeting_resource_template() -> None:
async with Client(mcp) as client:
result = await client.read_resource("greeting://World")
assert result.contents[0].text == "Hello, World!"
没有子进程、没有端口、没有传输层——Client(mcp) 直接连接到服务器对象。仓库的 CI 会通过这套测试保证文档示例与真实代码不脱节。这也正是你给自己服务器写测试的方式,更完整的说明见 测试指南。
下一步阅读路线
- 开始使用:从安装一路走到一个可运行、已测试的服务器;
- 客户端:构建"使用"MCP 服务器的一方应用;
- 添加到现有应用:如果你已有 FastAPI 或 Starlette 应用,可把 MCP 服务器挂载进去;
- 故障排查:按错误消息原文检索解决方案;
- v2 的新功能:5 分钟了解 v2 的变化;
- 迁移指南:从 v1 迁移的起点;
- API 参考:由源码生成的精确签名文档。
此外,该文档集也以 llms.txt 友好格式发布:llms.txt 是各页面索引,llms-full.txt 则是全部页面合并成的单个文件,适合与 LLM 一起阅读。
【免费下载链接】python-sdk
The official Python SDK for Model Context Protocol servers and clients
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



