Claude Media
MCPのTools仕様を読み解く — tools/callで何が起きているか

MCPのTools仕様を読み解く — tools/callで何が起きているか

MCPのTools仕様が定めるtools/list・tools/callの正確な挙動を、2026-07-28版の仕様原文から読み解きます。追加入力の往復設計まで扱います。

MCPのTools仕様は、サーバーがモデルに何をどう渡すべきかを、想像以上に細かく決めています。ツール名の文字種、結果の返し方が5種類あること、追加の入力が必要になったときの往復のやり方まで、仕様書1本の中に定義があります。この記事では2026-07-28版の仕様原文を、実装者が実際に手を動かす順に読み解きます。

MCPのTools仕様で定義されていること

Toolsは、サーバーが外部システムへの操作をモデルに公開する仕組みです。データベースへの問い合わせ、API呼び出し、計算の実行などが該当します。ツールは名前とスキーマで識別され、モデルが文脈から自動的に発見して呼び出す「モデル制御」の設計を取ります。

ただし仕様自体はUIの形を強制しません。決めているのは、tools/listtools/callという2つのメッセージのやり取りの形と、結果の中身の構造です。信頼と安全のため、危険な操作には人間の確認を挟むべきだとする勧告もありますが、これは実装への推奨であって、プロトコルレベルの強制ではありません。

tools/listの一覧取得 — 順序が効く理由

toolsの能力(capability)を宣言したサーバーはtools/listに必ず応答します。この一覧は空でもよく、時間とともに変わってもかまいませんが、同じ接続の中で他のリクエストの副作用として変化してはいけません。権限によって見えるツールの集合が変わるのは許容されますが、それは呼び出しごとの認可情報に基づく変化であって、接続状態としての変化ではないという整理です。

仕様が地味に強く推奨しているのが、決定的な順序での返却です。同じツール集合なら毎回同じ順番で返す。これによってクライアントはツール一覧を安心してキャッシュでき、さらにツール一覧をモデルへのプロンプトに含めるとき、プロンプトキャッシュのヒット率が上がります。ツール一覧はリクエストのたびにモデルへ渡す文脈の一部になるため、順序が毎回変わるとキャッシュが効かず、無駄なトークンコストが発生します。地味な仕様に見えて、実装のコストへ直結する項目です。

一覧のレスポンスにはttlMscacheScopeというフィールドも含められます。クライアント側のキャッシュ期間と、そのキャッシュを他の接続と共有してよいか(public)個別接続限りか(private)を指定するものです。

ツール定義にはinputSchemaのほか、任意でannotations(ツールの挙動を説明する追加情報)を持たせられます。ここで仕様が強く釘を刺しているのが、信頼できるサーバーからのものでない限り、クライアントはannotationsの内容を信用してはいけないという点です。「読み取り専用です」「破壊的な操作はしません」といった申告をそのまま信じて確認をスキップする実装は、悪意あるサーバーに対して脆弱になります。

ツール名の制約と衝突の避け方

ツール名は1〜128文字、英数字・アンダースコア・ハイフン・ドットのみを推奨し、大文字小文字を区別すべきとされています。スペースやカンマは避けるべきです。getUserDATA_EXPORT_v2admin.tools.listが仕様の挙げる有効な例です。

見落としやすいのが、この一意性がサーバー単体の範囲でしか保証されないことです。複数のMCPサーバーを束ねるクライアントやプロキシは、異なるサーバーが同じsearchという名前のツールを公開しているような衝突に出会います。仕様は、サーバー名(serverInfoのname)は一意性の担保に使うべきではないとし、代わりにサーバー識別子をツール名の前に付けるような曖昧さ解消の仕組みを実装側で用意すべきだとしています。複数サーバーを集約するゲートウェイやルーターを自作するなら、この前提を最初に設計へ組み込む必要があります。

tools/callの結果 — 5種類の返し方

tools/callはツール名と引数を渡すだけのシンプルなリクエストですが、返り値の型は豊富です。content配列には5種類を混在させられ、もう1つstructuredContentという返し方もあります。

