Claude Media
MCPのtools/list応答がttlMs/cacheScopeで拒否される問題と回避策

MCPのtools/list応答がttlMs/cacheScopeで拒否される問題と回避策

Claude CodeのMCPクライアントがttlMs/cacheScope付きのtools/list応答をスキーマ検証で拒否し、サーバーのツールが0件になる不具合の原因と回避策をまとめます。

MCPサーバーがtools/listの結果にttlMs(鮮度期限)やcacheScope(公開範囲)を含めて返すと、Claude CodeのMCPクライアントがスキーマ検証で応答全体を拒否し、サーバーが「接続済みなのにツールが0件」になる不具合が報告されています。報告者はクライアント側の検証が厳しすぎると見ていますが、サーバー側のパッチで解消した報告もあり、どちらに原因があるかは断定できません。回避策は2つあり、どちらも今すぐ試せます。

症状 — 接続済みなのにツールが1つも使えない

代表例として挙がっているのは、Roblox Studioが配布する公式MCPブリッジ(StudioMCP.exe)です。プロジェクトの.mcp.jsonでstdioサーバーとして登録すると、/mcpやsession_connectors_status相当の確認手段ではstatus: connectedと表示されるのに、tool_countが常に0のままになります。新しいセッションを開いても、アプリを再起動しても、OSを再起動しても症状は変わりません。

報告者はサーバー側の切り分けを自分で行っています。Claude Codeを介さず同じ起動コマンドに対して素のMCP JSON-RPCを直接送ったところ、サーバーは複数のプロトコルバージョンいずれでも100ミリ秒未満で28個のツールを返しました。この結果から、報告者はクライアント側の検証で応答が拒否されていると見ています(サーバーが送った値が仕様に厳密に沿っていたかどうかは、issueのログからは確定できません)。.mcp.jsonを書き直しても症状が変わらない、という報告もこの見立てと整合します。

ログ(%LOCALAPPDATA%\claude-cli-nodejs\Cache\<project>\mcp-logs-<server>\*.jsonl)には次のような検証エラーが残ります。

tools/list failed (Invalid result for tools/list: [
  { "path": ["ttlMs"], "code": "invalid_type", "message": "Invalid input" },
  { "code": "invalid_value", "values": ["public","private"], "path": ["cacheScope"], "message": "Invalid input" }
]); retrying in 250ms

ttlMsが数値として認識されずinvalid_typeになり、cacheScopeもinvalid_valueになっています。Claude Codeの公式ドキュメントによれば、tools/listのような能力検出リクエストは一時的なネットワークエラーやサーバーエラーに対して短い間隔を空けながら最大3回まで再試行される仕様です。ただし公式ドキュメントは、認証エラー・4xx応答・タイムアウトはこの再試行の対象外だと明記しています。先のログにあったretrying in 250msは、少なくとも一度は同じスキーマ検証エラーのまま再試行されたことを示しています。何度リトライしても同じ理由で失敗し続け、最終的にサーバーはツール0件のまま放置されます。

原因はv2 MCPクライアントランタイムの検証ロジック

Claude CodeのMCPクライアントには現在2つのランタイムがあります。v1はMCP TypeScript SDK 1.x、v2は同じコードをMCP TypeScript SDK 2.0上で動かしたもので、v2だけがMCPプロトコルリビジョン2026-07-28に対応します。この2026-07-28リビジョンで新設されたのが、tools/listなど一覧・読み取り系メソッドの結果に鮮度ヒントを載せるttlMsとcacheScopeです。MCPのttlMsとcacheScopeの仕様解説で扱っているとおり、ttlMsは「この結果を何ミリ秒新鮮とみなしてよいか」、cacheScopeは「public(誰でも再利用可)かprivate(同一認可コンテキストのみ)か」を示すフィールドです。

問題は、Roblox Studio側のMCPブリッジがttlMs・cacheScopeを含むtools/list応答を返しているのに対し、Claude Code側のv2クライアントが持つ検証スキーマがその値を受け付けなかった点にあります。ログのinvalid_typeはttlMsの型不一致、invalid_valueはcacheScopeの許容値不一致を示しており、フィールドが存在すること自体ではなく値の検証で弾かれています。ただしissueのログに残っているのは許容値の一覧(public/private)とエラーメッセージだけで、サーバーが実際に送った値がどう仕様から外れていたのかまでは確認できません。クライアント側の検証で応答全体が捨てられている、という点だけが確かな事実です。

クライアント側の検証で応答が拒否される不具合は、outputSchemaにdraft-07の$schemaを宣言したツールが「unsupported dialect」で拒否される件(MCP outputSchemaがdraft-07で拒否される問題)でも報告されています。

今すぐ試せる回避策

Anthropic側の修正が入る前に、利用者側で試せる回避策は2つ報告されています。

回避策内容注意点
CLIをv2.1.280へ固定する内容この不具合が起きる前のバージョンにダウングレードする注意点自動アップデーターが有効だと次回起動時に最新版へ戻ってしまう
MCP_PROTOCOL_NEGOTIATION=legacyを設定する内容v2クライアントのプロトコル2026-07-28プローブ自体を止め、旧プロトコルで接続させる注意点HTTP・claude.aiコネクタ・stdioサーバーすべてでプローブが無効になる

