Claude Media
MCP Inspectorの新旧バージョン互換性の仕組み

MCP Inspectorの新旧バージョン互換性の仕組み

MCP Inspectorがサーバーをlegacy/modernの2世代に分けて扱う仕組みと、ログ・タスク・セッションなど機能ごとに挙動がどう変わるかを解説します。

MCP Inspectorのプロトコル世代設定とは何か

MCP Inspectorは、接続先サーバーが2026-07-28の仕様改訂より前(legacy)か、それ以降(modern)かprotocolEraという設定値で管理しています。トランスポート(stdioかHTTPか)とは独立した設定で、同じHTTP URLをlegacyとしてもmodernとしても検査できるのが特徴です。Web版・CLI・TUIのどのクライアントでも設定方法は共通で、Web版なら「Server Settings」、設定ファイルならprotocolEraフィールドで指定します。

この設定が必要になった理由は単純です。2026-07-28の改訂でinitialize/notifications/initializedのハンドシェイクが廃止され、代わりにすべてのリクエストが_metaにプロトコルバージョンとクライアント機能を積むステートレス方式に変わりました。旧仕様のサーバーはまだ大量に稼働しているため、デバッグツールであるInspectorは両方の話し方をサーバーごとに切り替えられる必要があります。

legacy・auto・modernの3つの接続モード

モード接続時の挙動
legacy(既定)接続時の挙動素のinitializeのみ。プロービングは一切行わない
auto接続時の挙動先にserver/discoverを試し、modern以外の応答ならフォールバックでinitialize
modern接続時の挙動2026-07-28のみに固定。フォールバックなしで非modernサーバーは失敗する

既定値がautoではなくlegacyである点は、公式が明確に理由を説明しています。デバッグツールが接続のたびに自動でプロービングを行うと、静かに待ち続けるlegacyのstdioサーバーに対してserver/discoverプローブが止まってしまい、しかも記録したいトラフィックの記録(トランスクリプト)を汚してしまうためです。automodernを選ぶのは利用者の明示的な操作にし、Protocolタブに映る内容が「自分が設定したクライアントの挙動どおりである」ことを保証しています。

接続が確立すると、ネゴシエートされた世代は接続ヘッダーと「Connection Info」に表示されます。modern接続ではserver/discovercapabilities(extensions含む)・instructionssupportedVersionsも返し、サーバー名とバージョンは結果の_metaio.modelcontextprotocol/serverInfoに載ります。

ログ・リソース購読はどう変わるか

ロギングの扱いは世代間で最も分かりやすい差が出る部分です。legacyではlogging/setLevelをセッション開始時に1回送るとセッションスコープでログレベルが固定され、Logsタブは「Set Active Level」セレクタで操作します。modernではlogging/setLevel自体が廃止され、リクエストごとに_meta["io.modelcontextprotocol/logLevel"]をスタンプする方式に変わりました。ログレベルをOffにするとlogLevelキー自体が省略され、同じツール呼び出しでもログが一切出ません。Inspectorのサーバーごとの既定値はdebug(最も詳細なレベル)で、必要ならmodernLogLevel: "off"で既定を戻せます。

リソース購読も同様です。legacyはresources/subscribeを送るだけのセッションフラグ的な扱いですが、modernはsubscriptions/listenという長命なストリームに置き換わり、購読が確認されるとnotifications/subscriptions/acknowledgedが返ります。Inspectorの「Subscriptions」セクションにはストリームの状態を示すバッジが追加され、Connecting...からListeningへ遷移する様子が見えます。ストリームが切れた場合、Inspectorはsubscriptions/listenを再送して自動的に再接続します。

Tasksタブの表示条件そのものが世代で変わる

Tasks(長時間実行タスク)の扱いは、UIタブの出し方自体が世代によって異なる珍しいケースです。legacyでは、サーバーがcapabilities.tasksを広告していればTasksタブが現れ、tasks/listで一覧を取得しtasks/getでポーリングします。完了したペイロードはブロッキングのtasks/resultで取得し、キャンセルはtasks/cancelです。

modernではTasksは拡張機能(io.modelcontextprotocol/tasks)として扱われるため、タブはcapabilities.tasksではなくネゴシエートされた拡張機能の有無でゲートされます。ツールをタスクとして実行するとtools/callCreateTaskResult(resultType: "task")を返し、Inspectorはtasks/getのみをポーリングします(tasks/listは存在しないため、Refreshはクライアントが既に把握しているハンドルを再ポーリングするだけです)。完了したタスクは結果をインライン化し、ブロッキングのtasks/result呼び出しは発生しません。追加入力が必要なタスクはinput_required状態になり、埋め込まれたelicitation(追加入力要求)がpending-requestモーダルに表示されます。回答はtasks/updateで送信され、次のポーリングで完了します。

Tasksがコア仕様ではなく拡張機能として先行実装された経緯はMCP Tasksが拡張機能に移った理由に詳しくまとめています。

modernのTasks実装を試す場合、公式のテスト用サーバー構成にはmodern_taskmodern_input_taskという2つのツールが含まれています。前者は単純な完了待ちのタスクを、後者はinput_requiredを経由して追加入力を求めるタスクを再現するためのもので、Tasksタブの2つの状態遷移(即完了とinput_required経由の完了)を1つの設定ファイルで両方確認できるようになっています。

複数ラウンドのツール結果(MRTR)はInspector上でどう進むか

