别再手写JSON Schema了!用Python SDK,三步搭建你的MCP Server
如果你还在手写复杂的JSON Schema来定义工具,那你可能走了一条弯路。今天聊聊怎么用MCP官方Python SDK,把"苦力活"变成"写函数"。
先说结论:MCP Server没你想的那么难
很多开发者第一次听到"MCP Server",脑子里浮现的画面是——一堆协议文档、复杂的JSON结构、看不到头的调试过程。
但实际上呢?
用官方Python SDK,你定义一个工具,和写一个普通Python函数几乎没有区别。装饰器一挂,类型注解一写,SDK自动帮你把JSON Schema生成好,Claude直接就能调用。
今天我们用一个文档管理服务器的例子来走一遍完整流程。这个服务器只做两件事:读文档和改文档。功能虽然简单,但五脏俱全,足以让你理解MCP Server的核心套路。
第一步:一行代码,启动服务器
安装好mcp SDK之后,创建一个MCP Server只需要一行:
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("DocumentMCP", log_level="ERROR")
FastMCP是SDK提供的快速启动类。第一个参数是你的服务器名称,log_level控制日志输出等级。就这么简单,服务器的骨架就搭好了。
接下来,我们需要准备一些"数据"。在这个示例中,所有文档都存在内存里,用一个字典来模拟:
docs = {
"deposition.md": "This deposition covers the testimony of Angela Smith, P.E.",
"report.pdf": "The report details the state of a 20m condenser tower.",
"financials.docx": "These financials outline the project's budget and expenditures",
"outlook.pdf": "This document presents the projected future performance of the system",
"plan.md": "The plan outlines the steps for the project's implementation.",
"spec.txt": "These specifications define the technical requirements for the equipment"
}
键是文档ID,值是文档内容。生产环境中,你可以替换成数据库查询、文件系统读取,甚至API调用——数据从哪来不重要,重要的是工具接口怎么定义。
第二步:用装饰器定义工具——读文档
传统方式下,你需要手写一段JSON Schema告诉Claude:"这个工具叫什么名字、接受什么参数、每个参数是什么类型、什么含义。"
SDK的做法是:你写Python函数,它帮你翻译成Schema。
来看"读文档"工具的完整实现:
@mcp.tool(
name="read_doc_contents",
description="Read the contents of a document and return it as a string."
)
def read_document(
doc_id: str = Field(description="Id of the document to read")
):
if doc_id not in docs:
raise ValueError(f"Doc with id {doc_id} not found")
return docs[doc_id]
逐行拆解一下:
@mcp.tool装饰器:告诉SDK"这是一个工具",同时指定工具名称和功能描述。Claude在选择工具时,会参考这个description来判断该不该调用它。- 函数参数 + 类型注解:
doc_id: str告诉SDK这个参数是字符串类型。SDK会自动把它写进JSON Schema。 Field(description=...):来自Pydantic,给参数加上自然语言描述。Claude读到这段描述后,就知道应该传什么值进来。- 错误处理:找不到文档时抛出
ValueError,MCP协议会把异常信息传回给Claude,Claude可以据此调整策略。
💡 划重点:你不需要写一行JSON,SDK通过类型注解和Field描述,自动生成了Claude能理解的完整工具规范。
第三步:再来一个工具——改文档
光能读不能改,那就少了一半功能。我们再定义一个"查找替换"工具:
@mcp.tool(
name="edit_document",
description="Edit a document by replacing a string in the documents content with a new string."
)
def edit_document(
doc_id: str = Field(description="Id of the document that will be edited"),
old_str: str = Field(description="The text to replace. Must match exactly, including whitespace."),
new_str: str = Field(description="The new text to insert in place of the old text.")
):
if doc_id not in docs:
raise ValueError(f"Doc with id {doc_id} not found")
docs[doc_id] = docs[doc_id].replace(old_str, new_str)
这个工具接收三个参数:文档ID、要替换的旧文本、替换后的新文本。逻辑非常直白——找到文档,执行字符串替换,完事。
注意old_str的描述里特别强调了"Must match exactly, including whitespace"。这类细节非常关键。Claude在调用工具时,会严格参考参数描述来构造输入。描述写得越精确,Claude犯错的概率就越低。
为什么SDK方案值得用?
把上面的流程总结一下,SDK方案的优势可以归纳为以下几点:
🔧 告别手写Schema 不用再对照JSON Schema规范一字一句地拼字段了。Python类型注解就是你的Schema来源。
✅ 自动参数校验 类型不对?缺少必填字段?SDK在参数进入函数之前就会拦截,省去了大量防御性代码。
📝 描述即文档
Field(description=...) 既是给Claude看的使用说明,也是给人看的参数文档。一处维护,两处受益。
⚠️ 异常处理自然融入
Python的raise语句直接变成工具的错误响应,不需要额外封装错误码和错误信息。
🚀 注册即生效 装饰器挂上去,工具就注册了。不需要额外调用注册函数,不需要维护工具列表。
写在最后
MCP的设计哲学其实很清晰:让AI能调用外部能力,同时让开发者定义这些能力的门槛尽可能低。
Python SDK把这个理念落了地。在它的帮助下,搭建一个MCP Server的核心工作量,从"理解协议 → 编写Schema → 处理通信",简化成了"写一个带装饰器的Python函数"。
今天的文档管理示例只是一个起点。你完全可以在此基础上扩展——加上文档列表查询、权限控制、版本管理,甚至接入真实的文件系统或数据库。
工具的边界,取决于你的想象力。而SDK负责的,是把你的想象力高效地翻译成Claude能理解的语言。
如果你正准备动手搭一个MCP Server,不妨从这个例子开始。跑通一个最小可用版本,然后一步步往上加功能。毕竟,写代码最好的方式,永远是先让它跑起来。
你在用MCP做什么有趣的项目?欢迎在评论区聊聊。
官方教程地址:https://anthropic.skilljar.com/
目前15门课,从零基础的Claude怎么用,到硬核的API开发、代码集成和MCP协议全都有。
之前的文章如下:
Claude Code 官方教程来啦!手把手带你学习Claude Code(一)
Claude Code 官方教程来啦!手把手带你学习Claude Code(二)掌握AI的四把钥匙:让你从"会用AI"到"用好AI"
