はじめに
Claude Code on the web のセッションを開始した直後、システムから渡される情報の中に「107個のツールがToolSearchの後ろに隠れていて、スキーマ未読み込みの状態」という記述があった。ツールを増やしすぎるとコンテキストが圧迫される問題は知られているが、実際にどういう仕組みで・どのくらいの規模で「隠されている」のかを、本セッション自身の挙動とAnthropic公式ドキュメントを突き合わせて確認する。
この記事で学べること
- ツール数増加がなぜ問題になるか(コンテキスト圧迫と選択精度低下の2つ)
- Claude Codeが実際にどのツールを「未読み込み」のまま起動するか(本セッションでの実測)
- Anthropic Messages APIの
tool_search_tool_regex_20251119/tool_search_tool_bm25_20251119の実装方法 - 導入時に押さえておくべき制約・設計のコツ
対象読者
- MCPサーバーを複数接続してClaude Code / Claude APIを使っている方
- ツール数が増えてコンテキストが圧迫されている、ツール選択の精度が落ちていると感じる方
前提環境(実機検証)
- 実行環境: Claude Code on the web(クラウド実行環境・リモートセッション)
- モデル: claude-sonnet-5
- 接続MCPサーバー: GitHub MCP、Slack MCP 等
- 検証: 本記事のセッション内で
ToolSearchを実際に呼び出して確認(2026-07-16)
TL;DR
- Anthropic公式によると、GitHub・Slack・Sentry・Grafana・Splunkを繋いだ典型的な構成では、ツール定義だけで 約55,000トークン を消費するケースがあり、Tool Searchはこれを 85%以上削減 する
- ツール選択の精度は、利用可能なツールが 30〜50個を超えると低下し始める(同ドキュメント)
- 本セッションでも起動直後に 107個のツール(GitHub関連60個・Slack関連18個・Claude Code組み込み29個)が「名前だけ」渡され、スキーマ未読み込みの状態だった。
ToolSearchで検索して初めて呼び出し可能になる実装を、このセッション自身で確認した - 同じ設計思想がAnthropic Messages APIには
defer_loading: trueとして公式提供されている。regex版(tool_search_tool_regex_20251119)とBM25版(tool_search_tool_bm25_20251119)の2種類がある
背景・課題
MCPサーバーを複数接続すると、各ツールのname・description・input_schemaが軒並みコンテキストウィンドウに乗る。Anthropicの公式ドキュメント「Tool search tool」は、この問題を次の2つに整理している。
A typical multiserver setup (GitHub, Slack, Sentry, Grafana, and Splunk) can consume ~55k tokens in definitions before Claude does any work.
- コンテキスト圧迫: 何も作業していない時点でツール定義だけで数万トークンを占有する
- 選択精度の低下: 利用可能なツールが30〜50個を超えると、Claudeが適切なツールを選ぶ精度自体が落ちる
Tool Searchは「全部のツールを最初から読み込む」のではなく「使う可能性が高いツールだけその場で検索・展開する」ことでこの2つを同時に解決する仕組みとして提供されている。
実際に確認してみた(本セッションの実機検証)
① 起動直後、107個のツールが「名前だけ」渡されていた
セッション開始直後、システムリマインダーには次のような一文があった。
The following deferred tools are now available via ToolSearch. Their schemas
are NOT loaded — calling them directly will fail with InputValidationError.
Use ToolSearch with query "select:<name>[,<name>...]" to load tool schemas
before calling them:
CronCreate
CronDelete
...
実際にリストアップされていたツールを数えると合計107個で、内訳は次の通りだった。
| カテゴリ | 件数 | 具体例 |
|---|---|---|
| Claude Code 組み込みツール | 29 |
Monitor, WebSearch, WebFetch, TaskCreate, SendMessage 等 |
| GitHub MCP | 60 |
create_pull_request, merge_pull_request, list_issues 等 |
| Slack MCP | 18 |
slack_send_message, slack_read_thread, slack_search_users 等 |
この時点でこれらのツール名を直接呼び出そうとすると、パラメータのスキーマ自体がまだクライアント側に存在しないため InputValidationError になる(システムリマインダーに明記されている挙動)。
② ToolSearch で実際に呼び出し可能にした
本セッションの作業中、GitHub上でPRを作成・マージする必要が出たタイミングで、以下のクエリを投げた。
ToolSearch({ query: "select:mcp__github__create_pull_request,mcp__github__merge_pull_request" })
返ってきたのは各ツールの完全なJSON Schema(owner / repo / title / head / base などのパラメータ定義を含む)で、この時点で初めて mcp__github__create_pull_request を実際に呼び出せるようになった。実際に、このツールを使ってPRを1件作成・マージするところまで問題なく完了している。
続けて、まったく別カテゴリの3ツールをカンマ区切りでまとめて指定してみた。
ToolSearch({ query: "select:WebSearch,WebFetch,Monitor" })
こちらも1回のクエリで3ツール分の完全なスキーマが同時に返ってきた。select: プレフィックスに複数ツール名をカンマ区切りで渡せば、まとめて読み込めることが確認できた。
つまりClaude Codeは、「使う可能性のあるツールを全部読み込む」のではなく「使うと決まった/使いそうなツールだけを、その場で読み込む」構造で動いている。
仕組みの解説(Anthropic公式ドキュメントより)
上で確認したClaude Code側の挙動と同じ設計思想が、Anthropic Messages APIには tool_search_tool として公式に提供されている。Claude Code自身のToolSearch実装の内部詳細(regex/BM25のどちらの方式を使っているか等)は公開されていないため、以下はあくまでAPI版の公式仕様として区別して説明する。
defer_loading の使い方
tools配列の各ツール定義に defer_loading: true を付けると、そのツールは初期コンテキストから除外される。Tool Search用ツール自身(tool_search_tool_regex_20251119 または tool_search_tool_bm25_20251119)だけは非遅延にしておく必要がある。
Tool Search用ツール自身の定義(非遅延):
{
"type": "tool_search_tool_regex_20251119",
"name": "tool_search_tool_regex"
}
defer_loading: true を付けたツールの定義例:
{
"name": "get_weather",
"description": "Get the weather at a specific location",
"input_schema": {
"type": "object",
"properties": {
"location": { "type": "string" },
"unit": { "type": "string", "enum": ["celsius", "fahrenheit"] }
},
"required": ["location"]
},
"defer_loading": true
}
Claudeがツールを検索すると、APIは tool_reference ブロックを返し、内部でそれを完全なツール定義に自動展開する。この展開はプロンプトの前置き(プレフィックス)には触れないため、プロンプトキャッシュは維持される(公式ドキュメント「Prompt caching」節)。
regex版とBM25版の違い
| 項目 | regex版 | BM25版 |
|---|---|---|
| バージョン文字列 | tool_search_tool_regex_20251119 |
tool_search_tool_bm25_20251119 |
| クエリ形式 | Python re.search() 相当の正規表現(大文字小文字区別なし) |
自然言語 |
| 最大長 | 200文字 | 500文字 |
| クエリ例 | "get_.*_data" |
「天気を取得するツール」 |
上限・エラー(公式ドキュメント)
-
defer_loading: trueを付けられるツールは1リクエストあたり最大 10,000個 - 1回の検索で返る候補は既定で最大 5個
- 全ツールを遅延指定すると400エラー(
At least one tool must have defer_loading=false. All tools cannot be deferred.) - 存在しないツール名を参照すると400エラー(
Tool reference 'unknown_tool' not found in available tools) - 検索自体の失敗は200 OKの中で
tool_search_tool_result_errorとして返り、error_codeはinvalid_tool_input/unavailable/too_many_requests/execution_time_exceededの4種類 -
defer_loading: trueを付けたツールにはcache_controlを同時に設定できない(400エラー。キャッシュのブレークポイントは非遅延ツール側に置く)
使うときのコツ(公式の推奨)
- 最も使用頻度が高い3〜5個のツールは遅延させない(検索を挟まず即座に呼べるようにする)
- ツール名に
github_やslack_のような一貫したプレフィックスを付けると、1回の検索でグループごとヒットしやすくなる。本セッションで実際に確認したmcp__github__*という命名も同じ思想で設計されている - descriptionにユーザーが使いそうなキーワードを含める(Claudeは名前・説明・引数名・引数説明のすべてを検索対象にする)
- ツールが10個未満、全ツールが毎リクエスト使われる、または定義の合計が100トークン未満程度なら(いずれか1つでも該当すれば)、Tool Searchを使わず標準のツール呼び出しのままでよい、と公式が明言している
著者視点の発見ポイント
ドキュメントを読むだけでは「トークンが85%減る」という数字は抽象的だったが、実際に本セッションのシステムリマインダーを数えてみると107個というかなり具体的な数だった。特に意外だったのは、GitHub MCPだけで60個ものツールが定義されていた点で、これを毎ターンのコンテキストに全部乗せていたら、ツール1個あたりの定義が数十〜100トークン程度としても優に数千トークン規模がプロンプトの先頭に常駐することになる。Tool Searchの仕組みは「使われないツールに精度とトークンを奪われない」ための設計であり、MCPサーバーを複数繋ぐ運用では既定でオンにしておいて損はない、というのが実際に触ってみた実感である。
まとめ
- ツール数が増えるとコンテキスト圧迫と選択精度低下の両方が起きる(公式実証: 30〜50個超で精度低下、55kトークン規模まで定義が肥大するケースあり)
- Claude Codeでは実際に、107個のツールが起動時「名前だけ」の状態で渡され、
ToolSearchで検索して初めて呼び出し可能になる構造を本セッションで確認した - 同じ思想がAnthropic Messages APIには
tool_search_tool_regex_20251119/tool_search_tool_bm25_20251119として公式提供されている。defer_loading: trueを付けるだけで導入できる - 3〜5個の頻出ツールは遅延させない、命名にプレフィックスを揃える、が実運用のコツ
参考リンク
- Tool search tool | Claude Platform Docs — 仕組み・コード例・エラー一覧の一次情報
- Introducing advanced tool use on the Claude Developer Platform | Anthropic — Tool Search登場の背景