先给结论
MCP 调试常见问题里,八成集中在三件事:路径没写绝对路径、环境变量没传进去、往 stdout 打了日志污染了协议流。剩下的两成是协议版本与能力声明不匹配。官方给出的第一原则很明确:先用 MCP Inspector 单独测通 server,再接进客户端——在客户端里调试等于蒙眼找针。
问题一:server 起不来
典型表现是客户端显示已连接但立刻断开,或直接报 spawn 失败。逐项排查:
- 路径问题:客户端启动 stdio server 时的工作目录是不确定的(macOS 上可能是
/)。配置里必须用绝对路径,不要用./data这种相对路径。 - 可执行文件找不到:
command写python/node时,客户端可能拿不到你以为的那个解释器,直接写完整路径最稳。 - 权限问题:脚本没有执行权限、虚拟环境未激活。
{
"mcpServers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem",
"/Users/username/data"]
}
}
}
问题二:环境变量没生效
stdio 方式下,server 只继承客户端给的一小部分环境变量,.env 不会自动加载。密钥必须显式写进配置的 env 字段,或者在 Inspector 的连接面板里填。
{
"mcpServers": {
"myserver": {
"command": "mcp-server-myapp",
"env": { "MYAPP_API_KEY": "some_key" }
}
}
}
问题三:往 stdout 打了日志(stdio 的隐形杀手)
stdio 传输用 stdout 传 JSON-RPC 消息。任何 print / console.log 都会插进消息流,导致解析失败或进程挂死。正确做法是日志一律走 stderr,或用协议提供的日志通知。
import logging
logger = logging.getLogger(__name__)
@mcp.tool()
async def fetch_report(report_id: str) -> str:
"""Fetch a report by id."""
logger.info("Fetching report %s", report_id) # 走 stderr
return f"Report {report_id} is ready."
注意:基于 notifications/message 的日志机制在新版协议中已标记废弃,新代码优先用 stderr 或 OpenTelemetry 。
问题四:协议版本与能力声明不匹配
- 版本不兼容会拿到
UnsupportedProtocolVersionError (-32022),错误信息里会列出 server 支持的版本——用它来对齐客户端。 - 请求缺少必需字段会返回
-32602 (Invalid params):每个请求都要带协议版本与客户端能力声明。 - server 需要某项客户端能力(如 elicitation)而请求没声明,会返回
MissingRequiredClientCapabilityError (-32021),并指明缺哪个。
排查手段:调用 server/discover 看版本支持,同时检查请求里声明的能力是否与 server 期望一致。
标准排查流程
- 先在终端单独运行 server,确认它自己能启动、没有运行时报错。
- 用最新版 Inspector 连接(npx @modelcontextprotocol/inspector),看握手是否成功、工具列表是否齐全。
- 在 Inspector 里逐个测工具:正常参数 → 边界值 → 非法值,每个至少三个用例。
- 看通知面板的完整请求响应,确认参数传递与返回格式符合 inputSchema 。
- 做一次断线重连,确认 server 能正确处理重复初始化。
- Inspector 全绿后再接进客户端;仍失败则去查客户端日志(Claude Desktop 在 macOS 的 ~/Library/Logs/Claude/、 Windows 的 %APPDATA%\Claude\logs)。
常见报错速查表
| 症状 | 最可能原因 | 处理 |
|---|---|---|
| 连接后立刻断开 | server 启动崩溃 | 终端单独跑一遍看报错 |
| 工具找不到 | 未声明 tools 能力 | 检查 ServerCapabilities 与注册代码 |
| Invalid params | 参数与 inputSchema 不符 | 收紧 schema 或修正调用 |
| 一直挂起无响应 | 往 stdout 打了日志 | 改走 stderr |
| 版本不匹配 | 客户端/服务端协议版本差异 | 用 discover 对齐版本 |
| 配置改了没生效 | 客户端未重启 | 保存后完全退出重启 |
把日志做对,胜过事后乱猜
官方建议至少记录五类事件:启动步骤、资源访问、工具执行、错误条件、性能指标。日志用标准的 RFC 5424 八个级别,客户端通过请求里的日志级别字段按需订阅。 stdio server 打到 stderr 会被宿主自动捕获,这是最省事的路径;走 HTTP 传输时 stderr 不会被客户端收集,需要自己的日志聚合或 OpenTelemetry 。
Inspector 连不上,一定是 server 的问题吗?
为什么在 Inspector 里正常,接到客户端就失败?
通知面板刷得太快看不清怎么办?
HTTP 传输的 server 怎么调试?
三句话记住 MCP 调试
相关阅读:Claude Desktop 配置 MCP 教程、MCP Server 自己搭建教程、MCP 和 Function Calling 的区别。参考来源:Model Context Protocol 官方 Debugging 文档。









评论 (0)