返すもの使いどころ
text返すものプレーンテキスト使いどころ説明文・要約・エラーメッセージなど
image / audio返すものBase64エンコードされたメディアデータ使いどころ画像生成・音声合成の結果を直接返す
resource link返すものresources/readで参照できるURIのみ使いどころ大きなファイルなど、必要になるまで中身を送らない軽量な参照
embedded resource返すものリソースの中身ごと結果に含める使いどころ呼び出し直後にモデルへ内容を読ませたい小さなリソース
structuredContent返すものoutputSchemaに沿ったJSON値使いどころツール出力を構造化データとしてそのまま扱わせたいとき

resource linkとembedded resourceの使い分けは、結果のサイズとモデルに即座に読ませる必要があるかどうかで決まります。resource linkはresources/readで後から参照できる分だけ呼び出し直後のペイロードは軽くなりますが、仕様はresources/listの一覧に必ず現れるとは保証していません。モデルにその場で内容を判断させたい小さな結果はembedded resourceで返し、大きすぎて毎回送るコストが見合わない結果だけresource linkに留める、という基準が実装上は扱いやすくなります。

後方互換のため、structuredContentで構造化データを返す場合でも、同じ内容をシリアライズしたテキストをcontentにも含めるのがルールです。このstructuredContentは、LLMの「構造化出力」(モデル生成をスキーマで縛る機能)とは無関係の、サーバー側が作るデータである点を仕様は明確に区別しています。似た名前の別概念と混同しないための注記です。

{
  "result": {
    "resultType": "complete",
    "content": [
      { "type": "text", "text": "{\"temperature\": 22.5, \"conditions\": \"Partly cloudy\"}" }
    ],
    "structuredContent": {
      "temperature": 22.5,
      "conditions": "Partly cloudy"
    }
  }
}

追加入力が要るときの往復 — input_required

ツール呼び出しの途中でユーザーの追加入力が必要になることがあります。例えばGitHubのユーザー名の確認です。このケースのために、tools/callの結果はresultType: "input_required"を返せます。このときinputRequestsに何を尋ねるべきかの詳細(elicitation/createによるフォーム定義など)が入り、requestStateという不透明な文字列が添えられます。

クライアントは要求された入力をユーザーから集め、inputResponsesと受け取ったrequestStateを添えて同じツール名・同じ引数でリクエストを再送します。ここで注意すべきは、JSON-RPCのidは初回と再送で必ず変える必要があることです。この一連のやり取りは仕様全体で「複数回の往復リクエスト」(multi round-trip requests、MRTR)という一般化されたパターンとして定義されており、Toolsだけでなく、Resourcesの読み取りでも同じ形が使われます。

このMRTRという仕組み自体が2026-07-28版の仕様で新しく導入されたものです。それ以前は、サーバーがクライアントへroots/listsampling/createMessageのようなリクエストを送る手段として「サーバー起点のリクエスト」という別方式が使われていました。仕様はこの旧方式をもはやサポートしない破壊的変更だと明記しています。サーバー間で状態を共有するストレージ層や、ステートフルなロードバランシングを必要とせずに同じことを実現できる設計へ置き換えられた形です。古い実装ガイドを参考にサーバーを書いている場合、この置き換えを見落とすと動かないコードになります。

{
  "result": {
    "resultType": "input_required",
    "inputRequests": {
      "github_login": {
        "method": "elicitation/create",
        "params": { "mode": "form", "message": "GitHubのユーザー名を入力してください" }
      }
    },
    "requestState": "eyJsb2NhdGlvbiI6Ik5ldyBZb3JrIn0..."
  }
}

エラーは2系統 — プロトコルエラーとツール実行エラー

Toolsのエラー設計は、モデルが自力で回復できるかどうかで意図的に分かれています。プロトコルエラーは「存在しないツール名」「リクエストの形式不備」のような、モデルが直しようのない失敗です。標準のJSON-RPCエラー(code: -32602など)として返されます。

