MCP 入门:用 Python 从零写 MCP 服务器和客户端
一句话
Model Context Protocol(MCP,模型上下文协议)是一个开放协议,规定 AI 应用怎样连接外部工具和数据。有了它,工具的定义和执行从你的应用里拆出去,交给专门的 MCP 服务器;任何支持 MCP 的客户端都能直接用。这门课用 Python SDK 做一个文档管理服务器和配套客户端,讲透 3 种原语:工具、资源、提示,以及各自由谁控制。
这篇导读覆盖的课程
- Introduction to Model Context Protocol —— 4 个单元,含期末测评
课程结构
- 导论
- MCP 解决什么问题;MCP 客户端是什么。
- 动手写 MCP 服务器
- 项目搭建;用装饰器定义工具;用服务器检查器(Inspector)调试。
- 连接 MCP 客户端
- 实现客户端;定义和读取资源;定义和使用提示。
- 测评与总结
- 期末测评和 MCP 回顾。
精华:这门课真正要你带走的东西
MCP 解决“每个应用都要重写一遍集成”的问题。没有 MCP 时,你想让 Claude 操作 GitHub,就得自己写工具定义、自己调用 GitHub API、自己维护。别的应用也要接 GitHub,再写一遍。有了 MCP,GitHub 集成写成一个 MCP 服务器,所有支持 MCP 的客户端(Claude Code、Claude 桌面版、你自己的应用)都能直接连上。
3 个角色。宿主(host)是用户直接使用的 AI 应用;客户端(client)在宿主内部,负责和某一个服务器保持连接;服务器(server)对外提供工具、资源和提示。协议与传输方式无关:同一套消息可以走本地标准输入输出,也可以走 HTTP(传输细节在第 13 篇)。
用装饰器写工具,不用手写 JSON Schema。Python SDK 根据函数签名、类型标注和字段描述自动生成工具定义:
from mcp.server.fastmcp import FastMCP
from pydantic import Field
mcp = FastMCP("docs")
docs = {"plan.md": "Q4 计划草稿"}
@mcp.tool()
def read_doc(doc_id: str = Field(description="文档 ID,例如 plan.md")) -> str:
"""读取一份文档的全文。"""
return docs[doc_id]
@mcp.resource("docs://list")
def list_docs() -> list[str]:
return list(docs)
@mcp.prompt()
def summarize(doc_id: str) -> str:
return f"用 3 条要点总结文档 {doc_id}。"
if __name__ == "__main__":
mcp.run()
3 种原语,按“谁来控制”区分。这是本课最重要的一张表:
- 工具(tools)—— 模型控制。Claude 自己决定何时调用。用于执行动作:查询、写入、调用接口。
- 资源(resources)—— 应用控制。宿主应用决定何时读取,再放进上下文。用于提供只读数据,例如文档列表、配置。资源有固定 URI(如
docs://list),也可以用带参数的 URI 模板(如docs://{doc_id})。 - 提示(prompts)—— 用户控制。用户主动选择使用,例如在界面里点一个“格式化文档”命令。用于封装高质量的预设指令。
判断要用哪种原语时问一句:这件事该由谁来发起?
先用检查器调通,再接客户端。SDK 自带的 MCP Inspector 在浏览器里打开,可以直接列出服务器的工具、资源和提示,手动调用并查看返回。服务器在检查器里跑通了,再写客户端,排错范围会小很多。客户端这边,课程演示了怎样列出工具交给 Claude、怎样读取资源(按 MIME 类型处理 JSON 和纯文本)、怎样实现输入“@文档名”自动补全并把文档注入对话。
关键概念
- MCP(Model Context Protocol)
- AI 应用连接外部工具和数据的开放协议,基于 JSON-RPC 消息。
- 宿主 / 客户端 / 服务器
- 宿主是 AI 应用;客户端在宿主内部连接单个服务器;服务器提供工具、资源和提示。
- 工具(tools)
- 由模型决定何时调用的函数,用来执行动作。
- 资源(resources)
- 由应用决定何时读取的只读数据,通过 URI 标识,可以是固定 URI 或 URI 模板。
- 提示(prompts)
- 由用户主动选择的预设指令模板,可以带参数。
- MCP Inspector
- 官方调试工具,在浏览器里测试服务器的工具、资源和提示。
- FastMCP
- Python SDK 中的高层接口,用装饰器定义工具、资源和提示。
学前准备
- 能用 Python 写函数和类,了解类型标注。
- 了解 JSON 和 HTTP 请求—响应的基本概念。
- 建议先学第 11 篇的工具调用部分,理解工具定义和工具结果。
动手练一遍
- 跑起服务器:安装 Python SDK,把上面的示例保存为
server.py,用 Inspector 打开。分别调用工具、读取资源、获取提示。 - 加一个写工具:增加
edit_doc(doc_id, old, new)工具,做字符串替换。在 Inspector 里测试文档不存在时的报错。 - 加资源模板:增加
docs://{doc_id}资源,返回单篇文档。 - 接进 Claude Code:用
claude mcp add把服务器加进 Claude Code,让 Claude “把 plan.md 里的 Q4 改成 Q1”,观察它调用了哪个工具。 - 分类练习:为你工作中的一个系统(例如工单系统)列出 6 项能力,逐项判断应做成工具、资源还是提示,并写一句理由。
容易卡住的地方
- 所有东西都做成工具。只读数据由应用决定何时读取更合适,做成资源。
- 工具描述和参数描述写得太简略。Claude 靠描述决定何时调用、怎样传参。
- 跳过 Inspector 直接接客户端。出错时分不清是服务器还是客户端的问题。
- 工具出错时直接抛异常没有说明。返回清楚的错误信息,Claude 才能自我纠正。
- 以为 MCP 只能给 Claude 用。它是开放协议,其他支持 MCP 的应用也能连接。
延伸阅读
- MCP 官方网站 —— 协议规范、SDK 和教程(英文)
- MCP Python SDK —— 本课使用的 SDK 源码和示例
- Claude Code 文档:连接 MCP —— 在 Claude Code 中添加和管理 MCP 服务器(英文)
- 下一篇:MCP 进阶 —— 采样、通知、根目录和传输方式