業務活用事例

MCPツール設計:AIがツールを正確に選ぶ記述の書き方

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)、リトライ可否を含む構造化エラーを返します。汎用的な「失敗しました」ではエージェントが適切な回復策を取れません。