MCP Inspectorの使い方 — 自作サーバーの動作確認とデバッグ手順
MCP Inspectorは自作MCPサーバーの動作確認に使う公式ツールです。npxで起動し、Web・CLI・TUIの3クライアントでツール呼び出しやOAuth認証を検証する手順をまとめます。
MCP Inspectorとは — 自作サーバーの動作確認に使う公式ツール
MCP Inspectorは、MCP(Model Context Protocol)サーバーの動作確認とデバッグに特化した公式ツールです。@modelcontextprotocol/inspectorという単一パッケージに、Web・CLI・TUIの3つのクライアントが同梱されており(このほか実験的な接続クライアントmcpdoも入っています)、npxでその場で起動できるため、インストール作業は不要です。
最短の使い方は、npx @modelcontextprotocol/inspector <サーバーの起動コマンド>を実行し、ターミナルに表示されたトークン付きURLをブラウザで開くことです。ブラウザを使わない環境では、--cliか--tuiを先頭に付けます。
自作したサーバーをClaude CodeやClaude Desktopにいきなり繋ぐと、失敗したときに原因の切り分けが難しくなります。クライアント側の問題なのか、サーバーの実装ミスなのか、認証の設定ミスなのかが混ざって見えるからです。MCP Inspectorはこの間に挟まり、サーバー単体を人間が操作できる形で見せてくれます。ツール呼び出しの引数と戻り値、JSON-RPCの生トラフィック、認証フローの途中経過まで、実際のクライアントに繋ぐ前に目視で確認できるのが最大の価値です。
2.x系は2026年7月28日(UTC)公開の2.0.0から始まり、以降も更新が続いています。新旧プロトコルのバージョンをまたいだ互換性の扱いはMCP Inspectorの新旧バージョン互換性の仕組みで扱っています。動作にはNode.js 22.19.0以上が必要です。サーバーを一から書く手順はMCPサーバー自作ガイドが扱う範囲です。MCPの仕組み自体はMCP実用ガイドにまとめてあります。本記事はInspectorでの動作確認とデバッグの手順に絞ります。
起動前に確認すること — 3つのクライアントの使い分け
mcp-inspectorバイナリはランチャーで、実際の処理は3つのクライアントのどれかに委譲されます。モードを選ぶフラグ(--web / --cli / --tui)はコマンドの先頭に置く必要があり、それ以降の引数はすべて選んだクライアントへそのまま渡されます。
| クライアント | 起動コマンド | 向いている場面 |
|---|---|---|
| Web(既定) | 起動コマンドnpx @modelcontextprotocol/inspector | 向いている場面GUIでスキーマやレスポンスを目視確認したいとき |
| CLI | 起動コマンドnpx @modelcontextprotocol/inspector --cli <server> | 向いている場面シェルパイプラインやCIでの一発検証 |
| TUI | 起動コマンドnpx @modelcontextprotocol/inspector --tui <server> | 向いている場面SSH先やブラウザのないリモート環境 |
3クライアントは同じ接続コアを共有しています。トランスポート、設定ファイルの読み方、ディスク上のOAuth状態はすべて共通です。Webでログインを済ませておけば、CLIやTUIから同じ認証状態を再利用できます。
Webクライアントで自作サーバーに接続する
stdio(標準入出力)方式のサーバーは、起動コマンドをそのまま引数に渡します。
npx @modelcontextprotocol/inspector node build/index.js起動するとトークン付きのURLがターミナルに表示されます。そのURLをそのまま開いてください。localhost:6274を記憶から直接入力すると、Node側のAPIサーバーがトークン未一致で全リクエストを拒否します。バックエンドはローカルマシン上でプロセスを起動する権限を持つため、この認証は毎回のランダムトークンによるものです。固定したいときはInspectorが読む環境変数一覧のMCP_INSPECTOR_API_TOKEN環境変数でトークンを指定できます。
接続後の画面は、サーバーが実際に持つ能力(capability)によって変わります。toolsがあればToolsタブが、resourcesがあればResourcesタブが、promptsがあればPromptsタブが現れます。画面で試してからコードへ戻る流れは、Managed Agentsの手順とも似ています。詳しくはConsoleで視覚的に構築してからコードへ持ち帰るにあります。よく使うのは次の3系統です。
- Tools: スキーマがフォームとして描画され、値を入力して呼び出すと結果が下に表示されます。引数の型ミスもここで即座に分かります
- Protocol: JSON-RPCのやり取りをリクエストとレスポンスの組で見せる生トラフィックのログです
- Console(stdioサーバーのみ): サーバープロセスの標準エラー出力です。多くのstdioサーバーは自分の診断情報をここに吐くため、接続が理由もなく失敗したときはまず確認します
HTTPやSSEのサーバーでは、Consoleの代わりにNetworkタブが出ます。ステータスコードやヘッダー、本文といったHTTP層の様子が見られ、NetworkとConsoleが同時に並ぶことはありません。
Tasks・Logs・Protocol・Network・Consoleの監視系タブは、ピン留めすると右側の固定カラムに移ります。Toolsを操作しながらProtocolの流れを横目で追えるので、「呼んだ直後にどんなJSON-RPCが飛んだか」を画面の切り替えなしで確認できます。
CLIクライアントで一発検証・CI組み込みをする
CLIは1回の起動につき1つのメソッドを実行して結果を返し、そのまま終了します。人間が画面を見る前提のWebと違い、シェルやCIパイプラインに組み込む前提の設計です。
npx @modelcontextprotocol/inspector --cli node build/index.js --method tools/listツールを呼ぶときの引数指定は2通りあり、同時には使えません。郵便番号のように「数字に見える文字列」を渡すとき、違いがはっきり出ます。
引数指定の2方式
--tool-arg
値をJSONとして解釈する方式です。count=1は数値の1になり、"012"は12に変わります。options={"format":"json"}のようにオブジェクトも渡せます。
--tool-args-json
引数全体を変換せず、そのまま送る方式です。--tool-args-json '{"zip":"012"}'と渡せば、"012"は文字列の012のまま届きます。型を厳密に固定したい検証はこちらを使います。
--format jsonを付けると、バナー無しのJSONオブジェクトだけが標準出力に流れ、jqにそのままパイプできます。非ゼロの終了コードは失敗の種類ごとに固定されているため、呼び出し側は文言をパースせずに分岐できます。
| コード | 意味 |
|---|---|
0 | 意味成功 |
1 | 意味使い方の誤りなど想定外のエラー(その他すべて) |
2 | 意味ツールにMCP Appが無い(--app-infoでの確認時のみ) |
3 | 意味サーバーが認証を要求(401/403) |
4 | 意味サーバーに到達できない(DNS・接続拒否・タイムアウト) |
5 | 意味ツールがエラーを返した、または該当ツールなし |
失敗時は標準エラー出力に、原因を表すJSONが1行だけ出ます。auth_requiredのようなコードとstatus、接続先のurlが入っているので、2>&1 | tail -1 | jq .errorで取り出せます。tools/callの結果がisError: trueのときもペイロードは表示され、そのうえで終了コードが5になります。&&でつないだ後続のコマンドが、失敗した呼び出しの後で走ることはありません。
終了コードで分岐する書き方は次のとおりです。認証切れと到達不能を、ログの文言に頼らず見分けられます。
if out=$(mcp-inspector --cli "$URL" --transport http --method tools/list 2>err.json); then
echo "$out"
else
case $? in
3) echo "要認証: 先にWebクライアントでログインする" ;;
4) echo "サーバーに到達できない" ;;
*) jq .error < err.json ;;
esac
fiCI組み込みの典型形はこうなります。
mcp-inspector --cli --config ./ci-servers.json --server my-server \
--stored-auth-only --method tools/list --format json \
| jq -e '.result.tools | map(.name) | index("get_weather")' > /dev/nullサーバー一覧をファイルから読むときは、--configと--catalogで性質が違います。
--config と --catalog の使い分け
--config
指定したファイルを書き込み・初期化・移行のいずれもせず、そのまま使います。Claude Desktopなど他クライアントの設定ファイルを触らずに読むときの選択肢です。省略時の既定はなく、必ず指定します。
--catalog
Inspector自身の作業用サーバー一覧です。既定は~/.mcp-inspector/mcp.jsonで、MCP_CATALOG_PATHでも変えられます。画面からの追加・編集が保存されます。
ツールを呼ばず一覧だけ確かめたいときは、--method servers/listやservers/show --server <名前>が使えます。どちらもサーバーへ接続しません。ただしservers/showは、envの値や機微なヘッダー、OAuthのクライアントシークレットを伏せる一方、urlに埋め込まれたトークンやstdioのargsは伏せません。出力をそのままIssueに貼る前に、中身を確認します。
社内プロキシ越しにリモートサーバーを検証する場合は、HTTPS_PROXY・HTTP_PROXY・NO_PROXYの通常の環境変数がそのまま効き、Inspector専用のフラグは要りません。
TUIクライアントをリモート・ヘッドレス環境で使う
TUIはターミナル内で完結するインターフェースで、SSH接続先やGUIを持たない検証環境に向きます。動作には実TTYが必要なので、ヘッドレスなCIジョブでは動きません。そこはCLIの役割です。
npx @modelcontextprotocol/inspector --tui node build/index.js矢印キーまたはTabでタブを切り替え、cで接続、dで切断、EscかCtrl+Cで終了します。タブにはショートカットがあります。Info(i)・Auth(a)・Resources(r)・Prompts(m)・Tools(t)・Protocol(p)・Network(n)・Console(o)です。cは接続に使われるため、Consoleはoです。
CLIと違って--server <name>で1台を指定するフラグが無く、設定ファイル内の全サーバーを読み込んで画面上のリストから選ぶ形です。ファイルを指定しなければ、書き込み可能な~/.mcp-inspector/mcp.jsonが使われます。OAuthが必要なサーバーではcを押すだけでブラウザでの認可フローが自動的に始まり、コールバックが返れば再度cを押さずに接続が完了します。
OAuth認証が必要なリモートサーバーを検証する
リモートのMCPサーバーの多くは認可を要求します。Inspectorは3クライアントすべてで同じOAuthフローを実装しており、取得したトークンはディスク上で共有されるため、Webで一度ログインすればCLIやTUIからも使い回せます。仕組みの全体(401応答からのディスカバリー、PKCE付きトークン取得までの流れ)はリモートMCPのOAuth認証が扱う内容です。ここではInspector固有の挙動に絞ります。
コールバックURLはクライアントごとに違います。Webはメインアプリのlocalhost:6274/oauth/callbackが窓口です。CLIとTUIは衝突を避けるため、専用の127.0.0.1:6276/oauth/callbackを共有します。事前登録が必須なIdP(アイデンティティプロバイダー)を使うなら、このURLを一度登録しておけば繰り返し使えます。
CIのような非対話環境では、ブラウザを開いて15分待つような事態を避ける必要があります。
--stored-auth-only: 対話的なOAuthを一切開始せず、保存済みトークンがあればそれを使い、無ければ即座にauth_requiredで失敗します。CI向けの選択肢です--use-stored-auth: 人間がWebクライアントで完了させたログインを再利用し、リフレッシュトークンがあれば先に更新してから使います--print-handoff: リモートVM上でCLIを動かしつつ、認可はローカルのブラウザで完了させたいときに使う情報一式(ディープリンクとポートフォワードのコマンド)を出力します--wait-for-auth <秒>: 保存領域にトークンが現れるまで待ち、現れたら使います。人間にログインを任せた後の待ち受けで、時間切れは終了コード3です--list-stored-auth/--relogin: 前者は保存済みのサーバーURLを一覧して終了します。後者はそのサーバーの保存済みOAuthを削除してから接続します(HTTPとSSEのサーバーのみ)
リモートVMでの流れは、--print-handoffで出た情報を手元に持ち帰ってブラウザで認可し、VM側は--wait-for-auth 120のように待つ形です。
リダイレクトURIはIdPに登録した文字列と完全に一致する必要があります。localhost:6276と127.0.0.1:6276は、同じリスナーに届いても認可サーバーからは別のURIです。--callback-url(環境変数ならMCP_OAUTH_CALLBACK_URL)で変えられますが、ホストはループバックに限られます。また、既定のポートを同時に握れるのは1つのフローだけで、2つ目はEADDRINUSEで失敗します。並列で試すなら、インスタンスごとに別の固定ポートを割り当てます。
接続するサーバーと設定を持ち込む
stdioサーバーは、位置引数がすべて起動コマンドとして扱われます。サーバー自身へ渡したい引数は--の後ろに置きます。区切りが無いと、--verboseのような引数がInspector側に解釈され、サーバーまで届きません。この--区切りで引数を分けるのはWebとCLIのクライアントです。環境変数は-e、作業ディレクトリは--cwdで与えます。
mcp-inspector -e API_KEY=abc123 -e REGION=us-east-1 --cwd ~/projects/my-server \
node build/index.js -- --verboseリモートのHTTPサーバーは、--server-url https://api.example.com/mcp --transport httpのように指定します。必要なら--header "X-Tenant: acme"を足します。--transportにはhttp(Streamable HTTP)とsseが選べ、保護されたサーバーは401を返した時点でOAuthフローが走るため、事前の設定は要りません。HTTPサーバーでは、プロトコルの世代(legacy・modern・auto)も選びます。既定はlegacyで、2026-07-28の挙動を試すにはServer Settingsで切り替えます。
すでにClaude Desktop・Cursor・Cline・VS Codeに設定済みのサーバーは、Serversの画面のAdd Serversから取り込めます。MCP Registryのserver.jsonも読めます。取り込みは書き込み可能なカタログに統合され、既存の項目は上書きされません。手元のカタログを一切触りたくないときは、先ほどの--configで外部ファイルを読み取り専用のまま開きます。
mcp-inspector --config ~/Library/Application\ Support/Claude/claude_desktop_config.jsonネットワーク越しとDockerで開くとき
既定ではlocalhostにだけ束縛し、ループバックのオリジンからのリクエストだけを受けます。バックエンドがプロセスを起動する以上、どちらも防御線として扱われています。公開範囲を広げる選択肢は次のとおりです。
| やりたいこと | 設定 |
|---|---|
| 同じLANの別マシンから開く | 設定HOST=192.168.1.50のように特定アドレスを指定。許可オリジンは束縛ホストに追従する |
| TLSやリバースプロキシの背後に置く | 設定ブラウザのオリジンが公開URLになるためALLOWED_ORIGINS=https://inspector.example.comを設定 |
ワイルドカード(0.0.0.0など)に束縛 | 設定DANGEROUSLY_BIND_ALL_INTERFACES=trueが必須。非ループバックで開くにはALLOWED_ORIGINSも必要 |
特定アドレスへの束縛は許可されますが、ワイルドカードへの束縛は上のフラグ無しでは拒否されます。全インターフェースへ一度に公開する形はDNSリバインディング攻撃の標的になりやすく、1つのアドレスを意図して公開する形とは区別されているためです。
ALLOWED_ORIGINSは既定の一覧に追加されるのではなく、置き換わります。ループバックを残したいなら、http://localhost:6274,http://127.0.0.1:6274,http://192.168.1.50:6274のように全部を列挙します。スキームの無い値は警告付きで捨てられ、空にしても検査は無効化されず既定に戻ります。オリジン検証を切る設定はありません。
Dockerイメージはghcr.io/modelcontextprotocol/inspectorで、linux/amd64とlinux/arm64向けに公開されています。
docker run --rm -p 6274:6274 ghcr.io/modelcontextprotocol/inspectorコンテナは既定でWebモードを0.0.0.0:6274で待ち受け、ブラウザの自動起動は切ってあり、非rootで動きます。ワイルドカード束縛が前提のためDANGEROUSLY_BIND_ALL_INTERFACES=trueが既定で入っています。セッショントークンはコンテナのログに出ますが、-e MCP_INSPECTOR_API_TOKEN=<値>で固定もできます。
-p 8080:6274のようにポートを付け替えると、ブラウザのオリジンがhttp://localhost:8080になり、コンテナ内部のポートと合わずに接続が403になります。対処は2通りです。1つは-e CLIENT_PORT=8080 -p 8080:8080で内外のポートをそろえる方法です。もう1つは-e ALLOWED_ORIGINS=http://localhost:8080,http://127.0.0.1:8080の指定です。CLIやTUIをコンテナで動かすときは、Webサーバーが無いためヘルスチェックが失敗します。--no-healthcheckを付けます。
MCP Appsを表示するなら、サンドボックス用のポートにも届く必要があります。既定では動的に決まるためMCP_SANDBOX_PORTで固定し、公開または転送します。公式イメージが公開するのは6274だけです。サンドボックスのURLは常にhttpなので、https経由のページでは混在コンテンツとしてiframeが遮られます。
Inspectorでは動くのにクライアントで動かないとき
Inspectorで通ったサーバーがClaude DesktopやClaude Codeで失敗するなら、差は接続条件にあります。stdioサーバーは、クライアントの設定に書いたコマンド・引数・環境で起動されます。次の4点は、Inspectorでは問題にならずクライアントで初めて表に出やすい項目です。以下は公式のデバッグ解説がClaude Desktopの設定ファイルを例に挙げている内容で、他のstdioクライアントにも同じ原則が当てはまるとされています。
- 作業ディレクトリ: クライアントから起動したサーバーの作業ディレクトリは未定義になりえます(macOSでは
/になる例が挙がっています)。相対パスの./dataではなく絶対パスを書きます - 環境変数: stdioサーバーが自動で引き継ぐのは限られた一部で、内訳はプラットフォームごとに違います。APIキーなどは設定の
envに明示します。Inspectorでは-eが同じ役割です - 標準出力への書き込み: stdioサーバーがstdoutにログを出すと、プロトコルの通信と混ざって壊れます。診断はstderrへ出し、InspectorのConsoleタブで確かめます
- Streamable HTTPのログ: HTTPのサーバーはstderrがクライアントに取り込まれません。ログ基盤やOpenTelemetryを使い、リクエストはcurlやブラウザのNetworkパネルで見ます
これらを順に潰してもなお繋がらないときは、Inspectorの外の層が原因です。
クライアント側の登録方法はClaude Code MCP設定ガイドにあります。設定・起動・認証・ツール表示の4層で切り分ける手順は、MCPサーバーに接続できないときの切り分け手順です。
よくあるつまずきと対処
localhost:6274を直接開いてトークンエラーになる場合: 起動時に表示されたトークン付きのURLを開きます。一度開けばトークンがindex.htmlに埋め込まれるため、再読み込みやブックマークでは引き続き動きます- OAuthで、登録したリダイレクトURIと合わず失敗する場合:
localhostと127.0.0.1の取り違えを疑います。CLIとTUIの既定は127.0.0.1:6276です tools/list --app-infoの出力を--format jsonで整形したつもりが変わらない場合: 一覧では常に1行1ツールのNDJSONが出ます。--format jsonが効くのはtools/call --app-infoの単一ツールの出力だけです- CIでOAuthを求められて止まる場合: 標準入力と標準エラー出力のどちらにもTTYが無ければ、CLIは最大15分の待機に入らず
auth_requiredで即失敗します。TTYのある手元で試すと待ち続けるので、--stored-auth-onlyを付けておくと手元とCIで挙動がそろいます
動作確認の開発フロー
CLIで固める形に収束させると、検証の再現性が高くなります。
Inspectorを使った検証の流れ
- 1
CLIで接続を確かめる
--method initializeで、サーバーが起動してハンドシェイクを返し、期待した機能を申告しているかを1秒ほどで確かめます。結果は機械可読です。「動かない」の多くは、この段階で原因が見つかります。 - 2
Webクライアントで探索する
スキーマ駆動のフォームで実際にツールを呼び、横に出したProtocolタブと見比べて、挙動がおかしくなる条件を探します。
- 3
境界条件を試す
不正な入力、必須引数の欠落、同時呼び出し、HTTPサーバーなら新旧両方のプロトコル世代を試します。成功だけでなく、失敗が意図した形で返るかも確かめます。
- 4
CLIでアサーションに固定する
見つけた期待値を
--format jsonとjq -eでCIの検査にします。--stored-auth-onlyを付ければ、トークン切れで対話的なOAuthに入らず早く失敗します。
まとめ
Inspectorの価値は、失敗の原因をサーバー・認証・クライアントのどこに置くかを、実際のクライアントへ繋ぐ前に決められる点にあります。繋がらない原因がサーバー単体で再現するなら実装の問題で、Inspectorで通るのに繋がらないなら、クライアントの設定側に目を向ける合図です。
参照した一次ソース
この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。
- modelcontextprotocol.io/docs/2026-07-28/tools/inspector
- modelcontextprotocol.io/docs/2026-07-28/tools/inspector/web
- modelcontextprotocol.io/docs/2026-07-28/tools/inspector/cli
- modelcontextprotocol.io/docs/2026-07-28/tools/inspector/tui
- modelcontextprotocol.io/docs/2026-07-28/tools/inspector/configuration
- modelcontextprotocol.io/docs/2026-07-28/tools/inspector/authorization
- modelcontextprotocol.io/docs/2026-07-28/tools/inspector/recipes
- modelcontextprotocol.io/docs/2026-07-28/tools/debugging
- github.com/modelcontextprotocol/inspector