Claude Media
MCPのttlMsとcacheScopeでキャッシュ制御を仕様から理解する

MCPのttlMsとcacheScopeでキャッシュ制御を仕様から理解する

MCP 2026-07-28リビジョンで必須化されたttlMsとcacheScopeの仕様を解説します。鮮度計算の式とpublic/privateの使い分け、通知との関係まで示します。

MCPの2026-07-28リビジョンでは、tools/listprompts/listresources/listresources/readresources/templates/listserver/discoverが返す結果に、ttlMscacheScopeという2つのフィールドが必須(MUST)になりました。SEP-2549として提案されたこの変更は、クライアントが不要な再取得を減らせるようにするための鮮度ヒントです。MCPサーバーを自作するなら、この2フィールドを正しく埋めることが2026-07-28リビジョン対応の必須項目になります。

なぜMCPにキャッシュの仕様が必要になったのか

MCPはもともとlistChanged通知(一覧が変わったことをサーバーからクライアントへ知らせる仕組み)を持っていました。ですが通知だけでは「変わっていないことをどう確信するか」に答えられません。通知が来ない限り再取得しない実装は、通知の実装漏れや配送失敗があった場合に古いデータを持ち続けるリスクを抱えます。逆に念のため毎回取り直すと、ネットワーク往復とトークン消費(一覧の内容をコンテキストに載せ直すコスト)が積み上がります。

ttlMscacheScopeはこの両極端の中間を埋める仕組みです。サーバーが「この結果はこれくらいの時間なら新鮮とみなしてよい」という鮮度の期限を明示し、クライアントはその期限内は再取得を省略できます。仕組みとしてはHTTPのCache-Control: max-ageとほぼ同じ発想で、Web開発者には馴染みやすい設計です。

対象となるのは、resultType: "complete"(通常の完了結果)を持つ結果だけです。Multi Round-Trip Requests(追加入力を求めるやり取りの標準パターン)で返される中間応答(resultType: "input_required")はキャッシュ対象外で、キャッシュヒントも付与されません。また、追加入力の応答として送られたリトライ(inputResponsesrequestStateを含むリクエストの結果)もキャッシュしてはならない(MUST NOT)と定められています。入力に応じて結果が変わる以上、キャッシュキーに入力の中身まで含めない限り安全にキャッシュできないからです。

ttlMsとcacheScopeの仕様

ttlMsはミリ秒単位の整数で、「受信からこの時間だけ結果を新鮮とみなしてよい」という鮮度期限です。仕様が定める挙動は次のとおりです。

クライアントの扱い
0クライアントの扱い即座に古いとみなす。必要になるたびに再取得してよい
正の整数クライアントの扱い受信からその時間(ミリ秒)は新鮮とみなす
未指定クライアントの扱い0とみなす。古いサーバー実装でのみ起こりうる
負の値クライアントの扱い無視して0として扱う

鮮度の判定式は仕様に明記されています。

now < t_received + ttlMs

t_receivedは応答を受け取った時刻です。この式が真である間は結果を新鮮として使い回し、偽になった時点で次にその結果が必要になったタイミングで再取得します。

具体的な数値で追うと、ttlMs300000(5分)のtools/list結果を10時00分00秒に受信した場合、10時05分00秒より前にツール一覧が必要になれば再取得を省略でき、10時05分00秒を過ぎてから必要になった時点で初めて再取得します。仕様は「再取得のタイミングは結果が実際に必要になった瞬間」であることを重視しており、TTLの残り時間を先回りして計算し続けるような常駐処理を要求していません。

ここで注意が必要なのは、ttlMsポーリング間隔ではないという点です。仕様は「TTLを自動的なバックグラウンド再取得のトリガーとして扱ってはならない(SHOULD NOT)」と明記しており、あくまで「必要になったときに新鮮かどうかを確認するための鮮度ヒント」に限定しています。どうしてもポーリングする実装にするなら、ジッター(ランダムなばらつき)とバックオフを必ず入れることが求められます。

cacheScope"public""private"のどちらかを取り、「誰がこのキャッシュを再利用してよいか」を制御します。

意味
public意味ユーザー固有のデータを含まない。クライアント・共有ゲートウェイ・キャッシュプロキシの誰もが、任意のユーザーに対して再利用できる
private意味ユーザー固有のデータを含む。同じ認可コンテキスト内でのみ再利用可。異なるアクセストークンに対してキャッシュを共有してはならない(MUST NOT)

使い分けの目安は明快です。全ユーザーに同一の内容が返るtools/listprompts/listpublicが適切、認証済みユーザーごとに内容が変わるresources/readや、ユーザーでフィルタされた一覧結果はprivateが適切です。

ページネーションと組み合わせる場合、各ページは独立してキャッシュされる結果として扱います。ページごとに異なるttlMsを設定してよい一方、同一の一覧リクエストに対する全ページのcacheScopeは揃える(MUST)必要があります。最初のページがprivateなら、2ページ目以降もすべてprivateでなければなりません。カーソルによる分割取得の仕組み自体はMCPのページネーション仕様で扱っているので、あわせて参照してください。

