AI-Chain

MCP Inspector:把 Server 的連線、工具與 OAuth 問題拉進可驗證的除錯迴圈

MCP Inspector 不只是替 MCP Server 做圖形化展示,而是把 Web、CLI 與 TUI 放進同一個檢查工具鏈。本文從官方 v2 文件拆解它如何測試連線、列出工具、呼叫方法、檢查 MCP App 與處理 OAuth,並用可放進 CI 的 CLI smoke test 建立一條可重跑的驗證路徑。

分享:
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 與事件。
  2. 互動探索:使用 TUI 在終端機中測試,不必為了每次小修改都切換瀏覽器。
  3. 自動驗證:用 CLI 執行 initialize、tools/list 或 tools/call,把結果交給 shell 與 jq 判斷。
  4. 發布前防線:把 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。
  2. 每個 assertion 盡量獨立執行,讓失敗邊界清楚。
  3. 不在 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 就不應該是最後才補的配件。


參考資料