MCPに接続できたのにツールが出ない?tools/list・権限・実行エラーの切り分け
MCPサーバーが起動・接続済みでもツールが見えないときの確認順。tools/listの空応答・ページング、Codexの許可リスト、stdioのstdout混入、認証とtool実行エラーを分け、原因を絞る記録テンプレートを紹介します。
公開 2026.10.12 / 更新 2026.10.12
この記事のポイント
- MCP serverがtools/listで返した集合と、hostが最終的に見せる集合、tools/callの結果は別々に記録する
- tools/listが空でも仕様上は有効で、requestごとの認証・権限によって返る集合が変わる場合がある
- nextCursorはopaqueな値として全ページをたどり、空文字をページ終端と誤判定しない
- Codexではenabled_toolsとdisabled_toolsの適用順を確認し、他のhostへCodex固有設定を当てはめない
- protocol errorとresult.isErrorを分け、発見の失敗とtool実行の失敗を混ぜない
先に結論:接続済みでも、三つの確認結果は別
MCP serverの接続表示は、プロセスやtransportがつながったことを示す材料です。serverが何を返したか、hostが何を公開したか、tool callが成功したかまでは一度に証明しません。次の三段階を、同じserver・host・承認済みの認証条件で記録してください。
| 段階 | 確認するもの | その結果だけでは分からないこと |
|---|---|---|
| serverの応答 | tools/listの応答と、ページがあれば全ページのtool名・件数 | hostがそのtoolを採用・表示するか |
| hostが公開する一覧 | 対象host・session・profileで見えるtool名・件数 | toolの実行結果や上流サービスの権限 |
| toolの呼び出し | 承認済みのread-only toolの結果と、protocol errorかresult.isErrorか | 別のidentity・別host・別versionでの動作 |
serverまたはhostの一覧・件数を同じ条件で確認できない場合は「未観測/不明」と記録します。接続表示や片方の画面から、もう片方の一覧や件数を推定しないでください。
症状から次の確認先を選ぶ
| 症状 | 見る証拠 | 次の安全な確認 |
|---|---|---|
| serverが起動しない、すぐ終了する | stdioならprocessの終了状態とstderr、HTTPなら接続先の応答 | command・args・cwd・hostが使うruntime・startup timeoutを対象serverだけで確認する |
| HTTPは200だが一覧が出ない | 目的のMCP endpointからtools/list形式の応答が来ているか。HTMLやhealth応答ではないか | hostが表示するendpointとtransportを突き合わせ、Authorization headerやbodyを共有せず応答の種類だけを見る |
| tools/listが空 | 応答がprotocol上の正常な空一覧か、同じrequestに使われた認証role / scope | 空一覧は有効な結果として扱い、認証主体・許可scopeごとにserver側の公開条件を確認する |
| 欲しいtoolが見当たらない | nextCursorの有無、次ページを含めた全件数 | cursorの形式を読まずに次のrequestへ引き継ぐ。空文字もcursorとして処理し、値のtruthinessで打ち切らない |
| server側にはあるがhostに出ない | 同一のserver listとhost公開list、対象profile・server単位のtool policy | Codexならenabled_toolsの許可範囲とdisabled_toolsの除外を順番に確認し、他hostではそのhostの文書を使う |
| 追加・変更したtoolだけ古い | serverがlist-change通知をサポートするか、host / SDKが通知やcache更新を扱うか | 対象hostが文書化するrefresh方法を一つのsessionに限定して試す。全serverや全設定を一括変更しない |
| 一覧にある名前を呼ぶとunknown tool | request先server、tool名、現在のhost list、JSON-RPC protocol errorの種類 | 一覧を同じhostで再確認してから、名前・serverの取り違えや古いcacheを調べる |
| 呼び出し結果にresult.isError=true | tool実行後のエラー種別、入力schema、業務条件、上流認証 | tool execution errorとしてserver側の安全な診断情報を見る。一覧の再取得だけで直るとは決めつけない |
MCP 2026-07-28仕様では、serverがtools.listChanged capabilityを宣言し、clientがtoolsListChangedを有効にしたsubscriptions/listen streamを開いている場合に、tools list変更通知が送られます。hostやSDKが通知を受け取って一覧cacheを更新するか、どの操作で再取得するかは実装とrevisionを確認してください。
Python SDKで自作serverを実装している場合に限る診断例として、意図したapp/server instanceにtoolを登録しているか、同じtool名を重複登録していないかを確認します。これはPython SDKの実装確認であり、他のSDKやhost全般に共通する原因とは限りません。
HTTP 200だけではMCPのtool一覧を取得できたとは限りません。HTMLの案内ページ、health endpoint、認証用の応答、正しいendpointのJSON-RPC応答は別です。stdioでも、標準出力はprotocol messageの経路です。通常ログをstdoutへ混ぜず、仕様に沿ってstderrへ分けます。stderrに出力があること自体はserver errorの証拠ではありません。
Codexの許可・拒否リストは、serverの返答と分ける
CodexのMCP設定では、`enabled_tools`は利用可能toolのallow list、`disabled_tools`はdeny listで、deny listがallow listの後に適用されます。そのためserverのtools/listに名前があっても、Codexが公開する一覧に残るとは限りません。これはCodex host固有の設定です。別のMCP clientで同じkey名や順序を仮定せず、plugin由来serverでは設定の所有場所も確認します。
- 対象host・server・profileで、設定が実際に読み込まれているかを確認する
- allow listに欲しいtoolがあるか、deny listに同じ名前が残っていないかを分けて見る
- 修正が必要でも、許可するのは目的に必要なread-only toolに限定し、全toolを一括許可しない
- serverの起動timeoutとtool実行timeoutを混同せず、実行段階に合う項目だけを確認する
protocol errorとtool execution errorを分ける
| 見える結果 | 失敗した段階 | まず見るもの |
|---|---|---|
| JSON-RPC error(例: unknown tool) | requestの形式・名前・server側の処理などprotocol段階 | hostからどのserverへ、どの名前で呼んだか。現在の一覧とrequest先 |
| result内のisError=true | toolが実行結果を返す段階 | 入力schema、toolの業務条件、server自身の上流接続・権限 |
| transport / timeout error | 接続や処理時間の段階 | endpoint / process / startup timeout / tool timeoutのどこで失敗したか |
上表はMCP 2026-07-28仕様の分類で、unknown toolはJSON-RPC errorの例です。一方、参照したPython SDKのcall_toolはUnknown toolを例外ではなく結果として返し、Python側ではresult.is_errorを確認します。メッセージだけで判定せず、実際のJSON-RPC error、wire上のresult.isError、SDKやhostの属性を分けて観測し、このPythonの挙動を他のSDKやhostへ一般化しないでください。protocol errorも必ずしも一覧不一致ではありません。認証はidentity・scope・到達段階から確認し、権限全体を広げないでください。
仮定例:観測が違うと、直す場所も変わる
次の二つは診断の順番を示す仮定例で、実在するserverやログの報告ではありません。実際の件数やエラーを推定する材料には使わず、手元の同一条件で得た記録に置き換えてください。
| 仮定例 | 観測 | 切り分け |
|---|---|---|
| A:Codexの一覧にtoolがない | 同じ承認済みroleのserver listにはread-onlyの`catalog.search`がある。Codexのenabled_toolsにもあるが、disabled_toolsにも同じ名前がある。 | Codexではdenyがallowの後に適用される。serverの返答ではなくCodexの実効policyで落ちている仮説を確かめ、変更が承認されている場合にだけそのtoolの範囲を直す。 |
| B:一覧にはあるが実行に失敗 | host listに`catalog.search`があり、承認済みの小さなread-only callはresult.isError=trueで上流のaccess拒否を返した、という仮定。 | 発見は完了しているので、入力schemaと上流identityの読取権限をserverの安全な診断で確認する。toolを再登録したり、全scopeへ広げたりしない。 |
再現条件を安全に残す記録カード
再調査では生のconfigや通信ログを貼らず、項目名・件数・分類だけを残します。認証値、header、内部endpoint、query、tool payload、個人を識別する情報は記録カードに含めません。
host / version:
server / SDK version:
protocol revision (as shown in safe logs):
transport: stdio / Streamable HTTP / other
auth role label (no account identifier):
last successful stage: connect / tools-list-all-pages / host-list / tool-call
server tool count (all pages; unknown if unavailable):
host exposed tool count (unknown if unavailable):
requested tool name:
sanitized error category:
changed setting names only:
approved read-only retest outcome:解決と判断できる条件
同じ承認済みidentity・設定・host versionで、必要性を確認したread-only toolが最終host listに現れ、承認された小さなtest callから期待する結果を得られたことを確認します。接続成功、HTTP 200、tool名が一度表示されたことだけでは完了にしません。production writeを試したり、原因不明のまま再installしたり、securityやapprovalを広く無効にしたりする必要はありません。
MCP toolが見えないときのFAQ
MCP serverの接続表示が成功なら、toolも使えますか?
接続表示はtoolの取得や実行まで証明しません。serverが返す全ページ、対象hostが公開する一覧、承認済みtool callの結果を順に確認します。
tools/listが空ならserverの故障ですか?
必ずしも故障ではありません。MCP仕様では空のtool集合は有効で、requestに使った認証によって見えるtoolが変わる場合もあります。まずresponseがprotocol上正常かと、認証roleごとの公開条件を確認してください。
MCP 2026-07-28仕様でinitialize handshakeが見えないのは異常ですか?
2026-07-28仕様はstatelessとして各requestに必要なmetadataを持たせます。そのrevision同士なら、旧initialize / initialized handshakeが見えないことだけで異常と判断しません。host・server・SDKが実際に対応するrevisionとlifecycleは別途確認します。
関連記事
- MCPとは?AIエージェントに外部ツールをつなぐ仕組みと注意点
MCPはAIに外部ツールをつなぐ共通プロトコルです。仕様とCodexの設定・認証・tool権限を分けて、安全な導入判断を整理します。