Claude Code Tool Search実践ガイド — Deferred Toolsで実現するコンテキスト95%削減の仕組みと、MCP Server設計の最適解
MCP Serverを5つ接続したら、Claude Codeの応答が目に見えて遅くなった——そんな経験はないだろうか。
50以上のツールスキーマがすべてシステムプロンプトに展開されると、コンテキストウィンドウの大半がツール定義で埋まってしまう。Claude Codeはこの問題を「Deferred Tools + Tool Search」という仕組みで解決している。ツール名だけを軽量にリストし、必要になった瞬間にスキーマを取得する——いわば「遅延読み込み」だ。
本記事では、この最適化メカニズムの内部動作から、自作MCP Serverのdescription設計がTool Search精度に直結する理由、そして実際の運用で踏むハマりポイントまでを解説する。
なぜTool Searchが必要なのか — ツール爆発問題の実態
全ツールスキーマ展開のコスト計算
Claude Codeに接続されたツールは、通常であれば会話開始時にJSON Schemaとしてシステムプロンプトに展開される。1ツールあたりの定義は、パラメータの数や説明文の長さにもよるが、平均200〜500トークンを消費する。
仮に50ツールを接続した場合、それだけで1万〜2.5万トークンがシステムプロンプトを占有する計算になる。Sonnetの200Kコンテキストウィンドウであっても、ユーザーのコードや会話履歴に使える領域が大きく圧迫されるのは明らかだ。
コンテキスト汚染がもたらす3つの弊害
ツール定義がコンテキストを圧迫すると、以下の3つの問題が同時に発生する。
- 推論精度の低下: コンテキストの大部分が無関係なツール定義で埋まると、LLMが本来集中すべきユーザーの指示やコードに対する注意が分散する
- 応答速度の低下: 入力トークン数が増えれば、処理時間もそれに比例して増加する
- 料金の増加: API利用の場合、入力トークンに対して課金されるため、使いもしないツール定義のために余分なコストが発生する
この3重苦を解決するのがDeferred Toolsだ。Deferred Toolsでは、ツール名だけがsystem-reminderに軽量リストとして表示される。1ツールあたり約10〜20トークンで済むため、50ツールでも500〜1000トークン程度に収まる。正直、初めてこの仕組みを知ったときは「なぜ最初からこうしなかったのか」と思った。
Claude Code起動時に以下のようなメッセージを見たことがあるはずだ。
<system-reminder>
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:
AskUserQuestion
WebFetch
WebSearch
mcp__my-server__create_item
mcp__my-server__delete_item
mcp__my-server__list_items
...
</system-reminder>
名前だけが並び、パラメータ定義は一切含まれていない。これがDeferred Toolsの「軽量リスト」だ。
Deferred Toolsの仕組み — 2段階ロードアーキテクチャ
通常ツール vs Deferred Toolの違い
Claude Codeのツールは2種類に分かれる。
| 通常ツール | Deferred Tool | |
|---|---|---|
| 会話開始時 | 完全なJSON Schemaがfunctionsブロックで提供 | 名前のみsystem-reminderにリスト |
| 即座に呼び出し | 可能 | 不可(InputValidationError) |
| スキーマ取得 | 不要 | ToolSearchで事前取得が必要 |
全ツール定義の合計トークン数が閾値(推定10Kトークン前後)を超えると、自動的にdefer_loadingが有効化される。この判定はClaude Codeが内部的に行うもので、ユーザーが明示的にON/OFFする設定は存在しない。
ToolSearchによるオンデマンドスキーマ取得
Deferred Toolを使うには、まずToolSearchでスキーマを取得する必要がある。ToolSearchには3つのクエリ形式がある。
// 1. select指定 — 正確なツール名で直接取得(最も確実)
ToolSearch({ query: "select:WebFetch,WebSearch", max_results: 5 })
// 2. キーワード検索 — 曖昧マッチでツールを探す
ToolSearch({ query: "slack send message", max_results: 5 })
// 3. プレフィクス+ランキング — 名前にプレフィクスを含むものを優先
ToolSearch({ query: "+mcp__analytics report", max_results: 5 })
取得されたスキーマは通常ツールと同一のfunctionsブロック形式で返される。以降はパラメータを指定して普通に呼び出せる。
// ToolSearchの返却例
<functions>
<function>{"description": "Fetch content from a URL...",
"name": "WebFetch",
"parameters": {"type": "object", "properties": {...}, ...}}
</function>
</functions>
defer_loading判定の閾値
閾値は公式に明示されていないが、接続ツール数が少ない(10個以下程度)場合はすべて通常ツールとして展開される。MCP Serverを複数接続してツール総数が増えたときに初めてdefer_loadingが発動する。
少数ツールのMCP Serverを1つだけ使っている場合は、この仕組みを意識する必要はない。
自作MCP Serverのツール設計 — Tool Search精度を左右するdescription最適化
descriptionが検索精度に直結する理由
Tool Searchのキーワード検索は、ツール名とdescriptionを対象にマッチングを行う。つまり、descriptionの書き方が検索精度を直接左右する。
以下は良い例と悪い例の比較だ。
// 悪い例: 曖昧で検索にヒットしにくい
server.tool("process", "Process the data", { ... }, async (params) => {
// ...
});
// 良い例: 動詞+目的語で明確、検索キーワードが含まれている
server.tool("create_user_account",
"Create a new user account with email and role assignment. " +
"Validates email format and checks for duplicates before creation.",
{ ... },
async (params) => {
// ...
}
);
ツール粒度の設計指針
1ツール1責務が基本原則だ。「何でもできる万能ツール」は、Tool Searchでどのクエリにも中途半端にマッチしてしまい、結果として適切なツールが検索上位に来ない。
# 悪い例: 1つのツールに複数の責務
@server.tool()
def manage_database(action: str, table: str, data: dict):
"""Manage database operations (create, read, update, delete)"""
...
# 良い例: 責務ごとに分離
@server.tool()
def insert_record(table: str, data: dict):
"""Insert a new record into the specified database table."""
...
@server.tool()
def query_records(table: str, filter: dict):
"""Query records from a database table with optional filters."""
...
命名規則のベストプラクティス
MCP Serverのツールはmcp__サーバー名__ツール名の形式で命名される。この構造を活かすポイントは以下の通り。
- descriptionの1行目に動詞+目的語で要約を書く(例: "Create a new user account")
- 詳細は2行目以降に追記する
- 同一サーバー内の類似ツールはツール名で明確に区別する(
list_usersvslist_roles) max_resultsのデフォルトは5なので、同じサーバーに似た名前のツールが6つ以上あると検索漏れのリスクがある
SkillsのDeferred LoadingとTool Searchの違い
Claude Codeには、Deferred Toolsとは別にSkillsという仕組みがある。両者はsystem-reminderにリスト表示される点で似ているが、根本的に異なるメカニズムだ。
| Tool Search (Deferred Tools) | Skills | |
|---|---|---|
| 取得対象 | JSON Schema(ツール定義) | プロンプト全体 |
| 呼び出し方 | ToolSearchツール | Skillツール |
| 呼び出し後 | パラメータを渡してツール実行 | プロンプトが会話に注入される |
| 用途 | ツールの遅延読み込み | 専門知識・ワークフローの遅延読み込み |
Anthropic APIにはtool_search_toolというサーバーサイドの機能も存在する。Claude CodeのToolSearchは、これを内部的にラップした実装と考えてよい。
注意すべきは、ツール数が少なくてもSkillsが大量にあればsystem-reminderは肥大化するという点だ。Deferred ToolsとSkillsの両方が遅延読み込みで動いている前提で、全体のコンテキスト予算を設計する必要がある。
実践Tips — よくあるハマりポイントと対処法
「InputValidationError」が出たら
最もよくあるエラーがこれだ。Deferred Toolを直接呼び出すと発生する。
// エラーになるパターン
mcp__my-server__create_item({ name: "test" })
// → InputValidationError: tool schema not loaded
// 正しいパターン: 先にToolSearchでスキーマを取得
ToolSearch({ query: "select:mcp__my-server__create_item", max_results: 1 })
// → functionsブロックでスキーマが返却される
// → 以降は通常通り呼び出し可能
mcp__my-server__create_item({ name: "test" })
// → 成功
Claude Codeを普通に使っていれば、AIが自動的にToolSearchを呼んでからツールを実行してくれるため、ユーザーが意識する場面は少ない。しかし、プロンプトで明示的にツールを指定した場合や、カスタムスキルの中でツールを参照する場合には注意が必要だ。
Tool Searchで目的のツールがヒットしない場合
以下のチェックリストを確認してほしい。
select:で正確な名前を指定する: キーワード検索は曖昧マッチなので、意図しないツールが返ることがある。確実に取得するならselect:ツール名を使う- descriptionを見直す: MCP Serverのツール定義で、検索キーワードとなりうる単語がdescriptionに含まれているか確認する
- ツール名変更時のキャッシュ: MCP Serverのツール名を変更した場合、Claude Codeの再起動が必要になることがある
- 不要なツールを無効化する: Claude Codeの
settings.jsonでMCP Serverごとにツールの有効/無効を制御できる。使わないツールをオフにすれば、閾値以下に抑えてそもそもdefer_loadingを回避する戦略も取れる
// ~/.claude/settings.json での制御例
{
"mcpServers": {
"my-server": {
"command": "node",
"args": ["server.js"],
"disabledTools": [
"mcp__my-server__rarely_used_tool",
"mcp__my-server__debug_only_tool"
]
}
}
}
個人的には、このdisabledToolsによる間引き戦略がもっと知られてもいいと思う。全ツールを有効にしたまま「なぜか遅い」と悩むケースは意外と多い。
まとめ
MCP Serverのエコシステムが拡大するほど、Tool Search / Deferred Toolsの理解は必須になる。押さえるべきポイントは3つだ。
- ツール数が増えたら自動的にdefer_loadingが効く。パフォーマンス劣化を感じたら、まずツール総数を確認する
- 自作MCP Serverではツール名とdescriptionの設計がTool Searchの検索精度を決める。1行目に動詞+目的語の要約、1ツール1責務を徹底する
- 不要なツールは
settings.jsonで無効化し、コンテキスト予算を本当に必要なツールに集中させる
これらを意識するだけで、50+ツール環境でもClaude Codeの推論精度と応答速度を維持できる。ツールが増えてきたなと感じたら、まずはsystem-reminderの冒頭を確認してみてほしい。"The following deferred tools are now available via ToolSearch"というメッセージが出ていれば、この最適化はすでに動いている。
