Claude Media
MCPコネクタのmcp_tool_listingでツール一覧を固定する手順

MCPコネクタのmcp_tool_listingでツール一覧を固定する手順

MCPサーバーがツールを変えても、会話の途中でClaudeに見えるツールが変わらないようにする方法です。mcp_tool_listingブロックの扱いと、toolsへの固定手順をまとめます。

MCPコネクタ経由でMCPサーバーを使っていると、サーバー側がツールを足したり消したりした結果、同じ会話の途中でClaudeに見えるツールが変わることがあります。mcp-client-2026-09-15 というbetaヘッダーを付けると、APIがサーバーから受け取ったツール一覧を mcp_tool_listing ブロックとして返し、その一覧を固定できます。この記事では、ブロックの扱い方と、mcp_toolset の tools への固定手順を扱います。

mcp_tool_listingとは何か

MCPコネクタは、Messages APIにMCPサーバーのURLを渡すだけで、MCPクライアントを自作せずにリモートのMCPサーバーを使える機能です。サーバーの接続情報を mcp_servers に、使うツールの設定を tools 配列の mcp_toolset に書きます。

mcp_tool_listing ブロックは、mcp-client-2026-09-15 ヘッダーで追加された機能です。このヘッダーを付けると、APIがサーバーにツール一覧を問い合わせたとき、レスポンスの先頭にブロックが入ります。問い合わせたサーバーごとに1ブロックです。

{
  "type": "mcp_tool_listing",
  "mcp_server_name": "example-mcp",
  "tools": [
    {
      "name": "echo",
      "description": "Returns the text it receives.",
      "input_schema": {
        "type": "object",
        "properties": { "text": { "type": "string" } },
        "required": ["text"]
      }
    }
  ]
}

tools の各要素は、サーバーが返したツール名(サーバー名は付きません)、説明文、入力スキーマの3つで構成されます。これは、サーバーがその時点で公開していたツール定義の記録です。

新しいヘッダーは mcp-client-2025-11-20 の機能をすべて含みます。併記せず、置き換えて送ります。利用できるのはClaude APIで、機能はbetaです。

何が困るのか — 固定しないときの挙動

MCPサーバーは、いつでもツールを変えられます。固定しない構成では、APIがサーバーに問い合わせるたびに、その時点の一覧がClaudeに渡ります。会話が数ターン続くあいだにサーバーがデプロイされれば、ツールの名前や引数が途中で入れ替わることがあります。

困る場面は次のとおりです。

  • 動作確認を終えたツール定義が、本番運用で知らないうちに変わる
  • 会話の前半と後半で、同じ依頼に使えるツールが違う
  • 再現したい不具合が、サーバーの状態によって再現しなくなる

ツールが多すぎることによるコンテキスト圧迫は別の問題です。そちらはMCPのツール定義はなぜコンテキストを圧迫するのかで扱っています。ここで話すのは、量ではなく一覧の安定性です。

一覧を固定する流れ

固定には2つの層があります。1つ目はAPIが自動で行う記録、2つ目は呼び出し側が tools に書き込む手動の固定です。

くらべる

自動で記録する場合と手動で固定する場合

自動の記録

アシスタントメッセージの返送

返ってきた mcp_tool_listing ブロックを、アシスタントメッセージごと変更せずに次のリクエストへ含めます。以降のリクエストは、サーバーに問い合わせ直さず、記録された一覧を使います。

手動の固定

mcp_toolsetのtoolsに書き込む

ブロックの tools を mcp_toolset の tools フィールドへコピーします。APIはサーバーにツール一覧を問い合わせず、そのエントリだけが使われます。

自動の記録を保つ

自動の記録を使うときに守ることは2つです。

  1. アシスタントメッセージは、mcp_tool_listing ブロックを含めたまま、そのまま返送する
  2. ブロックを含むリクエストには、毎回 mcp-client-2026-09-15 を付け続ける

履歴を整形してブロックを落とすと、記録が失われて、次のリクエストで一覧を取り直すことになります。

