MCP Python SDK 快速上手:用 20 行代码构建你的第一个 MCP 服务器与客户端

MCP Python SDK 快速上手:用 20 行代码构建你的第一个 MCP 服务器与客户端

【免费下载链接】python-sdk The official Python SDK for Model Context Protocol servers and clients 【免费下载链接】python-sdk 项目地址: https://gitcode.com/gh_mirrors/pythonsd/python-sdk

本指南以官方 Python SDK 的入口文档为核心,介绍 Model Context Protocol(MCP)的基本概念、SDK 的安装方式,并带你从零创建一个同时暴露工具(Tool)与资源模板(Resource Template)的 MCP 服务器,通过 mcp dev 与 MCP Inspector 完成交互式验证。读完本文,你将理解 SDK 如何从 Python 类型注解自动生成 JSON Schema 与协议处理代码,并掌握后续深入官方文档各章节的正确路径。

MCP 是什么,这个 SDK 能做什么

Model Context Protocol(MCP) 允许应用程序以标准化方式向 LLM 提供上下文,把"提供上下文"这件事与"和 LLM 交互"这件事彻底分离。本仓库 mcp 包正是这一协议官方的 Python 实现(文档面向当前稳定分支 v2,要求 Python 3.10+)。

使用该 SDK 可以:

  • 构建 MCP 服务器,向任意 MCP 主机(host)暴露工具(tools)、资源(resources)与提示词(prompts);
  • 构建 MCP 客户端,连接任意 MCP 服务器;
  • 支持全部标准传输方式:stdio、Streamable HTTP 与 SSE。

在 MCP 的术语体系中,host 是用户正在对话的 LLM 应用(如 Claude、IDE、Agent 运行时);client 寄生于 host 内部,负责说 MCP 协议的话,每个 host 对应一个连接就运行一个 client;server 正是你用本 SDK 构建的东西,它向客户端暴露能力,但从不直接与模型对话。SDK 同时提供了一个 Client 类——host 正是用同一个类通过 URL 或子进程方式访问服务器,你也可以用它来测试自己的服务器。

安装:两条命令二选一

# 方式一:使用 uv
uv add "mcp[cli]"

# 方式二:使用 pip
pip install "mcp[cli]"

[cli] 这个 extra 会额外安装 typer 与 python-dotenv,带来 mcp 命令行工具(mcp dev、mcp run、mcp install),开发阶段基本必需;部署时如不需要可以只装核心包。若在服务器上希望日志输出更美观,还可选用 mcp[rich] extra。

关于每个依赖的用途,官方安装文档 docs/get-started/installation.md 有完整说明,要点如下:

  • mcp-types:全部协议类型(请求、结果、内容块)以独立包形式随 SDK 同步版本发布,代码中通过 mcp.types 别名导入;
  • anyio:整个 SDK 的异步运行时,因此同时支持 asyncio 与 trio;
  • pydantic:所有 mcp.types 模型的基础,同时承担 schema 生成与校验;
  • httpx2、starlette、uvicorn、sse-starlette、python-multipart:HTTP 客户端与服务端传输层;
  • jsonschema、pyjwt[crypto]、opentelemetry-api 等:分别支撑结构化输出校验、OAuth 授权与可观测性。

第一个服务器:两个函数就是一个 MCP 服务器

创建文件 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},URI 中的 {name} 是函数参数,读取时按传入的名字返回问候语。

注意两个导入路径的区别:from mcp.server import MCPServer 用于服务器端,而客户端是 from mcp import Client——不存在 from mcp import MCPServer 这种写法。

类型注解即声明

这里没有任何一处"额外声明":工具的名称来自函数名,描述来自 docstring,参数 schema 完全来自 a: int, b: int 这类类型注解。从源码看,@mcp.tool() 装饰器最终调用 MCPServer.add_tool()(见 src/mcp/server/mcpserver/server.py),后者把函数交给 ToolManager 与 Tool.from_function 处理;核心的"函数签名 → pydantic 模型"转换发生在 func_metadata()(见 src/mcp/server/mcpserver/utilities/func_metadata.py):SDK 通过 inspect.signature 读取每个参数,调用 create_model 动态构造一个 addArguments 的 pydantic 模型,这个模型就是对外发布的 JSON Schema 来源。

