MCP Inspector:把 Server 的连线、工具与 OAuth 问题拉进可验证的除错回圈
MCP Inspector:把 Server 的连线、工具与 OAuth 问题拉进可验证的除错回圈
MCP Server 的问题,往往不是「有没有启动」这么简单。它可能在 initialize 阶段就协议不相容,也可能成功连线却没有暴露预期的 tool;远端 HTTP 服务可能卡在 OAuth,CI 则可能因为输出混入人类可读的 banner,导致后续 JSON 解析失败。当 MCP 开始成为 AI Agent 的工具边界,这些问题不能只靠开发者打开一个网页、凭感觉按几下来判断。
我这次挑 modelcontextprotocol/inspector,是因为它把「检查 MCP Server」做成一个真正的开发者工具,而不是单纯的示范 UI。官方 repository 目前的 v2 版本以一个 mcp-inspector binary 同时提供 Web、CLI 与 TUI 三种介面;CLI 还能输出机器可读的 JSON,直接放进 shell、CI 或 smoke test。换句话说,它的价值不只在于看见工具清单,而在于把连线、能力协商、工具呼叫、OAuth 与失败状态转成可重跑的验证步骤。
本文以 MCP Inspector 官方 GitHub repository、README、CLI 文件、MCP server configuration 文件与 smoke testing 文件为主要查证来源。本文记录的 repository 状态以 2026 年 9 月 11 日查证结果为准;版本、命令列参数与 MCP SDK 行为仍应以官方文件为准。
先讲结论:它解决的是「MCP 能不能被验证」
MCP Inspector 适合放在 MCP Server 开发周期的中间位置。它不是要取代单元测试,也不是用来取代正式的 conformance suite,而是补上从「Server 程式码能执行」到「Agent 真的能稳定使用」之间的那段空白。
我会把它的用途分成四层:
1. 快速诊断:在 Web 介面中连接一个本机或远端 Server,查看初始化结果、tools、resources、prompts 与事件。
1. 互动探索:使用 TUI 在终端机中测试,不必为了每次小修改都切换浏览器。
1. 自动验证:用 CLI 执行 initialize、tools/list 或 tools/call,把结果交给 shell 与 jq 判断。
1. 发布前防线:把 connect、list、call、assert 串成几秒内完成的 smoke job,在每次 commit 或 deploy 后执行。
这个定位很重要。若你只是想做一次手动展示,Web 介面已经足够;若你要让团队知道某个 Server 在升级 SDK、修改 schema 或切换 OAuth provider 后是否仍然可用,真正有价值的是 CLI 的可重跑性。
为什么 Web、CLI、TUI 要共用同一个 Inspector
官方 README 将 Inspector 拆成四个 client 区域:Web、CLI、TUI 与 launcher,另外由 core 放置共用程式码。Web 是 Vite、React、Mantine 加上 Node backend 的单页工具;CLI 是适合 automation、CI 与 agent feedback loop 的 scriptable client;TUI 则使用 Ink 与 React 提供互动式终端介面。三者最后都透过同一个 mcp-inspector 入口分派。
这个设计让我想到一个常被忽略的工程原则:互动介面可以不同,但验证语意不应该各自发明。Web 适合人眼探索,CLI 适合程式判断,TUI 适合在终端快速往返;如果三者背后使用相同的连线设定、transport 与核心解析逻辑,团队才比较不会遇到「浏览器看起来正常,CI 却连不上」的落差。
当然,共用核心不代表所有参数行为完全相同。官方 configuration 文件特别说明,Web、CLI 与 TUI 对 --header、--transport stdio 以及 -- 分隔符有各自的细节。因此我不建议把一条在 Web 上可行的命令直接复制到 CI;应该先读对应 client 的文件,再把最小可验证命令固定下来。
三种介面,各自适合什么工作
Web:用来看完整状态与探索未知 Server
Web 介面最适合第一次接触某个 Server,或需要观察工具 schema、resource、prompt 与 MCP App 行为的情境。它能把协议互动转成可视化状态,让你快速知道 Server 到底提供了什么,以及某个工具的输入 schema 是否和前端预期一致。
它也适合用来做「探索性除错」:先连线,看看 initialize 回传的 server information 与 capabilities,再进一步列出工具并尝试一次安全的读取操作。不过,Web 的优点是互动速度,不是可重播性。你在画面上按过什么、当时使用了哪些 header、某个错误是否只是偶发,未必能被另一位同事精确重现。
TUI:把互动测试留在终端工作流
TUI 的价值在于它把互动式检查放回 terminal。对习惯 SSH、tmux 或远端开发环境的人来说,这比开浏览器更自然。它也能成为从 CLI smoke test 过渡到 Web 除错前的中间层:先用命令连线,再在同一个终端中深入查看状态。
但 TUI 仍然是给人看的介面。只要验证结果要被 CI 或其他工具消费,就应该回到 CLI 的 --format json,不要尝试解析画面排版。
CLI:真正把 Inspector 接进工程流程
CLI 是我认为最值得写进文章的部分。官方文件将它定义为 connect、执行一个 --method、再 disconnect 的工具;它支援 tools、resources、prompts,也能透过 servers/list 与 servers/show 查询 catalog entry 而不连线。
最小的本机 Server 检查可以是:
npx @modelcontextprotocol/inspector --cli node build/index.js --method initialize
这个命令不会呼叫实际工具,而是先完成 MCP handshake,输出 serverInfo、protocolVersion、capabilities 与 instructions,然后断线。对 smoke test 来说,这是很好的第一个探针:成本低,却能确认「目标活着,而且真的在说 MCP」。
从 initialize 到 tools/call:一条可重跑的验证路径
我会建议把 MCP Server 的检查拆成由浅入深的四步,而不是一开始就直接呼叫最复杂的工具。
第一步:先验证连线与协议
stdio Server 需要把启动命令放在 Inspector 的 target 位置;远端 Server 则可以使用 HTTP 或 SSE。Streamable HTTP 的例子如下:
npx @modelcontextprotocol/inspector --cli \
--transport http --server-url https://example.com/mcp --method initialize
SSE 则使用:
npx @modelcontextprotocol/inspector --cli \
--transport sse --server-url https://example.com/sse --method initialize
这一步只回答「能不能握手」。它不能证明工具一定正确,也不能证明权限配置完整,所以不要把 exit code 为零误解成整个产品流程已通过。
第二步:列出能力,确认契约没有漂移
接着列出 tools、resources 或 prompts:
npx @modelcontextprotocol/inspector --cli node build/index.js \
--method tools/list --format json
--format json 是关键。官方 smoke testing 文件指出,预设输出是给人阅读的 text 格式;只要结果要被脚本处理,就应该明确指定 JSON。一般方法的 envelope 会包含 result,有些情况还会有 appInfo 或 schemaFindings。因此 consumer 不应假设每次回应只有固定的单一栏位。
若要确认某个工具存在,可以搭配 jq -e:
npx @modelcontextprotocol/inspector --cli node build/index.js \
--method tools/list --format json \
| jq -e '.result.tools | map(.name) | index("my_tool")' > /dev/null
这里的工程重点不是 jq 本身,而是把「工具契约」写成失败时会中止的条件。工具名称消失、Server 回传格式改变、或连线指到错误环境时,CI 都应该清楚失败,而不是留下看似成功的 log。
第三步:只呼叫一个可控工具
当能力清单符合预期,再做一次工具呼叫:
npx @modelcontextprotocol/inspector --cli node build/index.js \
--method tools/call \
--tool-name mytool \
--tool-arg key=value \
--tool-arg another=value2 \
--format json
若输入是巢状 JSON,可以把整个值放进 --tool-arg:
--tool-arg 'options={"format": "json", "max_tokens": 100}'
我会把 smoke test 的工具挑选视为安全设计,而不是测试细节。优先挑选唯读、幂等、没有外部副作用的工具,例如回传版本、健康状态或固定 fixture。不要为了证明「真的能 call」而在每次 CI 执行删除、发信、写入资料库或修改云端资源的工具。
第四步:把每个 assertion 拆成独立 process
官方 smoke testing 文件的核心建议,是每个 assertion 使用一个 Inspector process。这样每个步骤都会有清楚的 stdout、stderr 与 exit code,失败时也比较容易知道是 connect、list 还是 call 出问题。它不是完整的 conformance suite,而是每次 commit 或 deploy 皆可执行的快速健康检查。
这个做法也让故障排查更直接:
- initialize 失败,先看 target、transport、Node 版本与 timeout。
- tools/list 失败,检查 Server 是否在 initialize 后正确宣告能力,以及输出是否真的为 JSON。
- tools/call 失败,检查工具名称、schema、参数型别与 Server 端 exception。
- 只有 Web App probe 失败时,才需要进一步检查
appInfo的回应形状,而不是硬读.result。
`--config` 与 `--catalog`:看似相同,其实责任完全不同
Inspector v2 把 Server 设定分成两个概念。--catalog 是 Inspector 自己管理、可以写入的 Server 清单;如果档案不存在,CLI 与 TUI 会建立空的 catalog。--config 则是唯读的 session file,档案不存在时会报错,Inspector 不会替你建立或修改它。两者互斥,也不能和 ad hoc target 混用。
这个区分对团队特别重要。
- 你自己的本机工作集合,适合放在
--catalog。 - CI 中由 repository 提供的固定设定,适合使用
--config,确保测试不会悄悄改动档案。 - 临时测试某个命令或 URL,直接使用 ad hoc target。
例如,读取一个固定 session file 并指定 Server:
npx @modelcontextprotocol/inspector --cli \
--config ./mcp.json --server my-server \
--method initialize
另一个容易踩到的坑是 CLI 的 target 顺序。CLI 会把第一段连续的非 dash token 当作 target,因此 target 必须放在 Inspector 自己的旗标前面:
# 正确
npx @modelcontextprotocol/inspector --cli node build/index.js --method tools/list
# 容易连到错误来源
npx @modelcontextprotocol/inspector --cli --method tools/list node build/index.js
第二种形式不一定直接报错,node build/index.js 可能被丢掉,Inspector 反而回头使用 catalog。这类「命令成功,但测到错的 Server」比明确失败更危险,所以我会把 target 顺序与来源选择一并写进 code review checklist。
`--` 分隔符与 timeout:CI 最容易忽略的两个细节
当 stdio Server 自己也需要旗标时,必须处理 Inspector 与 target 的参数边界。CLI 的 -- 分隔方式和 Web、TUI 相反;CLI 下,分隔符后的内容会成为 Inspector 参数,而 target 命令在前面。
例如:
npx @modelcontextprotocol/inspector --cli \
node build/index.js --config ./server.conf -- --method tools/list
实际使用前请用目标 client 的文件验证分隔方向,因为把 Web 范例原封不动搬到 CLI,可能让 --config 被错误的一方吃掉。
另一个是 timeout。官方文件指出,ad hoc target 或 --server-url 的 --connect-timeout 预设为 15000 毫秒,设定为 0 则会停用。这个预设对互动式测试很合理,但 CI 不应把 timeout 关掉;一个黑洞式的远端主机不该让 runner 一直等待到工作本身被强制终止。
OAuth 与远端 Server:能登入不代表测试已经完成
MCP Inspector 的远端连线不只涉及 transport,也可能涉及 OAuth discovery、授权码流程、token 储存与 refresh。CLI 文件说明,从 catalog 或 config 载入的 Server,可以带入 headers、connection/request timeout、OAuth 与 roots 设定;临时的 --header 可以覆盖当次执行的 header,但不会改写档案中的其他设定。
这里我会特别提醒两件事。第一,测试设定档不应把秘密直接提交进 repository;官方 configuration 文件将 --config 定位成不会被 Inspector 写入的唯读 session file,但唯读不代表内容本身自动安全。第二,OAuth 的成功应该被当成一条可观测的测试步骤:要确认 discovery 成功、token 能被保存或取得、接着 initialize 和 tools/list 也成功,而不是只看浏览器是否出现 consent screen。
如果 CI 需要非互动执行,smoke testing 文件也提醒要避免让 OAuth 流程卡在人工登入。最好的做法是使用测试专用的授权环境、明确管理 token 的生命周期,并让测试在缺少授权时快速失败;不要把真实使用者帐号或长期 token 写入 log。
MCP App 的回应形状:不要假设永远有 `result`
Inspector v2 对 MCP App 提供专门的 probe。官方 smoke 文件指出,除了 --app-info 之外,一般方法的 JSON envelope 通常包含 result,也可能有 appInfo 与 schemaFindings;但 --app-info 是另一种形状,回应可能只有 appInfo,不会有 result。
这是一个很典型的整合陷阱:consumer 如果固定读 .result,遇到 --app-info 就会把合法回应误判成错误;如果 consumer 只接受 appInfo,又会漏掉 tools/list --app-info 的 NDJSON 行为。正确做法是依 key 判断回应类型,并把 exit code 与 JSON 栏位各自当成可用讯号。
我认为这个设计也说明了一件事:工具的可用性不只是「有没有 API」,还包括输出契约是否让下游程式正确理解。当 Agent、CI 与人类 UI 都会使用同一个 Server 时,这些 envelope 差异必须在文件与测试中明确写出来。
安装与第一个可验证任务
官方 v2 README 要求 Node >=22.19.0。如果只是使用已发布的 package,可以直接用 npx;如果要在 Inspector repository 内开发,则需要在 root 执行 npm install,再执行 npm run build。这个 v2 repository 不是 npm workspace,每个 clients/* 都有自己的 package.json 与 node_modules,root scripts 会串起 Web、CLI、TUI 与 launcher 的建置。
我会用以下顺序开始:
1. 先确认执行环境
node --version
npx --version
jq --version
Node 版本若低于官方要求,先升级,不要把后续的 ESM、undici 或 bundling 错误误判成 MCP Server 问题。CI 也不要让 npx 每次漂移到最新版本;官方 smoke 文件建议在自动化环境固定精确版本,例如:
npx --yes @modelcontextprotocol/[email protected] --cli node build/index.js --method initialize
--yes 用来避免第一次安装时出现互动提示,而精确版本则避免同一个 commit 在不同日期跑到不同 Inspector。
2. 先做 connect-only probe
npx --yes @modelcontextprotocol/[email protected] \
--cli node build/index.js --method initialize
如果这一步失败,先不要往 tools/call 看。确认 target 命令可以单独启动、stdio 没有把非协议 log 写到 stdout、远端 URL 与 transport 相符,并检查 --connect-timeout 是否足够。
3. 把结果转成 CI 可读的 JSON
npx --yes @modelcontextprotocol/[email protected] \
--cli node build/index.js --method tools/list --format json \
| jq -e '.result.tools | length > 0' > /dev/null
这里的 assertion 只是示例。实际专案应验证你真正依赖的工具名称、输入 schema 或必要的 resource,而不是只判断 tools 阵列非空。
4. 再加入安全的 tools/call
最后才把一个唯读 fixture 或健康检查工具放进 pipeline:
npx --yes @modelcontextprotocol/[email protected] \
--cli node build/index.js \
--method tools/call --tool-name health_check \
--format json \
| jq -e '.result' > /dev/null
这四步完成后,Inspector 才真正从「除错画面」变成「Server contract 的执行器」。
它不适合解决什么问题
MCP Inspector 很有用,但我不会把它包装成万能测试工具。
第一,它不能替你证明商业逻辑正确。tools/list 只证明能力宣告存在,tools/call 成功也不代表资料真的符合产品规则;你仍需要 Server 自己的 unit test、integration test 与 domain assertion。
第二,它不是完整的安全审计工具。Inspector 能协助你查看 headers、OAuth、roots 与工具行为,但权限模型、最小权限、秘密管理、audit log 与供应链风险,仍然要由部署团队负责。特别是能执行本机命令或存取档案的 stdio Server,不能因为 Inspector 显示连线成功就直接信任。
第三,它不能消除 transport 与环境差异。Node 版本、proxy、DNS、TLS、container 网路、OAuth provider 与 Server 的启动输出,都可能让本机测试和 production 不同。它可以把失败变得更清楚,但不能替你建立正确的 production parity。
第四,Web UI 的互动成功不能代替 CI。手动按按钮只能证明某个时刻有人完成了一次操作;要建立团队信心,仍需把关键流程转成固定版本、固定 config、固定 timeout 与可判断的 exit code。
我会怎么把它放进团队流程
如果团队刚开始导入 MCP,我会先建立一个很小的验证矩阵:
- 每次 pull request:本机 stdio Server 的 initialize 与 tools/list。
- 每次 deploy:远端 HTTP 或 SSE Server 的 initialize、必要工具存在性与一个唯读 tools/call。
- 每次 OAuth 设定变更:discovery、授权、token 使用与后续 MCP method。
- 每次 Inspector 或 MCP SDK 升级:用 pinned version 重跑同一组 smoke test,再检查 exit code 与 JSON envelope。
测试脚本本身也要遵守三个原则:
1. stdout 只保留给结果,stderr 留给 diagnostics,不要用 2>&1 把两者混在一起后再交给 jq。
1. 每个 assertion 尽量独立执行,让失败边界清楚。
1. 不在 log 印出 API key、Cookie、OAuth token 或完整的敏感 header。
这个流程的核心不是增加一个工具,而是让 MCP Server 从「某个 Agent 好像可以用」变成「我们知道哪个契约已经被验证」。
最后的判断:Inspector 是 MCP 的可观测测试面
我认为 MCP Inspector 最值得注意的地方,不是它同时有 Web、CLI 与 TUI,而是它把协议互动的不同使用者放在一条一致的工具链里:人可以用 Web 探索,开发者可以用 TUI 除错,CI 可以用 CLI 断言,Agent 开发者则可以把工具回馈纳入自己的回圈。
如果你的 MCP Server 还在「可以连线就算成功」的阶段,先从 initialize、tools/list 与一个唯读 tools/call 开始;如果你已经遇到 OAuth、proxy、MCP App、roots 或 config 漂移,则更应该把这些边界写成可重跑的测试。
它最适合的团队,是已经有 MCP Server 或准备把 MCP 接进 AI Agent,并且愿意把除错经验沉淀成自动化检查的人。若你只需要一次性的手动 demo,Web 可能已经足够;但只要 Server 要被持续部署、被多人使用,CLI smoke test 就不应该是最后才补的配件。
参考资料