もう1点、コード側の注意があります。ブロックはレスポンスの先頭に入るため、content[0] がテキストだと決め打ちしている実装は動かなくなります。ブロックの type を見て分岐してください。

for block in response.content:
    match block.type:
        case "mcp_tool_listing":
            print(block.mcp_server_name, [t.name for t in block.tools])
        case "text":
            print(block.text)

toolsに手動で固定する

一覧を自分で持ちたいときは、ブロックの tools を mcp_toolset にコピーします。

{
  "type": "mcp_toolset",
  "mcp_server_name": "example-mcp",
  "tools": [
    {
      "name": "echo",
      "description": "Returns the text it receives.",
      "input_schema": {
        "type": "object",
        "properties": { "text": { "type": "string" } },
        "required": ["text"]
      }
    }
  ]
}

tools を指定した mcp_toolset では、default_config と configs を適用したうえで、ここに書いたエントリがそのままツールになります。許可リストや defer_loading の設定は、固定と併用できます。

固定したツール一覧は、リポジトリに保存してレビューの対象にすることもできます。サーバー側の変更が一覧に入るのは、自分でコピーし直したときだけになります。

実際の手順

公式のサンプルに沿って、固定されるまでの流れをcurlで追います。

手順

未固定のリクエストから固定済みのリクエストまで

  1. 1

    未固定のリクエストを送る

    mcp_toolset に tools を付けず、ヘッダーを mcp-client-2026-09-15 にして送ります。

  2. 2

    mcp_tool_listingを取り出す

    レスポンスの content から、type が mcp_tool_listing のブロックを探し、その tools を取り出します。

  3. 3

    toolsに書き込んで再送する

    取り出した配列を mcp_toolset の tools に入れて、同じリクエストをもう一度送ります。

  4. 4

    ブロックが返らないことを確かめる

    固定済みのときは、レスポンスに mcp_tool_listing ブロックが含まれません。APIがサーバーに問い合わせないためです。

ステップ2と3は、jqで次のように書けます(公式サンプルの抜粋です)。