MCP_PROTOCOL_NEGOTIATIONはv2 MCPクライアントランタイムでのみ意味を持つ環境変数で、Claude Code v2.1.221以降が対象です。autoにするとHTTP・claude.aiコネクタ・stdioサーバーへプロトコルリビジョン2026-07-28のプローブを送り、応答が無ければ旧プロトコルで接続します。legacyを指定するとこのプローブ自体を全サーバーに対してスキップし、常に旧プロトコルのハンドシェイクで接続します。v2クライアントでネゴシエーションが成立した後のtools/listで失敗しているため、legacy指定で旧リビジョンの接続に戻すと症状が消える、という報告です。旧リビジョンで接続すればサーバーがこの2つのフィールドを付けない、という想定の回避策で(サーバー側の実装によっては挙動が変わる可能性があります)、利用者から解決報告があります。

# 環境変数で回避する場合(セッションごと)
MCP_PROTOCOL_NEGOTIATION=legacy claude

どちらのプロトコルで接続したかは、デバッグログのnegotiatedProtocolVersionで確認できます。新しいログファイルを見る必要はなく、先ほどのmcp-logs-<server名>/*.jsonlに残るConnection established with capabilitiesという行の中に、この値がJSONの1フィールドとして含まれています。legacy指定後にログを再確認し、この値が2026-07-28以外(旧リビジョン)になっていれば、ネゴシエーションが意図どおり無効化されています。値が変わらず同じエラーが続く場合は、この不具合とは別の原因(サーバー側の起動失敗や別の検証エラー)を疑ったほうがよく、ログの該当箇所を見比べながら切り分けます。

恒常的に固定したい場合は、settings.jsonのenvキーに追加します。

{
  "env": {
    "MCP_PROTOCOL_NEGOTIATION": "legacy"
  }
}

バージョンを固定してダウングレードする場合は、公式インストーラーにバージョン番号を渡します。

curl -fsSL https://claude.ai/install.sh | bash -s 2.1.280

ダウングレード後は自動アップデーターが有効だと次回の起動時に最新版へ戻ってしまうため、固定を保つにはDISABLE_AUTOUPDATER=1でバックグラウンドの自動更新チェックを止めます(claude updateの手動実行は引き続き使えます)。

組織全体に同じ回避策を配布する

複数の開発者が同じstdio MCPサーバー(社内ツール連携や、今回のようなゲーム開発ツールの公式ブリッジなど)に依存している場合、各人のsettings.jsonにMCP_PROTOCOL_NEGOTIATION=legacyを手作業で書かせるのは運用として崩れやすい方法です。組織で環境変数を配布する管理設定の仕組みそのものは、Managed MCPで許可リストを管理する記事で扱っている管理設定ファイル(managed settings)経由で行えます。管理設定に書いたenvの値はユーザー側の設定より優先されるため、修正版のリリースを待つ間、組織全体に同じ回避策を一括で強制できます。

ただし管理設定はallowedMcpServersやdeniedMcpServersのような許可リスト機能とは別の設定項目です。既存のMCPサーバー管理ポリシーを上書きしないよう、追加するenvキーの範囲を組織内で確認してから展開します。

サーバー側の対応を待つ場合の見分け方

この不具合はサーバーとクライアントの双方が動く組み合わせで再現するため、サーバー側のアップデートで解消するケースも報告されています。Roblox Studio側では、MCPブリッジを含むStudio本体のバージョン0.740.19.7400003でこの組み合わせに対応したパッチが配布され、CLI 2.1.183と書かれたコメントでツールが返るようになったとの報告があります(issueのスレッド内でバージョン表記に揺れがあります)。ただし別の利用者からは「接続はするがツールを呼び出せない」という残存症状も報告されており、サーバー側の対応だけで全員の環境が直るとは限りません。

自分の環境がこのパターンに当てはまるかは、ログの検証エラーで判断できます。mcp-logs-<server名>/*.jsonlにttlMsやcacheScopeを含むinvalid_type/invalid_valueエラーが出ていれば、この不具合と同じ症状です。エラーメッセージに別のフィールド名が出ている場合は、別の検証不一致(前述のoutputSchemaのdialect不一致など)を疑ったほうが早く解決します。

サーバー開発者の立場からすると、この不具合の再発を避ける確実な方法は自分では選べません。プロトコル2026-07-28のフィールドを返すと、一部のクライアント環境で拒否される報告があるためです。当面は、tools/listの結果にttlMs・cacheScopeを含めるかどうかをサーバー側の設定で切り替えられるようにしておくと、利用者側でクライアントの挙動に応じて調整しやすくなります。すでにこのフィールドを固定で返している場合は、ここまでの回避策(クライアント側のネゴシエーション無効化かバージョン固定)を利用者に案内するほうが早く復旧します。

まとめ

ttlMs・cacheScopeはMCPプロトコルリビジョン2026-07-28で新設された、tools/list応答の鮮度ヒントです。Claude Codeのv2 MCPクライアントはこのリビジョンに対応していますが、invalid_type/invalid_valueで応答が拒否され、サーバーのツールが恒久的に0件になる不具合が2026-09-26以降報告されています。クライアント側の検証が厳しすぎるとする報告者の見立てが有力ですが、サーバー側の実装に起因する可能性も残っています。CLI changelogのv2.1.283までの項目にも、この不具合を修正した記載はありません。今すぐ試せる回避策は、MCP_PROTOCOL_NEGOTIATION=legacyでプロトコルネゴシエーションを止めるか、v2.1.280へバージョンを固定することの2つです。他の修正を巻き戻さない分、先に試しやすいのは前者です。

この記事を共有:XはてブLinkedIn