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つです。
- アシスタントメッセージは、
mcp_tool_listingブロックを含めたまま、そのまま返送する - ブロックを含むリクエストには、毎回
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
未固定のリクエストを送る
mcp_toolsetにtoolsを付けず、ヘッダーをmcp-client-2026-09-15にして送ります。 - 2
mcp_tool_listingを取り出す
レスポンスの
contentから、typeがmcp_tool_listingのブロックを探し、そのtoolsを取り出します。 - 3
toolsに書き込んで再送する
取り出した配列を
mcp_toolsetのtoolsに入れて、同じリクエストをもう一度送ります。 - 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カスタムツールの作り方にあります。
関連する記事
MCP をもっと見る →MCPとは — AIと外部ツールをつなぐ標準プロトコルの仕組み・採用状況・Claudeでの使い方
mcp-client-2025-04-04の移行 — tool_configurationをMCPToolsetへ
Anthropic Advanced Tool Use — Claudeが大量ツールを扱う3つの機能
text editor toolを自前実装する手順 — max_charactersとundo_edit廃止
Tool Searchを自作する — tool_referenceを返す埋め込み検索の実装
Browser use toolのセキュリティ対策6原則 — プロンプトインジェクション対応