MCP Python SDK 快速上手:用 10 行代码构建并调试你的第一个 MCP 服务器

  • 人工智能
  • MCP 服务
  • MCP Clients

【免费下载链接】python-sdk

The official Python SDK for Model Context Protocol servers and clients

项目地址: https://gitcode.com/gh_mirrors/pythonsd/python-sdk
点击查看 免费下载

导读:本文基于官方 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 命令的实现,它做了三件事:

  1. 导入服务器模块:_import_server 会把文件所在目录临时加入 sys.path,按 mcp、server、app 的顺序在模块中查找 MCPServer 实例(也支持 server.py:my_server 这种 file:object 语法指定对象名);
  2. 收集依赖:读取服务器对象上的 dependencies 属性(MCPServer 构造参数之一),与 --with/--with-editable 选项合并,构建 uv run --with ... mcp run server.py 形式的启动命令;
  3. 拉起 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 会通过这套测试保证文档示例与真实代码不脱节。这也正是你给自己服务器写测试的方式,更完整的说明见 测试指南。

下一步阅读路线

此外,该文档集也以 llms.txt 友好格式发布:llms.txt 是各页面索引,llms-full.txt 则是全部页面合并成的单个文件,适合与 LLM 一起阅读。

  • 人工智能
  • MCP 服务
  • MCP Clients

【免费下载链接】python-sdk

The official Python SDK for Model Context Protocol servers and clients

项目地址: https://gitcode.com/gh_mirrors/pythonsd/python-sdk
点击查看 免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值