MCP 调试全指南:Inspector、stdio 日志、路径、环境变量与协议错误
MCP 调试全指南:Inspector、stdio 日志、路径、环境变量与协议错误
MCP 从入门到工程实践系列,第 9 篇,共 9 篇。
本文以 MCP2026-07-28为版本基线;涉及旧版 Wire Format 的差异会明确说明。
MCP 出错时,最常见的做法是直接怀疑“模型为什么没调用 Tool”。但模型其实位于很靠后的环节。
一条完整链路可能包含:
Host 启动 Server Process ↓ 建立 stdio / HTTP Transport ↓ 交换 MCP Message ↓ 列出 Tool / Resource / Prompt ↓ 模型选择能力 ↓ Host 校验权限并调用 ↓ Server 执行业务代码 ↓ 访问外部 API / 文件 / 数据库 ↓ Result 返回模型任何一层都可能失败。有效调试的核心不是“多看几眼代码”,而是把链路分层隔离。
一、MCP 调试的第一原则:从内到外
建议固定按以下顺序:
1. Server 能否独立启动 ↓ 2. Transport 能否通信 ↓ 3. MCP 能力能否列出 ↓ 4. Tool / Resource / Prompt 能否单独操作 ↓ 5. 业务依赖是否正常 ↓ 6. 接入目标 Host 后是否正常 ↓ 7. 模型是否选择正确如果 Server 连tools/list都不能返回,就没有必要先研究 Prompt 或模型推理。
二、三类核心调试工具
1. MCP Inspector
Inspector 可以理解为 MCP 世界的 Postman:
开发者 ↓ MCP Inspector ↓ MCP Server它绕开模型和目标 Host,可以:
- 连接 stdio 或 Streamable HTTP Server;
- 查看 Tool、Resource、Prompt;
- 检查 Name、Description 和 Schema;
- 手工填写 Arguments;
- 调用 Tool 并查看 Result;
- 观察 Notification 和协议消息。
诊断价值非常高:
| 结果 | 下一步 |
|---|---|
| Inspector 也失败 | 查 Server、Transport、配置、权限、依赖 |
| Inspector 成功,目标 Host 失败 | 查 Host 配置、版本、Cache、Capability、Permission |
| Inspector 手工调用成功,模型不调用 | 查 Tool Description、Schema、模型 Context 和策略 |
因此 Inspector 应是开发期第一个独立验证工具。
2. Server Logging
Server Log 要回答:
- 是否启动;
- 收到哪个 Method;
- Tool Name 与 Request/Trace ID 是什么;
- 参数校验到哪一步;
- 外部 API 返回什么 Status;
- 耗时和 Result Size;
- 抛出了什么 Exception。
日志的目标不是“越多越好”,而是让一次 Request 能被从入口追到出口。
3. Client Developer Tools
不同 Host 可能提供:
- Server 连接状态;
- 已发现 Tool;
- 子进程 Exit Code;
- Client Log;
- Console;
- Network Panel;
- Permission / Approval 记录。
这些 UI 属于具体 Client 实现,不是 MCP Protocol 强制要求。
三、stdio 最重要的规则:stdout 只传协议
stdio Transport 的三个流:
stdin = Client → Server 的 MCP 消息 stdout = Server → Client 的 MCP 消息 stderr = Server 的普通开发日志正常 stdout 可能包含:
{"jsonrpc":"2.0","id":1,"result":{"tools":[]}}如果 Server 写:
print("Server started!")Client 实际可能读到:
Server started! {"jsonrpc":"2.0","id":1,"result":{"tools":[]}}第一行不是合法 JSON-RPC Message,可能导致:
- Invalid JSON;
- Unexpected Token;
- Protocol Parse Error;
- Server Disconnected。
正确方式:
importsysprint("Server started!",file=sys.stderr)或配置 Pythonlogging写入 stderr。
这条规则也适用于依赖 Library:如果某个 Library 在 Import 或启动时向 stdout 打 Banner,一样会污染协议。
四、stderr 与协议 Logging 不是一回事
stderr
stderr 是操作系统进程流:
- 不经过 MCP Protocol;
- 不需要 JSON-RPC;
- 适合本地 stdio Server 的启动和错误日志;
- 通常被 Host 重定向到自己的 Log File。
旧式协议 Logging
旧设计可通过 Notification 传日志:
{"jsonrpc":"2.0","method":"notifications/message","params":{"level":"info","data":"Tool started"}}它没有id,因为 JSON-RPC Notification 不要求 Response。
在2026-07-28中,核心协议 Logging 已被标记为 deprecated。新实现优先使用:
- stdio:stderr;
- 生产环境:Server Logging Platform 与 OpenTelemetry。
兼容旧 Logging 时还要注意版本语义:新版本兼容边界要求 Client 在每个 Request 的_meta中明确 Opt-in:
{"_meta":{"io.modelcontextprotocol/logLevel":"info"}}这不同于更早版本的全局logging/setLevel。看到旧教程时,不能直接把 Wire Format 复制到当前协议。
五、Streamable HTTP 怎样调试
远程 Server 的 stderr 通常只在部署环境可见,需要组合使用:
- Application / Container / Cloud Log;
- Reverse Proxy / Gateway Log;
curl;- Host Network Panel;
- HTTP Status;
- MCP Header 与 JSON Body;
- Streaming 或 Subscription Stream 状态;
- Trace ID。
常见 HTTP Status:
| Status | 常见排查方向 |
|---|---|
| 401 | 未认证、Token 缺失或失效 |
| 403 | 已认证,但当前身份权限不足 |
| 404 | MCP Endpoint 或 Route 错误 |
| 429 | Rate Limit |
| 500 | Server 内部异常 |
| 502 | Gateway 无法连接后端 |
| 504 | Gateway 或上游超时 |
不要只看 Status Code。还应关联 Response Body、Proxy Log、Server Trace 与具体 MCP Request。
六、Working Directory 与绝对路径
GUI Host 启动本地 Server 时,它的 Current Working Directory 往往不是项目目录。
脆弱配置:
{"command":"python","args":["server.py"]}更稳妥:
{"command":"/absolute/path/.venv/bin/python","args":["/absolute/path/server.py"]}Server 内部也不要默认相对路径总是从项目根开始:
open("config.json")可以根据当前文件位置构造:
frompathlibimportPath BASE_DIR=Path(__file__).resolve().parent CONFIG_FILE=BASE_DIR/"config.json"排错时记录实际:
command;args;- Current Working Directory;
- Runtime Path;
- Script Path;
- 文件是否存在;
- 当前用户是否有执行和读取权限。
七、环境变量为什么“终端能跑,Host 不能”
终端中已经export的变量,不一定完整传给 GUI Host 启动的子进程。
典型现象:
KeyError: API_KEY;- Authentication Failed;
- 终端直接运行成功,接入 Host 后 Tool 失败;
- 使用了系统 Python,而不是 Virtual Environment。
检查:
- Host Config 是否显式传入
env; - Server 是否显式加载
.env; - GUI Process 的 PATH 是否包含 Node、Python 或
uv; - Credential 是否注入了正确的 User/Tenant Context;
- Runtime 与 Dependency 是否来自预期 Virtual Environment;
- Secret 是否被安全保存,且没有提交到 Git。
调试时可记录“某变量是否存在”,不要把真实 Token 值写进日志。
八、按现象定位故障层
| 现象 | 优先检查 |
|---|---|
| Server 进程没有出现 | command、args、绝对路径、Runtime、执行权限 |
| Server 启动后立即退出 | Syntax、Import、Dependency、Environment、Port |
| Server 运行但 Client 解析失败 | stdout 污染、JSON-RPC、Transport 不匹配 |
| 已连接但没有 Tool | Decorator/Registration、tools/list、启动异常、Cache |
| Tool 可见但调用失败 | Arguments、inputSchema、Permission、业务代码、上游 API |
| Inspector 成功但 Host 失败 | Host Config、Capability、Version、Cache、Approval |
| HTTP 连接失败 | Endpoint、TLS、OAuth、Proxy、Gateway、Header |
| 模型从不选择 Tool | Tool Description、Context 注入、候选过多、应用策略 |
这张表的价值在于先缩小层级,再阅读对应日志。
九、理解常见 JSON-RPC Error
-32602 Invalid params
这是 JSON-RPC 标准错误码,表示某个 Method 的 Parameters 无效。
例如 Tool Schema 要求:
{"state":"CA"}实际传入:
{"state":123}可能返回-32602。
但它不只意味着“Tool Arguments 类型错”。还可能来自:
- Method 的必填参数缺失;
_meta格式不正确;- Client Capability 未按要求声明;
- Protocol Version 不兼容;
- SDK 和 Server 对同一字段版本认知不同。
在2026-07-28中,请求携带协议版本与 Client Capabilities 等元数据是重要边界。排查时要对照server/discover的结果和实际 Request_meta,不能只盯着arguments。
-32022 UnsupportedProtocolVersionError
Server 不支持 Client 使用的协议版本。Errordata应帮助说明 Server 支持的版本。
排查:
- Client 与 Server SDK 版本;
- 是否混入旧版 Message;
- Host 是否缓存了旧连接信息;
- 目标 Server 实际部署版本。
-32021 MissingRequiredClientCapabilityError
Server 需要某项 Client Capability,例如 Elicitation,但 Request 未声明或 Client 不支持。
这时不是修改 Tool Argument,而是:
- 查看 Server 的能力要求;
- 查看 Client 是否实现对应 Feature;
- 正确声明 Capability;
- 必要时采用不依赖该 Capability 的降级路径。
Transport Error 与 Tool Business Error
两者也要分开:
Transport / Protocol Error → Request 没有正常走完 Tool Result isError: true → MCP Request 已成功到达并执行 → 业务操作本身失败例如“文件不存在”可以是 Tool Business Error,而不是 JSON-RPC Transport Failure。
十、Weather Server 的完整调试流程
以系列第 6 篇的 Weather Server 为例。
第 1 步:验证外部 NWS API
先绕开 MCP,确认:
- URL 拼接正确;
User-Agent和Accept符合要求;- HTTP Status;
- Response 是否真是 JSON;
- Alerts 是否包含
features; - Points Response 是否包含
properties.forecast; - Forecast Response 是否包含
properties.periods; - Timeout、DNS 和网络出口是否正常。
如果这一步失败,问题在业务依赖或 HTTP 层,不要先调@mcp.tool()。
第 2 步:验证 Python Helper
单独测试make_nws_request和format_alert:
response.json()是否返回dict;- 异常是否被
except Exception吞掉; - Key Access 是否抛
KeyError; - 空
features是否被正确识别为“没有预警”; - 错误日志是否进入 stderr。
教学代码失败后只返回None,可能隐藏真实原因。调试阶段应临时增加结构化 Exception Log。
第 3 步:使用 Inspector 验证 MCP 层
确认:
- Server 能建立连接;
tools/list有get_alerts与get_forecast;- 自动生成的 Input Schema 正确;
state、latitude、longitude类型正确;- 手工调用能返回 Content;
- Error 时
isError表达合理。
第 4 步:接入目标 Host
确认:
command和绝对路径;- Virtual Environment 与依赖;
- Environment Variables;
- Host 能看到 Tool;
- Tool Schema 已刷新;
- Host 允许模型调用;
- User Approval 流程;
- Host 与 Server 的 Protocol/SDK Version。
第 5 步:再调模型选择
前四步都通过后,才研究:
- Tool Name 与 Description 是否清楚;
- 参数说明是否足够;
- 模型 Context 是否真的包含该 Tool;
- Tool 太多是否影响 Selection;
- Host 是否有自动调用、必须确认或禁用策略。
十一、用 Request ID 串联一次调用
推荐结构化日志:
{"timestamp":"2026-08-08T10:20:30Z","level":"info","request_id":"abc123","method":"tools/call","tool":"get_forecast","duration_ms":450,"result_size_bytes":1620,"status":"success"}一条 Request 的关键阶段使用相同 Request/Trace ID:
Host 发起 tools/call ↓ request_id=abc123 Server 开始执行 ↓ request_id=abc123 NWS 请求完成 ↓ request_id=abc123 Tool Result 返回对于 Sampling、Elicitation 或跨 Server Code Mode,还应建立 Parent/Child Trace,区分一次用户任务中的多次子调用。
十二、日志应该记什么,不该记什么
建议记录:
- Timestamp;
- Severity Level;
- Request / Trace ID;
- Protocol Method;
- Tool / Resource Name;
- Server 与 Client Version;
- 关键阶段;
- Duration;
- Result Size;
- Error Type 与 Stack Trace;
- Retry 和 Recovery。
不要记录:
- API Key;
- Authorization Header;
- Password;
- OAuth Token;
- 未脱敏个人信息;
- 没必要的完整 Tool Arguments;
- 完整 Resource Content;
- 用户上传文件正文。
如果必须定位参数问题,优先记录字段名、类型、长度、Hash 或经过审批的脱敏摘要。
十三、代码和配置改了,为什么仍然像旧版本
本地开发中常见:
- Host Config 改了,但 Host 没重新加载;
- stdio Server 旧子进程仍在运行;
- Tool Definition 被 Host Cache;
- Provider Conversation 还携带旧 Schema;
- 只关闭窗口,没有完全退出桌面应用;
- HTTP 部署仍指向旧 Container/Image。
因此修改后要明确重启哪一层:
只改 Tool 业务逻辑 → 重启 Server Process 改 Host Config / command / env → 完全重启 Host 或重新建立连接 改 Tool Schema → 重启 Server + 刷新 tools/list / Cache 改部署版本 → 验证实际 Endpoint 和 Build Identifier快速迭代阶段优先用 Inspector,链路更短。
十四、Claude Desktop 调试只是一个 Client 示例
官方页面使用 Claude Desktop 演示,但这些 UI 不是 MCP 规范要求。
查看连接状态
在 Connectors 一类菜单中检查 Server 是否出现、Tool 是否可见。如果 Server 根本不存在,先查启动和配置,不要研究模型调用。
查看日志
示例路径:
- macOS:
~/Library/Logs/Claude; - Windows:
%APPDATA%\Claude\logs。
macOS 可观察:
tail-n20-F~/Library/Logs/Claude/mcp*.log日志通常包含 Connection Event、Config Error、Runtime Error 和 Message Exchange。分享前必须脱敏。
Client DevTools
官方 Debugging 页面还演示通过 Client 的 Developer Settings 打开 Chrome DevTools,用:
- Console 查看 Client-side Error;
- Network 查看 HTTP Payload 与 Timing。
具体文件、快捷键和菜单可能随应用版本变化,应以目标 Client 当前文档为准。
十五、一个高效的排错 Checklist
Server Process
- Runtime 存在且版本正确;
- Dependency 已安装;
- Script 使用绝对路径;
- Server 没有立即退出;
- stdio stdout 没有普通日志。
Transport
- Client 与 Server 使用相同 Transport;
- stdin/stdout 未被包装脚本污染;
- HTTP Endpoint、TLS、Proxy 正确;
- Streaming Connection 没被 Gateway 截断。
MCP Layer
- Inspector 能连接;
tools/list/resources/list/prompts/list正常;- Schema 与当前代码一致;
- Protocol Version 与 Capability 匹配;
- Error Code 和
data已完整记录。
Business Layer
- Tool Arguments 通过 Schema Validation;
- Credential 存在且权限正确;
- 外部 API、文件和数据库可访问;
- Timeout、Rate Limit、Empty Result 与真实 Error 被区分。
Host / Model Layer
- Host 已完全重启或刷新;
- Tool 被注入模型 Context;
- Permission/Approval 没有阻止调用;
- Description 足以让模型选择;
- Tool 数量没有导致明显干扰。
十六、向社区求助时提供什么
提交 GitHub Issue 或 Discussion 前,先:
- 查看 Server Log;
- 用 Inspector 复现;
- 复查 Config;
- 确认 Environment;
- 缩小到最小复现。
高质量报告应包含:
- 已脱敏 Log Excerpt;
- 已脱敏 Client/Server Config;
- 最小 Steps to Reproduce;
- OS、Runtime、SDK 与 Protocol Version;
- Transport 类型;
- Inspector 是否能复现;
- Expected Result;
- Actual Result;
- 完整 Error Code 与
data。
不要只写“连不上”,也不要粘贴 Credential 或个人 Resource Content。
十七、特别注意文档版本边界
Debugging 页面或旧文章中可能仍出现:
initialize握手;Mcp-Session-Id;logging/setLevel;notifications/message。
最终2026-07-28规范移除了旧核心握手与 Session,并弃用了协议级 Logging。分层调试方法仍然有效,但具体 Wire Field 必须以实际 Client、Server、SDK 和 Protocol Version 为准。
遇到“官方页面示例和 SDK 对不上”时:
- 先确认 URL 中的文档版本;
- 确认安装的 SDK Version;
- 区分 Conceptual Guide、Migration Guide 和 Specification;
- 不要把不同版本的 Class Name 或 Message 混用;
- 用 Inspector 和真实 Wire Log 验证当前实现。
十八、常见误区
误区 1:模型不调用,所以一定是模型问题
不一定。Tool 可能根本没注册、没注入 Context、被权限拦截或 Server 已断开。
误区 2:本地 Server 可以随意print
stdio 模式不行。普通 stdout 会破坏协议,应写 stderr。
误区 3:Inspector 成功就表示一切都成功
它证明 Server 与 MCP 基本操作正常;真实 Host 仍可能在配置、Capability、Version、Cache 和 Permission 上失败。
误区 4:-32602一定只是 Tool 参数类型错
不是。Method Params、_meta、Capability 和 Version 也可能造成 Invalid Params。
误区 5:终端里有的环境变量,GUI Host 一定也有
不一定。GUI Process 的 PATH 和 Environment 经常不同,需要显式验证。
误区 6:Tool 返回isError: true等于 Transport 断开
不是。它通常表示协议调用成功完成,但业务操作失败。
误区 7:改完代码后关掉聊天窗口就够了
不一定。旧 stdio Process、Host Config Cache、Tool Definition Cache 或远程部署都可能仍是旧版本。
十九、总结
MCP 排错可以浓缩成一句话:
先证明每一层单独成立,再把它们连起来;不要从最外层的模型行为倒猜所有内部故障。
最实用的顺序是:
直接运行 Server ↓ 检查 stderr ↓ Inspector 列出并调用能力 ↓ 验证外部 API / 文件 / 数据库 ↓ 接入真实 Host ↓ 检查 Cache、Permission 和 Version ↓ 最后优化模型选择至此,九篇系列已经从 MCP 架构、Primitives、Resources/RAG、Client 能力、本地连接、Server 开发、Client Tool Loop,一直走到规模化与调试,形成了一条完整学习路径。
参考资料
- https://modelcontextprotocol.io/docs/2026-07-28/tools/debugging
- MCP 2026-07-28 Release Notes
- https://modelcontextprotocol.io/docs/2026-07-28/develop/build-server
- https://modelcontextprotocol.io/docs/2026-07-28/develop/build-client
