python-sdk 入门指南:用 Model Context Protocol 三步写出你的第一个 MCP Server

python-sdk 入门指南:用 Model Context Protocol 三步写出你的第一个 MCP Server 人工智能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 for Model Context ProtocolMCP的 first steps 入门文档展开逐步讲解如何用三个装饰器在同一个 server 中同时暴露 tools、resources、prompts 三类能力并借助 MCP Inspector 与内置Client完成交互验证。读完本文你将掌握 MCP 中 host / client / server 的角色划分、三大原语primitives的控制权差异、capabilities 声明机制以及一套从写代码到测试验证的完整实战流程。角色速览host、client 与 serverMCP 的世界里只有三个词后续每一篇文档都会用到先一次性说清host是 LLM 应用本身Claude、某个 IDE、某个 agent runtime。它是用户直接对话的对象。client寄生在 host 内部负责说 MCP 这门语言。host 每连接一个 server就为它运行一个 client。server是你用这套 SDK 构建的东西它向 client 暴露各种能力永远不会直接与 model 对话。server 由你来写host 是别人的产品。SDK 同时为你提供了Client类——这正是 host 用来通过 URL 连接 server、或把 server 作为子进程拉起时所用的同一个类。它稍后会出现在本页的实战环节中也是你日后测试自己 server 的核心工具。有一点需要特别注意SDK 的两半有着两个不同的导入路径。官方文档明确提醒正确的是from mcp import Client和from mcp.server import MCPServer并不存在from mcp import MCPServer这种写法。这一点可以在 src/mcp/client/init.py 与 src/mcp/server/mcpserver/server.py 的导出结构中相互印证。三大原语谁决定使用它一个 server 恰好只暴露三类东西区分它们的唯一标准是由谁决定去使用它原语Primitive由谁控制它是什么典型例子Toolsmodelmodel 为了执行某个动作而调用的函数API 调用、数据库写入Resourcesapplicationhost 加载进 model 上下文的数据某文件的内容、某 API 的响应Promptsuser用户按名称调用的可复用消息模板斜杠命令、菜单项“由谁控制”是整个划分的全部意义所在tool 之所以执行是因为model决定调用它resource 之所以被附加是因为application判断 model 需要它prompt 之所以运行是因为user选中了它。如果你写过 web API大部分直觉其实已经就位resource 相当于一次GET加载数据、不改变任何东西tool 相当于一次POST做事情、可能产生副作用。prompt 在 HTTP 世界里没有对应物它更接近用户按名称运行的已保存查询。一个 server三类能力三个装饰器搞定一切下面这个示例来自仓库中的 docs_src/first_steps/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 fHello, {name}! mcp.prompt() def summarize(text: str) - str: Summarize a piece of text in one sentence. return fSummarize the following text in one sentence:\n\n{text}逐行拆解三个装饰器做了什么mcp.tool()把add变成一个toolmcp.resource(greeting://{name})把greeting变成一个resource templateURI 中的{name}正是函数的参数mcp.prompt()把summarize变成一个prompt它返回的字符串会成为一条 user message。其余的一切——名字、描述、参数 schema——SDK 全部从函数本身读取函数名、docstring、类型注解。你没有单独声明任何一项。从源码看装饰器的底层注册从源码结构看这三个装饰器最终都汇入MCPServer内部三个管理器。在 src/mcp/server/mcpserver/server.py 中MCPServer类的构造函数第 157 行起会创建ToolManager、ResourceManager与PromptManager见第 200–204 行随后通过Server把这些请求家族逐一绑定到处理函数上tools/list、tools/call、resources/list、resources/read、resources/templates/list、prompts/list、prompts/get见第 218–224 行。装饰器方法本身也支持大量可选项。例如tool()方法第 660 行起接受name、title、description、annotations、icons、meta、structured_output等参数其中structured_output为None时会根据函数的返回类型注解自动探测输出是结构化还是非结构化resource()方法第 779 行起还额外支持mime_type、security仅对模板资源生效的路径安全策略等参数。不过对于入门示例什么都不传即可默认值就是最常用的行为。一个值得注意的细节resource装饰器在 源码第 850–855 行 会检查你是否忘了调用它——如果直接写resource而不是resource(uri)会抛出带明确提示的TypeError。同理tool()忘记带括号也会得到 Did you forget to call it? 的报错第 709–713 行。URI 模板与函数参数的强校验resource()装饰器会在装饰时机而非运行时机就解析 URI 模板并做一次严格的参数匹配校验。根据 src/mcp/server/mcpserver/server.py 的实现URI 中是否存在变量{param}纯粹决定这是模板资源还是静态资源模板资源要求 URI 变量集合与函数参数集合完全一致否则抛出ValueError例如{name}与{name, extra}不匹配若使用{?...}/{...}这类查询变量client 在请求时可以省略被绑定的 Python 参数必须声明默认值否则同样会在装饰阶段报错。这套「装饰时尽早失败」的设计让模板书写错误在启动瞬间就能暴露而不是等到第一次请求才变成模糊的内部错误。动手试试用 MCP Inspector 跑起来用 MCP Inspector 运行上面的 serveruv run mcp dev server.py打开它打印出来的 URL。Inspector 为每个原语准备了一个 tab按顺序逐一体验即可。mcp dev是 SDK 命令行工具见 src/mcp/cli/cli.py提供的开发子命令它会把你的 server 与官方 Inspector 界面连接起来。Tools表单即 schema会看到一个条目add描述为Add two numbers.直接来自 docstring。表单里有一个必填的整数字段a和另一个b。填入 1 和 2点击调用结果是3。表单完全是从a: int, b: int自动生成的——这正是函数类型注解推导出的 JSON Schema。Inspector 这么做其他任何 client 也都是这么做。仓库中的 tests/docs_src/test_first_steps.py 用快照精确验证了这一点add的input_schema是{type: object, properties: {a: {title: A, type: integer}, b: {title: B, type: integer}}, required: [a, b], title: addArguments}而add(1, 2)的返回内容就是文本3。Resources模板与具体资源的区别Resources列表是空的。greeting出现在Resource Templates之下原因正如文档所言greeting://{name}带有参数在有人提供name之前根本不存在一个可以列出的具体 resource。测试 test_templated_resource_is_a_template_not_a_resource 验证的正是这一点——具体资源列表为空。给它传入World并读取Hello, World!读取返回的TextResourceContents携带urigreeting://World、mime_typetext/plain与文本内容见测试中的快照断言。也就是说模板在没有参数时只是「可实例化的原型」填上参数后才成为可读取的具体资源。Prompts不过是生成消息的函数同样只有一个条目summarize带一个必填的text参数。输入一些文本并获取它你会收到一条role: user的消息content 正是渲染后的字符串。prompt 的全部本质就是一个用来构建 messages 的函数。测试验证了渲染结果传入MCP is a protocol.返回的消息文本是Summarize the following text in one sentence:\n\nMCP is a protocol.。顺带说明Inspector 是通过stdiotransport 运行你的 server 的——这只是 MCP server 能说的传输协议之一。现阶段你不需要做选择运行 server 的细节见 运行你的 server。Capabilitiesclient 凭什么知道该问什么你在 Inspector 里看到了三个 tab它怎么知道该有三个当 client 连接时server 会声明自己的capabilities它愿意应答哪些请求家族。client 依据这份声明决定自己该请求什么。你从未手写过这份声明——MCPServer替你声明好了。亲自看一眼。在一个终端中让server.py以 HTTP 方式运行uv run mcp run server.py --transport streamable-http再从另一个终端用 client 连接它import anyio from mcp import Client async def main() - None: async with Client(http://localhost:8000/mcp) as client: print(client.server_capabilities.model_dump(exclude_noneTrue)) if __name__ __main__: anyio.run(main)python client.py输出{prompts: {list_changed: True}, resources: {subscribe: True, list_changed: True}, tools: {list_changed: True}}这字典就是你的 server 对外声明的capabilities也是每个连接的 client 最先获知的信息。它对应的请求权限如下Capabilityclient 现在可以调用toolstools/list、tools/callresourcesresources/list、resources/templates/list、resources/readpromptsprompts/list、prompts/getMCPServer同时服务全部三类原语因此这三项永远会被声明。这一点在 tests/docs_src/test_first_steps.py 中被验证得相当彻底测试不仅断言本例的输出字典与快照完全一致还特别构造了一个什么都没注册的空MCPServer(Empty)其 capabilities 与完整示例完全相等——也就是说三大原语的 capability 与注册内容无关是MCPServer无条件提供的。注意什么「不在」里面观察输出中缺什么没有completions。completions为 resource templates 与 prompts 提供参数自动补全需要你亲手写一个 handler本 server 没有于是该 capability 缺席行为得体的 client 也就不会去请求。这就是所有可选能力的统一规则注册了对应功能capability 就出现不注册client 就假装它不存在。关于如何补上这块拼图Completions 一文给出了完整证明。从 src/mcp/server/mcpserver/server.py 可以看到mcp.completion()装饰器会为completion/complete请求注册处理器handler 接收refPromptReference 或 ResourceTemplateReference、argument与context返回补全候选项。上面那个client.py是一个完整的 MCP clientClient 文档是它的主场。而在测试中你可以跳过终端和端口直接把 server 对象交给ClientClient(mcp)。这同样有专文讲解Testing。正是这种「进程内直连」的方式让 tests/docs_src/test_first_steps.py 里每一个断言都以最直接的方式对应到文档中的每一步操作——文档的每一处声称都有真实测试背书。你「没有写」的东西回头审视这一页你只写了三个短小的 Python 函数但你没有写JSON Schema。a: int, b: int就是add的 schemaSDK 根据类型注解自动生成。请求处理器。tools/list、resources/read、prompts/get……全部由 SDK 替你 serve。capability 声明。MCPServer为你构建好了。协议的任何一行。版本协商version negotiation、JSON-RPC 帧封装framing、capability 交换capability exchange——这一切都发生在mcp dev和client.py的内部你从头到尾都没看见。这个「写一个函数 / 得到整套协议」的比例正是这套 SDK 存在的全部意义。小结host是 LLM 应用client是它里面说 MCP 的那一半server是你构建的东西。tools 由model控制resources 由application控制prompts 由user控制。每个原语一个装饰器mcp.tool()、mcp.resource(uri)、mcp.prompt()名称、描述与 schema 全部来自函数本身。带{param}的 URI 会生成 resourcetemplate与具体 resources 分开列出。server 的capabilities由 SDK 替你声明client 只会请求 server 声明过的内容。Client(http://localhost:8000/mcp)连接你正在运行的 server把 server 对象直接交给它——Client(mcp)——从第一天起它就是你的测试框架。下一步接下来请阅读 连接真实 host把同一个 server 真正跑进 Claude Desktop 或某个 IDE 里。然后是 Testing一页纸、一个内存 client从此你再也不用靠猜来判断代码是否工作。之后每个原语都会有专属页面从由 model 驱动的那一个开始Tools。赞分享人工智能MCP 服务MCP Clients【免费下载链接】python-sdkThe official Python SDK for Model Context Protocol servers and clients项目地址https://gitcode.com/gh_mirrors/pythonsd/python-sdk点击查看免费下载相关推荐如何快速掌握 Model Context Protocol Python SDK初学者完整指南如何快速掌握 Model Context Protocol Python SDK初学者完整指南 Model Context Protocol Python S人工智能MCP 服务MCP ClientsMaestro故障排除手册常见问题与解决方案清单Maestro故障排除手册常见问题与解决方案清单 Maestro 是一款 AI 智能体编排指挥中心Agent Orchestration Command C桌面应用AI AgentAgent 编排交互助手人工智能python-sdkMCP Python SDK入门指南从零搭建、运行与测试你的第一个 MCP Serverpython sdkMCP Python SDK入门指南从零搭建、运行与测试你的第一个 MCP Server 本文是 MCPModel Context人工智能MCP 服务MCP Clients创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考