MCP 调试全指南:Inspector、stdio 日志、路径、环境变量与协议错误

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已认证,但当前身份权限不足
404MCP Endpoint 或 Route 错误
429Rate Limit
500Server 内部异常
502Gateway 无法连接后端
504Gateway 或上游超时

不要只看 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。

检查:

  1. Host Config 是否显式传入env
  2. Server 是否显式加载.env
  3. GUI Process 的 PATH 是否包含 Node、Python 或uv
  4. Credential 是否注入了正确的 User/Tenant Context;
  5. Runtime 与 Dependency 是否来自预期 Virtual Environment;
  6. Secret 是否被安全保存,且没有提交到 Git。

调试时可记录“某变量是否存在”,不要把真实 Token 值写进日志。

八、按现象定位故障层

现象优先检查
Server 进程没有出现commandargs、绝对路径、Runtime、执行权限
Server 启动后立即退出Syntax、Import、Dependency、Environment、Port
Server 运行但 Client 解析失败stdout 污染、JSON-RPC、Transport 不匹配
已连接但没有 ToolDecorator/Registration、tools/list、启动异常、Cache
Tool 可见但调用失败Arguments、inputSchema、Permission、业务代码、上游 API
Inspector 成功但 Host 失败Host Config、Capability、Version、Cache、Approval
HTTP 连接失败Endpoint、TLS、OAuth、Proxy、Gateway、Header
模型从不选择 ToolTool 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-AgentAccept符合要求;
  • HTTP Status;
  • Response 是否真是 JSON;
  • Alerts 是否包含features
  • Points Response 是否包含properties.forecast
  • Forecast Response 是否包含properties.periods
  • Timeout、DNS 和网络出口是否正常。

如果这一步失败,问题在业务依赖或 HTTP 层,不要先调@mcp.tool()

第 2 步:验证 Python Helper

单独测试make_nws_requestformat_alert

  • response.json()是否返回dict
  • 异常是否被except Exception吞掉;
  • Key Access 是否抛KeyError
  • features是否被正确识别为“没有预警”;
  • 错误日志是否进入 stderr。

教学代码失败后只返回None,可能隐藏真实原因。调试阶段应临时增加结构化 Exception Log。

第 3 步:使用 Inspector 验证 MCP 层

确认:

  • Server 能建立连接;
  • tools/listget_alertsget_forecast
  • 自动生成的 Input Schema 正确;
  • statelatitudelongitude类型正确;
  • 手工调用能返回 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 前,先:

  1. 查看 Server Log;
  2. 用 Inspector 复现;
  3. 复查 Config;
  4. 确认 Environment;
  5. 缩小到最小复现。

高质量报告应包含:

  • 已脱敏 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 对不上”时:

  1. 先确认 URL 中的文档版本;
  2. 确认安装的 SDK Version;
  3. 区分 Conceptual Guide、Migration Guide 和 Specification;
  4. 不要把不同版本的 Class Name 或 Message 混用;
  5. 用 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