通知・ページネーションとの組み合わせで見落としやすい点

ttlMslistChanged通知は補完関係にあり、両方を実装してもよい設計です。長時間かかるツール呼び出しの進捗を伝えるprogress通知とは目的が異なるので混同しないでください(進捗通知についてはMCPの進捗通知(progress notifications)を実装するパターンを参照)。仕様が想定する組み合わせは2パターンあります。

  • listChanged: trueを広告せずttlMsだけを返す。クライアントはTTLベースの鮮度判定だけに頼る
  • listChanged: trueを広告しつつttlMsも返す。TTL期限内の不要な再取得を避けつつ、変更があれば通知で即座に無効化(invalidate)される

後者の場合、TTLがまだ有効な間に関連する通知を受け取ったら、キャッシュはその通知の時点で即座に古いものとして扱います。TTLの期限が優先されるのではなく、通知が来た時点でTTLの残り時間を無視して無効化する、という順序を仕様は明記しています。

キャッシュキーの決め方にも注意が必要です。キャッシュされた応答は「メソッド名 + 結果に影響するパラメータ」で識別されます。resources/readならuri、ページネーションされた一覧リクエストならcursorが該当します。メソッドやパラメータが異なるリクエストに対して、以前のキャッシュ結果を流用してはなりません(MUST NOT)。

セキュリティ上の注意点もあります。cacheScope: "public"は「認証済みエンドポイントから返ってきた結果であっても、異なるアクセストークンを持つ呼び出し元の間で共有されうる」ことを意味します。仕様は、サーバー実装者に対してcacheScopeの値が本当にそのプリミティブの公開範囲を正しく反映しているか確認すること、そしてアクセス制御をcacheScopeだけに頼ってはならないことを明記しています。cacheScopeはあくまでキャッシュの共有可否を示すヒントであり、認可の仕組みそのものではありません。

tools/listの順序もキャッシュヒット率に影響する

ttlMscacheScopeと同じ2026-07-28リビジョンで、もう1つキャッシュに関わる推奨事項が追加されました。「サーバーはtools/listからツールを決定的な順序(deterministic order)で返すべき(SHOULD)」というものです。仕様が挙げる目的は2つで、クライアント側のキャッシュを機能させることと、LLMのプロンプトキャッシュのヒット率を改善することです。

これはClaude Codeの利用者にとって直接効いてくる話です。MCPサーバーが接続のたびにツールの並び順を変えると、Claudeに渡されるシステムプロンプト相当の内容(利用可能なツール一覧)が毎回微妙に異なる文字列になり、Anthropic側のプロンプトキャッシュが効きにくくなります。逆に順序が安定していれば、同じツール一覧を含むプロンプトの先頭部分がキャッシュヒットしやすくなり、レイテンシとコストの両方に効きます。ttlMscacheScopeがMCP層のキャッシュを扱うのに対し、この順序の安定性はMCPサーバーの外側にあるモデル呼び出し側のキャッシュにまで波及する、射程の広い推奨事項です。

MCPサーバー開発者はどこでcacheScopeの判断を誤りやすいか

実装で起きやすい誤りは、「動作確認のときにたまたま自分のトークンでしか叩いていないから」という理由で、本来privateが適切な結果をpublicにしてしまうことです。個人アカウント向けにフィルタされたresources/listや、テナントごとに内容が異なるtools/listは典型的なprivate対象です。ここをpublicと誤指定すると、共有キャッシュを経由して別の認可コンテキストの利用者に他人のデータが渡る事故につながります。MCPセキュリティガイドで扱っている「サーバーへの信頼確認」とは別の層で発生する問題であり、サーバー実装者自身が防ぐしかない部分です。

もう1つの落とし穴は、ttlMsを「サーバー側のデータが変わらない保証期間」と誤解することです。仕様は明確に「TTLは鮮度のヒントであって保証ではない(not a guarantee)」と述べています。サーバーはTTLが切れる前にデータを変更してよく、TTLはあくまで「クライアントがどれくらいの間、再取得を合理的に省略できるか」を示すだけです。長すぎるTTLを設定すると、変更の反映が遅れて見える形で表面化します。逆に短すぎるTTLは、キャッシュを実質的に無効化してしまい、仕様を実装した意味が薄れます。データの変わりやすさに応じてTTLを個別に調整するのが実務上の落としどころです。

まとめ

MCPのキャッシュ仕様は、ttlMs(鮮度期限のヒント)とcacheScope(公開範囲の制御)という2つのフィールドで、通知だけでは解決できない「変わっていないことの確信」を補います。2026-07-28リビジョンでtools/list等の一覧・読み取り系メソッドに必須化された仕様であり、resultType: "input_required"の中間結果や、追加入力を伴うリトライされた結果はキャッシュ対象外です。ページネーションと組み合わせるときは、ページごとにttlMsを変えてよい一方でcacheScopeは全ページで揃える必要があります。Claude CodeからMCPに接続する構成でパフォーマンスを詰めていくなら、この2フィールドの設計と、ツール一覧を返す順序の安定化は、どちらも避けて通れない仕様です。

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