TOOLS=$(jq '.content[]
  | select(.type == "mcp_tool_listing") | .tools' <<<"$FIRST")
PINNED=$(jq --argjson tools "$TOOLS" \
  '.tools[0].tools = $tools' <<<"$BODY")

$FIRST は1回目のレスポンス、$BODY は未固定のリクエスト本文です。.tools[0] は tools 配列の先頭、つまりこの例では mcp_toolset を指します。toolsetが先頭でない構成では、添字を合わせてください。

Python SDKでは、ブロックの tools から name、description、input_schema を取り出してtoolsetに渡します。

pinned = [
    {
        "name": t.name,
        "description": t.description,
        "input_schema": t.input_schema,
    }
    for t in listing.tools
]
tools = [{
    "type": "mcp_toolset",
    "mcp_server_name": "example-mcp",
    "tools": pinned,
}]

SDKの型は言語ごとに異なります。ブロックに対応する型(Pythonなら mcp_tool_listing を表す型)が使えるかは、利用中のSDKのバージョンで確かめてください。

会話の途中でMCPサーバーを足すとき

MCPサーバーを会話の途中で追加したい場合は、inline-tools-2026-09-15 と mcp-client-2026-09-15 の2つのヘッダーを併記します。role: "system" のメッセージに tool_addition ブロックを入れ、definition に mcp_toolset を置きます。

{
  "role": "system",
  "content": [
    {
      "type": "tool_addition",
      "tool": {
        "type": "tool_definition",
        "definition": { "type": "mcp_toolset", "mcp_server_name": "calendar" }
      }
    }
  ]
}

サーバーのURLとトークンは、これまでどおり mcp_servers に書きます。tool_addition ブロックには入れません。この場合も、レスポンスの先頭に追加したサーバーの mcp_tool_listing ブロックが返ります。ここでも content[0] を決め打ちしないでください。

固定するときの判断

固定するかどうかは、ツール定義を事前に確かめたいか、サーバーの変更をすぐ取り込みたいかで分かれます。

状況固定の相性
ツール定義を事前にレビューして使いたい固定の相性手動の固定が合う
会話の途中でツールが変わると困る固定の相性自動の記録でまず足りる
サーバーの新機能を常に取り込みたい固定の相性固定しない構成のまま
自社管理のMCPサーバーで、変更が頻繁固定の相性一覧のコピーし直しを運用に入れる

手動で固定した場合、使われるのは tools に書いたエントリそのものなので、サーバーがツールを消しても一覧は変わりません。呼び出しがサーバー側でどう扱われるかは、ドキュメントに記載がありません。固定した一覧は、サーバーの変更に合わせて更新する前提で運用してください。

更新の確認は、固定していないリクエストをもう一度送るだけで足ります。届いた mcp_tool_listing の tools を保存済みの一覧と比べれば、サーバー側で増えたツール、消えたツール、スキーマが変わったツールが分かります。差分がなければ固定を保ち、あればレビューしてから書き換えます。

diff <(jq -S . pinned-tools.json) <(jq -S . latest-tools.json)

pinned-tools.json は保存済みの一覧、latest-tools.json は固定なしのリクエストで届いた tools を書き出したものです。

名前やスキーマの食い違いが疑われるときの切り分けは、MCPサーバーに接続できないときの切り分け手順の「ツール表示」の層から入ると追えます。ツール名の付き方はMCPツール名の命名規則とサーバー間衝突の防ぎ方にまとめています。

固定した一覧に許可リストを重ねる

固定した tools には、default_config と configs が適用されます。固定した一覧のうち特定のツールだけを使わせたいときは、既定を無効にして、使うツールだけを有効にします。

{
  "type": "mcp_toolset",
  "mcp_server_name": "example-mcp",
  "default_config": { "enabled": false },
  "configs": { "echo": { "enabled": true } },
  "tools": [
    {
      "name": "echo",
      "description": "Returns the text it receives.",
      "input_schema": {
        "type": "object",
        "properties": { "text": { "type": "string" } },
        "required": ["text"]
      }
    }
  ]
}

逆に、一覧は丸ごと使い、危険なツールだけを configs で enabled: false にする書き方もできます。defer_loading を default_config に置けば、固定した定義をツール検索の遅延読み込みと組み合わせられます。固定は「何が一覧にあるか」、configs は「そのうち何を使うか」を決める層なので、役割が重なりません。

使う前に押さえる制約

固定機能の外側にある、MCPコネクタ全体の条件も確認しておきます。

  • betaである: 固定のヘッダーはClaude APIで使えます。他のプラットフォームでの提供は、固定機能については記載がありません
  • ZDRの対象外: MCPコネクタはZDR(ゼロデータ保持)の取り決めの対象外で、ツール定義と実行結果を含むMCPサーバーとのやり取りは通常の保持ポリシーに従います
  • サーバーの条件: HTTPで公開されたサーバーが対象です。Streamable HTTPとSSEの両方に対応し、ローカルのSTDIOサーバーは直接つなげません
  • 対応するMCPの機能: MCP仕様のうち、ツール呼び出しだけが対象です
  • toolsetの検証規則: mcp_servers に書いたサーバーは、それぞれちょうど1つの mcp_toolset から参照されている必要があります

configs に書いたツール名がサーバーに存在しなくても、エラーにはならず、バックエンドに警告が残るだけです。固定した tools と configs の名前がずれていても、気づきにくい点は覚えておくとよいでしょう。

よくある質問

プロンプトキャッシュには影響しますか

ツールの変更とキャッシュの関係は、別のドキュメントに書かれています。tools 配列はリクエストのプレフィックスのなかでも早い位置にあり、編集すると会話全体のキャッシュが無効になります。固定した一覧を毎回同じ内容で送る運用は、この点と噛み合います。ただし、mcp_tool_listing の記録がキャッシュにどう作用するかは、MCPコネクタのページに記載がありません。

自社のAgent SDKで作ったMCPサーバーにも使えますか

Messages APIのMCPコネクタの機能なので、公開されたHTTPのMCPサーバーが対象です。プロセス内で動かすMCPサーバーの作り方はAgent SDKカスタムツールの作り方にあります。

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