ツール実行エラーはAPI障害・入力値の範囲外・ビジネスロジック上の失敗など、モデルが引数を変えて再試行すれば直る可能性がある失敗です。こちらはエラーとして落とすのではなく、tools/callの結果としてisError: trueを付けて返します。仕様は「クライアントはツール実行エラーをモデルに渡し、自己修正を促すべき」と明記しています。この2系統を混同してすべてJSON-RPCエラーにしてしまうと、モデルは「日付の形式が違う」ことに気づけず、同じ失敗を繰り返すことになります。

状態を持つツールの設計指針 — Stateful Tools

MCPにはプロトコルレベルのセッション概念がありません。そのため、ショッピングカートやデータベーストランザクションのように呼び出しをまたいで状態を持たせたいときは、サーバー側で明示的なハンドルを発行する設計にします。create_basketのようなツールがbasket_idを返し、以降のadd_item呼び出しにそのbasket_idを引数として渡す、という形です。

仕様はハンドル設計時の注意点を4つ挙げています。

注意点理由
ハンドルを「権限そのもの」ではなく「名前」として扱う理由認証済みサーバーでも、呼び出しのたびに認可を再検証する必要があるため
内部構造を推測させない不透明な値にする理由IDの中身から他のリソースを類推・改ざんされないようにするため
ハンドルの寿命をツールの説明文にはっきり書く理由「24時間操作がないと失効する」などをモデルが把握し、失効前提で挙動を組み立てられるようにするため
失効したハンドルへの呼び出しには、その旨を伝えるツール実行エラーを返す理由モデルが失効に気づき、新しいハンドルを作り直せるようにするため

この最後の項目は、プロトコルエラーとツール実行エラーを使い分ける設計そのものです。失効したハンドルへの呼び出しをプロトコルエラーとして返してしまうと、モデルはそれを「直しようのない失敗」と解釈し、ハンドルを作り直す動きに進めません。ツール実行エラーとしてisError: trueで返すからこそ、モデルは失効を自分で検知し、create_basketのようなツールを呼び直して回復できます。

HTTPヘッダーにパラメータを渡すx-mcp-header

Streamable HTTPトランスポートを使うサーバー向けに、x-mcp-headerという拡張プロパティがあります。inputSchema内の特定のプロパティにこの注釈を付けると、そのパラメータの値がMcp-Param-{name}というHTTPヘッダーとしてもリクエストに複製されます。ロードバランサーやWAFのようなネットワーク中間層が、リクエストボディを解析せずにルーティングや処理判断をできるようにするための仕組みです。

値には整数・文字列・真偽値しか使えず(number型は不可)、制御文字を含められないなどの制約があります。仕様はパスワードやAPIキーのような機微な値にこの注釈を付けるべきではないと明記しています。ヘッダーはネットワーク中間層から見える値だからです。便利な仕組みですが、セキュリティ境界を越えて値が露出することを理解したうえで使う機能です。

この仕様がMCPサーバー実装で効くところ

仕様を通読すると、Tools設計の軸は「モデルが自己修正できる余地を最大化する」ことだと分かります。エラーを2系統に分けたのも、input_requiredで往復を許したのも、ツール名の文字種を制限したのも、すべてモデルが迷わず正しい形で再試行できるようにするための設計です。決定的な順序とキャッシュヒントは一見地味な項目ですが、ツール一覧が毎リクエストでモデルの文脈に載ることを踏まえると、プロンプトキャッシュ効率という実利に直結します。サーバーを自作するなら、まず結果の型を正しく分けることと、一覧の順序を安定させることの2点が、実装コストに対して効果の大きい投資になります。

まとめ

MCPのTools仕様は、tools/listtools/callという2つのメッセージを軸に、結果の型・エラーの分類・状態管理・追加入力の往復までを定義しています。実装で押さえるべきは、決定的な順序でのツール一覧返却、プロトコルエラーとツール実行エラーの使い分け、そして状態を持たせる場合は不透明なハンドルを発行することの3点です。自分でMCPサーバーを作るところから始めたい場合はMCPサーバー自作ガイドを、動作確認にはMCP Inspectorの使い方を参照してください。Resources仕様の読み解きはMCPのResources仕様を読み解くで扱っています。

この記事を共有:XはてブLinkedIn
MCP をもっと見る →