MCP工具实战(二)-Python封装MCP工具与调试
上一篇我们先统一了认知:MCP 不是 CLI 的替代,而是让模型稳定调用工具的标准协议层。
这一篇开始进入实战,目标很明确:
- 用 Python 从 0 封装一个可调用的 MCP Tool
- 讲清楚需要安装哪些库,以及每个库的作用
- 演示本地调试流程(含
mcp dev) - 给出一份能直接排错的 Debug 清单
目录
- 实战目标与最终效果
- Python 需要哪些库
- 项目初始化与安装依赖
- 封装第一个 MCP 工具(完整代码)
- 如何运行 MCP 服务
- 如何用 mcp dev 调试
- Inspector 与常见调试策略
- 常见问题与排错清单
- 总结
1. 实战目标与最终效果
我们做一个最小可运行服务器,暴露 2 个工具:
search_blog_posts:根据关键词搜索文章(示例数据)get_post_detail:根据文章 id 获取详情
为什么用这个例子?
- 参数简单,便于看懂 schema 生成逻辑
- 返回结构清晰,便于你后续替换成真实数据库/搜索服务
- 覆盖了 MCP 工具最关键的输入、输出和错误处理
2. Python 需要哪些库
官方 Python SDK 的核心包是 mcp。
如果你要用命令行工具(比如 mcp dev、mcp install),需要安装带 cli 扩展的版本。
2.1 最小依赖
mcp[cli]- 提供 Python MCP SDK
- 提供
mcp命令行能力(mcp dev、mcp run、mcp install)
2.2 常见业务依赖(按需)
httpx:如果你的工具要请求外部 HTTP APIpydantic:复杂参数建模与校验时很好用(可选)python-dotenv:本地读取.env配置(可选)
如果你只是做第一个 demo,
mcp[cli]就够了。
3. 项目初始化与安装依赖
这里用 uv 演示(官方文档也大量使用 uv)。你也可以换成 pip。
1 | # 1) 新建项目目录 |
如果你习惯 pip:
1 | pip install "mcp[cli]" |
4. 封装第一个 MCP 工具(完整代码)
创建 server.py:
1 | from mcp.server.fastmcp import FastMCP |
这段代码的关键点
FastMCP("blog-tools")定义了 MCP 服务名称。@mcp.tool()把 Python 函数注册成 MCP 工具。- 函数参数类型提示 + docstring,会被用于生成工具描述和参数约束。
- 业务错误要明确抛出,让客户端能看到清晰失败原因。
5. 如何运行 MCP 服务
有两种常见方式。
5.1 直接运行 Python 文件
1 | python server.py |
5.2 使用 MCP CLI 运行
1 | uv run mcp run server.py |
实战建议:本地调试优先
mcp dev,正式跑通后再接入你的 MCP 客户端(如 Claude Desktop、IDE Agent)。
6. 如何用 mcp dev 调试
这是 Python MCP 开发里最好用的命令之一。
6.1 基本用法
1 | uv run mcp dev server.py |
这条命令会帮助你快速进入调试流程(通常配合 Inspector 使用),你可以直观看到:
- 服务是否正常启动
- 工具是否被正确发现
- 参数 schema 是否符合预期
- 调用结果与错误输出是否清晰
6.2 常见进阶参数
1 | # 运行时临时附加依赖 |
6.3 一个容易忽略的限制
uv run mcp run / uv run mcp dev 的便捷能力,主要针对 FastMCP 方式。
如果你使用的是更底层的 server 写法,这两个命令未必适用,建议直接按底层服务方式运行。
7. Inspector 与常见调试策略
除了 mcp dev,建议你熟悉 MCP Inspector。
7.1 Inspector 快速启动
1 | npx @modelcontextprotocol/inspector <command> |
本地 Python 服务常见形式(示意):
1 | npx @modelcontextprotocol/inspector \ |
7.2 在 Inspector 里重点看什么
- Tools 列表
- 工具名是否正确
- 描述是否清晰
- 输入 schema
- 必填字段是否正确
- 类型是否符合预期(int/str/bool)
- 执行结果
- 正常返回结构是否稳定
- 异常时是否给出可理解的错误信息
- 通知与日志
- 是否有初始化失败、参数错误等信号
8. 常见问题与排错清单
这部分是实战里最省时间的。
8.1 服务启动了,但客户端看不到工具
优先检查:
- 你是否真的加了
@mcp.tool() - 是否启动了正确的
server.py - 客户端配置里的
command和args是否对应当前环境 - 改完配置后,客户端是否“完全重启”
8.2 工具调用失败但没有明显报错
排查顺序:
- 看客户端日志(如 Claude Desktop 日志)
- 看 Inspector 的通知流和调用结果
- 检查参数类型(例如本该 int 却传了字符串)
- 检查函数内部是否吞掉了异常
8.3 stdio 模式下最容易犯的错误
不要往 stdout 打调试日志。
stdio 传输依赖标准输出承载协议消息;你在 stdout 里随手 print,会污染协议流。
调试日志应写到 stderr,或使用日志能力发送结构化日志。
8.4 环境变量问题(非常高频)
如果你用 API Key / DB URL:
- 不要假设客户端会继承你终端全部环境变量
- 在客户端配置中显式传
env - 路径尽量用绝对路径,避免工作目录差异导致读取失败
9. 总结
到这里,你已经完成了 MCP 工具封装的第一步:
- 用
FastMCP把 Python 函数变成了可调用工具 - 明确了 Python 依赖:
mcp[cli]是核心 - 掌握了本地调试主线:
mcp dev+ Inspector + 日志排查
下一篇我会专门写配置与工程化:
MCP 服务配置参数逐项解释(command / args / env / 超时 / 重试 / 安全)+ 一套可复用模板。