同理,@mcp.resource("greeting://{name}") 装饰器会先解析 URI 模板(RFC 6570):URI 中含 {param} 即注册为模板资源,并校验模板变量与函数参数一一对应(见 src/mcp/server/mcpserver/server.py);若 URI 不含变量,则注册为静态资源,此时函数不允许再声明普通参数。

运行:mcp dev 与 MCP Inspector

uv run mcp dev server.py

这条命令会启动服务器,并打开 MCP Inspector——一个用于交互式探查服务器的可视化界面。运行后终端会打印一个 URL,用浏览器打开即可。

!!! note Inspector 是一个 Node.js 应用,因此 mcp dev 要求系统 PATH 中存在 npx。

从 CLI 源码(src/mcp/cli/cli.py)可以看到 mcp dev 的实际流程:先解析文件路径(支持 server.py:对象名 语法,默认按 mcp、server、app 三个常见变量名查找,且对象必须是 MCPServer 实例),导入模块并读取其 dependencies 属性,然后构造 uv run --with ... mcp run server.py 命令,最后通过 npx @modelcontextprotocol/inspector 拉起 Inspector 并传入该命令。CLI 还提供了 mcp run(直接以指定 transport 运行服务器)与 mcp install(安装到 Claude Desktop 应用)等子命令。

动手验证:调用工具、读取资源

调用工具 add

在 Inspector 中切换到 Tools 标签页,调用 add,参数填 a=1、b=2,返回结果:

3

Inspector 根据 a: int, b: int 的类型注解自动构建了表单——一个必填的整数字段 a,一个必填的整数字段 b。Claude 及其他所有 MCP host 也会以同样方式理解这个工具。

读取资源 greeting://World

切到 Resources 标签页,读取 greeting://World:

Hello, World!

由于 greeting://{name} 含参数,它属于"资源模板":在没有提供 name 之前,并不存在一个具体的可列举资源,所以它在 Inspector 中单独出现在 Resource Templates 列表下。

仓库中的等价验证

这套示例并非只停留在文档层面,仓库测试 tests/docs_src/test_index.py 用 Client(mcp) 把服务器对象直接交给内存客户端做了完全等价的断言:

async def test_add_tool() -> None:
    async with Client(mcp) as client:
        result = await client.call_tool("add", {"a": 1, "b": 2})
        # 断言返回 CallToolResult,文本内容为 "3"

async def test_greeting_resource_template() -> None:
    async with Client(mcp) as client:
        result = await client.read_resource("greeting://World")
        # 断言返回 TextResourceContents,文本为 "Hello, World!"

这正是一种不需要端口、不需要额外进程的测试方式:Client(server_object) 直接复用服务器实例,是后续编写服务器测试的起点(详见 docs/get-started/testing.md)。

回顾:SDK 替你写掉了什么

对照示例再看一遍,下面这些代码你一行都没有写:

  • 没有 JSON Schema。a: int, b: int 本身就是 schema——pydantic 模型在工具注册时即生成,并随 tools/list 响应发布给客户端;
  • 没有请求解析、序列化、校验代码。参数经 arg_model.model_validate() 校验后以 kwargs 形式传入函数,同步函数还会被调度到 worker 线程执行(见 src/mcp/server/mcpserver/utilities/func_metadata.py);
  • 完全没有协议处理。版本协商、JSON-RPC 帧封装、能力(capabilities)交换都发生在 mcp dev 与 Client 内部。

值得一提的还有 pre_parse_json:有些客户端(如 Claude Desktop)习惯把数组、对象以 JSON 字符串形式传入,SDK 会在校验前尝试自动解析这些字符串(见 src/mcp/server/mcpserver/utilities/func_metadata.py),进一步降低了与真实客户端对接时的摩擦。

你只写了两个带类型注解和 docstring 的 Python 函数,其余全部由 SDK 完成——这正是本 SDK 的设计初衷。如果你把服务器按其他 transport 跑起来(例如 uv run mcp run server.py --transport streamable-http),会发现服务器还会自动向客户端声明自己的能力(capabilities),包括 tools、resources、prompts 三组请求族的支持情况,客户端只会请求服务器声明过的能力。

下一步:围绕示例继续深入

本示例是整个官方文档的入口,后续按需选择路径即可:

【免费下载链接】python-sdk The official Python SDK for Model Context Protocol servers and clients 【免费下载链接】python-sdk 项目地址: https://gitcode.com/gh_mirrors/pythonsd/python-sdk

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

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

抵扣说明:

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

余额充值