modern世代では、ツールが最終結果の代わりにinput_requiredを返し、elicitation・sampling(サーバーからのモデル呼び出し要求)・roots/listのいずれかを埋め込めます。クライアントは埋め込まれたリクエストに応答し、新しいJSON-RPC idでtools/callをやり直してcompleteに到達するまで続けます。これがMulti-Round Tool Results(MRTR)です。

Inspectorはこの往復を手動で進行させる設計です。各ラウンドはinput_requiredタグの付いたpending-requestモーダルで一時停止し、利用者が回答するまで進みません。Protocolビューはこの一連のやり取りを個別の呼び出しとしてではなく、1つのMRTR会話としてまとめて表示します。なお、legacyで使われていたcollect_elicitationパターン(サーバーがserver.elicitInputを呼ぶ方式)は、modern接続ではサーバーからクライアントへのリクエストが許可されていないためエラーになります。MRTRはこのパターンの後継です。

各パラメータがどんなresultTypeを返すかの全体像はMCPのresultTypeフィールドが整理しています。

エラー表示・ヘッダーはmodernでどう詳しくなるか

modern世代ではMcp-*のHTTPヘッダー群と、より細かいJSON-RPCエラー分類が標準化されました。Inspectorはこれを2つのタブで役割分担して見せます。NetworkタブはHTTP層のビューで、ミラーリングされたMcp-*ヘッダーがハイライトされます。ProtocolタブはJSON-RPC層のビューで、仕様上の各エラーが総称的な失敗ではなく個別に描画されます。

代表的な4つのエラーコードは次のとおりです。

HTTPステータスJSON-RPCコード意味
400JSON-RPCコード-32020意味必須のミラーリングヘッダーが欠落・不一致(HeaderMismatch)
400JSON-RPCコード-32021意味リクエストにクライアント機能の宣言が欠けている
400JSON-RPCコード-32022意味サポート外バージョン(data.supportedに対応版が入る)
404JSON-RPCコード-32601意味メソッドが見つからない

なお、-32020は面によって出方が割れます。Mcp-Param-*ヘッダーのミラーリングはブラウザ版SDKの環境チェックでスキップされるため、Web版クライアントから該当ツールを呼ぶとヘッダーが欠落し厳格なサーバーは-32020(HeaderMismatch)を返しますが、Node上で動くCLI・TUIから同じツールを呼ぶと正しくミラーリングされエラーになりません。冒頭で触れた「設定方法はどのクライアントでも共通」というのはあくまでprotocolEraの指定方法の話で、この挙動自体はクライアントの実装差に起因します。

tools/call-32602で拒否された場合も、modernでは「Unknown Tool(存在しないツール名)」と「Invalid Parameters(それ以外の-32602)」を別々のエラーパネルとして描画します。両世代とも-32602自体は同じですが、legacyでは1つの汎用JSON-RPC失敗としか表示されず、メッセージを読んで原因を判別する必要があります。

セッションの有無が自作サーバーの実装に効いてくる

legacyのStreamable HTTP接続はサーバーが割り当てるセッションID(Mcp-Session-Id)を持ち、クライアントはHTTPのDELETEで明示的に破棄します。modernはセッションレスでリクエスト単位の設計になっており、セッションIDが無いためクライアントSDKはDELETEを送らず、切断はローカルで完結します。

これは自作のテストサーバーを書くときに実務上の制約になります。リクエストごとに使い捨てで構築されるstatelessなmodernハンドラーは呼び出し間で状態を保持できません。公式のテスト用サーバー構成でも、modern版のリソース購読設定はlegacy版と違ってupdate_resourceツールを持たせていません。使い捨てのサーバーインスタンスに対する変更が次の読み取りから見えなくなるためです。

言い換えると、modern世代のサーバーを実装するときはグローバル変数やインメモリキャッシュに頼った状態管理がそもそも成立しません。永続化が必要な処理は、サーバー側で発行した明示的なハンドルを通常のツール引数として受け渡す設計に切り替える必要があります。MCPのセッションID廃止がプロトコル全体に与える影響はMCPのセッションID廃止の理由にまとめています。

Inspectorで両世代を再現する最小手順

公式リポジトリのテストサーバーを使うと、legacy・modernそれぞれの挙動をローカルで再現できます。

git clone https://github.com/modelcontextprotocol/inspector
cd inspector && npm install && npm run build
cd clients/web && npm run test-servers:build

ビルド後、各セクションで挙げたtest-servers/configs/*.jsonをInspectorに読み込ませれば、ロギング・購読・Tasks・エラーコードのlegacy/modernそれぞれの挙動をその場で確認できます。自作サーバーがどちらの世代を前提に書かれているか迷ったときは、まずlegacyのまま接続してinitializeが通るかを確認し、通らなければautoに切り替えてserver/discoverの応答を見るのが最短の切り分け手順です。両方の応答を試したうえで、最終的にどちらの世代で運用するかをprotocolEraに固定しておくと、あとから見返したときの接続ログが読みやすくなります。

まとめ

MCP InspectorはprotocolEraという単一の設定値で、2026-07-28改訂前後のサーバーを同じツールで検査できるようにしています。既定は安全側のlegacyで、自動プロービングをするautoや強制的に最新版へ固定するmodernは利用者が明示的に選ぶ設計です。ロギング・リソース購読・Tasks・エラー表示・セッション管理のいずれも世代間で仕組みが大きく異なるため、自作サーバーをデバッグする際は接続前にどちらの世代で検査しているかを必ず確認してください。

この記事を共有:XはてブLinkedIn
MCP をもっと見る →