MCPツール設計:AIがツールを正確に選ぶ記述の書き方
この記事の要点
ClaudeがMCPツールを正確に選ぶためのツール説明文の書き方を解説。曖昧な記述が誤選択を招くメカニズム、境界の明確化、エラー応答の構造化、ツール数の最適化まで実践的に紹介します。
結論
Claudeがどのツールを呼び出すかは、ツールの説明文(description)によってほぼ決まります。「顧客情報を取得する」「注文情報を取得する」のように説明が似ていると、Claudeは間違ったツールを呼び出し続けます。説明文に「いつ使うか・いつ使わないか」の境界を明記することが、ツール選択精度を上げる最も効果的な施策です。
ツール選択がなぜ説明文で決まるのか
Claudeはツールを選ぶとき、コードの実装を見ることができません。見えているのはツールの名前と説明文だけです。「どのツールを使うべきか」の判断は、100%説明文の内容に依存しています。
説明文が薄いと何が起きるか、実例で見ます。
悪い例:
get_customer - "顧客情報を取得する"
lookup_order - "注文情報を取得する"
両方とも「何かを取得する」ツールで、入力として顧客IDや注文IDのような「IDに見えるもの」を受け取ります。ユーザーが「注文#12345を確認して」と入力した場合、Claudeはlookup_orderではなくget_customerを呼んでしまうことがあります。「#12345」が顧客IDにも見えるからです。
良い例:
get_customer - "顧客プロフィールを取得する。使用する場面: メールアドレス・電話番号・会員ステータスが必要なとき。
入力: customer_id(メールアドレスや電話番号では使用不可)。
使わない場面: 注文履歴・商品情報が必要なとき。"
lookup_order - "注文の詳細を取得する。使用する場面: 注文番号(#で始まる8桁)が与えられたとき。
入力: order_id(例: '#12345')または confirmation_code(英数字6文字)。
使わない場面: 顧客の個人情報が必要なとき(そちらはget_customerを使う)。"
説明文に含めるべき5つの要素
効果的なツール説明文には次の5要素を含めます。
| 要素 | 内容 | 書き方の例 |
|---|---|---|
| 目的 | このツールが何をするか | 「注文の配送ステータスと追跡情報を返す」 |
| 使う場面 | どんなクエリのときに呼ぶか | 「ユーザーが『荷物はどこ』『いつ届く』と聞いたとき」 |
| 入力フォーマット | 何を渡せばよいか | 「order_id: ’#‘で始まる8桁の数字文字列」 |
| エッジケース | 注意すべき入力の例外 | 「キャンセル済み注文も取得可能だが追跡情報はnullになる」 |
| 使わない場面 | どんなときは他のツールを使うか | 「返金処理にはprocess_refundを使う(このツールは読み取り専用)」 |
「使わない場面」を書くのは、類似ツールが複数ある環境で特に効果があります。ツール同士の境界を明示することで、Claudeが迷う余地を減らせます。
類似ツールが複数ある場合の設計
同じような機能を持つツールが複数あるとき、名前や説明が近いと誤選択が起きやすくなります。
例えば、文書分析用に次のような2つのツールがあったとします。
悪い設計:
analyze_content - "コンテンツを分析する"
analyze_document - "ドキュメントを分析する"
この2つはほぼ同じ説明で、Claudeがどちらを使えばいいか判断できません。
良い設計:
extract_web_results - "ウェブ検索結果のHTMLから記事タイトル・URL・要約を抽出する。
対象: 検索エンジン結果ページのHTML。
使わない場面: PDF・Wordファイル・内部データベースには使用不可。"
analyze_document - "PDF・Word・テキストファイルの内容を構造化して抽出する。
対象: ファイルパスまたはbinary content。
使わない場面: ウェブURL・HTMLには使用不可(そちらはextract_web_resultsを使う)。"
名前を変えて目的を明確にし、お互いを参照することで境界が明確になります。
ツール数を絞る:多すぎると選択精度が下がる
直感に反しますが、エージェントに渡すツールは少ない方が選択精度が上がります。
18個のツールを持つエージェントと4〜5個のツールを持つエージェントを比べると、18個の方が明らかに誤選択が増えます。ツールが増えるほど「この状況ではどれを使えばいいか」という選択の複雑さが増すためです。
また、専門外のツールを持つと誤使用が起きます。例えば「統合・分析エージェント」にウェブ検索ツールを渡すと、分析すべき場面で自分でウェブ検索を始めることがあります。
推奨する設計は「役割に応じたツールセット」です。
顧客サポートエージェント → get_customer, lookup_order, process_refund, escalate_to_human(4個)
リサーチエージェント → web_search, fetch_url, save_note(3個)
統合エージェント → verify_fact(限定的な検索のみ), format_report(2個)
高頻度で必要な場合だけ、スコープを絞ったクロスロールのツールを追加します。統合エージェントが頻繁にファクトチェックする必要があるなら、フルのウェブ検索ではなく特定DBだけを参照するverify_factを用意します。
tool_choiceで呼び出しを制御する
場合によって、Claudeのツール選択をプログラム側から制御したいことがあります。tool_choice設定でこれが可能です。
| 設定 | 動作 |
|---|---|
"auto" | Claudeがツールを使うかどうか自体を判断(テキスト返答の可能性あり) |
"any" | 必ず何かツールを呼ぶ(複数ある場合はClaudeが選ぶ) |
{"type": "tool", "name": "extract_metadata"} | 指定したツールを必ず呼ぶ |
「必ず構造化データを返してほしい」場合は"any"を使います。「処理の最初に必ずメタデータを取得してから次のステップに進む」という順序が決まっている場合は特定ツールを指定します。
構造化出力への応用についてはClaudeのJSONスキーマ構造化出力でも解説しています。複数のエージェントに適切なツールセットを配布する設計はマルチエージェント設計の実践パターンも参考になります。
構造化エラーレスポンスの設計
MCPツールが失敗したとき、「エラーが起きました」という汎用メッセージだけを返すと、エージェントは適切な回復策を取れません。エラーの種類によって対処が変わるからです。
エラーには4種類あります。
| エラー種別 | 例 | リトライすべきか |
|---|---|---|
| transient(一時的) | タイムアウト・サービス一時停止 | リトライ可能 |
| validation(入力エラー) | 不正なフォーマットのID | リトライ不要(入力の修正が必要) |
| permission(権限エラー) | アクセス権限なし | リトライ不要(人間のエスカレーション) |
| business(ビジネスルール) | 返金上限を超過 | リトライ不要(別ルートへ誘導) |
推奨するエラーレスポンス形式は次の通りです。
{
"isError": true,
"errorCategory": "transient",
"isRetryable": true,
"message": "注文管理システムが一時的に応答しません",
"retryAfterSeconds": 30
}
{
"isError": true,
"errorCategory": "business",
"isRetryable": false,
"message": "返金額が500円の上限を超えています。上位権限者への承認が必要です",
"requiredAction": "escalate_to_human"
}
エラーカテゴリとisRetryableフラグがあることで、エージェントは「一時的なエラーなので30秒後にリトライ」「ビジネスルール違反なので人間にエスカレーション」という判断を自律的に下せます。
なお、「アクセスに失敗した(結果0件)」と「検索したが該当なし(正常に0件)」は明確に区別して返す必要があります。どちらも0件に見えますが、前者はリトライが必要で後者は不要です。
MCPサーバーのスコープ設定
MCPサーバーの設定ファイルを「チーム全体で共有するもの」と「個人用のもの」で分けます。
プロジェクト共有(.mcp.json):
→ リポジトリにコミットされ、チーム全員が使う
→ GitHub連携・Jiraチケット管理・社内DB検索など
個人用(~/.claude.json):
→ 各自のローカルにのみ存在
→ 実験中のサーバー・個人の開発環境・テスト用ツール
共有設定ファイルにAPIキーやトークンを直書きしてはいけません。環境変数展開を使います。
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
}
}
}
}
${GITHUB_TOKEN}の形式で書くと、実行時に環境変数から値が読み込まれます。APIキーがコードリポジトリに混入するリスクをなくせます。
標準的な用途(GitHub・Jira・Slackなど)はコミュニティが提供する既存のMCPサーバーを活用し、自チーム固有のシステム連携だけカスタムサーバーを作るのが効率的です。
組み込みツールの使い分け
Claude CodeにはMCPツールとは別に、組み込みツールが用意されています。適切に使い分けることでコードベースの調査効率が大きく変わります。
| ツール | 用途 | 使うべき場面 |
|---|---|---|
| Grep | ファイル内容の検索 | 関数名・エラーメッセージ・インポート文を探す |
| Glob | ファイルパスのパターンマッチ | **/*.test.tsxなどのファイル名パターンで探す |
| Read | ファイルの全体読み込み | 対象ファイルが特定できている場合 |
| Edit | ファイルの部分編集 | ユニークなテキストで対象箇所を特定できる場合 |
| Write | ファイル全体の書き込み | Editで対象を特定できない場合・新規作成 |
| Bash | シェルコマンド実行 | 上記ツールで対応できない操作 |
コードベースの調査は「Grepでエントリポイントを見つける→Readで関連ファイルを追う」という順番が効率的です。全ファイルを最初からReadするのはトークンの無駄になります。
EditとWriteの使い分けも重要です。Editは「ユニークなテキスト」を特定してその部分だけを変更します。同じテキストが複数箇所にある場合はEditが失敗するため、そのときはRead+Writeで全体を書き換えます。
まとめ
MCPツール設計で精度を上げるための実践ポイントをまとめます。
- ツール説明文に「使う場面・使わない場面・入力フォーマット・類似ツールとの違い」を含める
- 説明が似ているツールは名前を変え、お互いを参照する形で境界を明示する
- 1エージェントに渡すツールは役割に必要な4〜5個程度に絞る
- エラーは種別(transient/validation/permission/business)とリトライ可否を構造化して返す
- 「アクセス失敗による0件」と「正常に0件」を区別して返す
- 共有MCPサーバー設定はAPIキーを環境変数で管理する
この設計を整えることで、エージェントのツール選択ミスが減り、エラー発生時の自律回復率が上がります。
よくある質問
MCPツールの説明文はどこまで詳しく書けばよいですか?
入力フォーマット・クエリ例・エッジケース・類似ツールとの違いを含めることが推奨されます。「何をするツールか」だけでなく「いつ使うべきか・使わないべきか」まで書くことでAIの選択精度が上がります。
1つのエージェントに何個のツールを渡すのが適切ですか?
役割に必要な4〜5個程度が目安です。ツールが多すぎると選択の判断が複雑になり、専門外のツールを誤使用するリスクが上がります。
MCPツールがエラーになったとき、どのように返せばよいですか?
isErrorフラグ、エラーカテゴリ(transient/validation/permission)、リトライ可否を含む構造化エラーを返します。汎用的な「失敗しました」ではエージェントが適切な回復策を取れません。