DeepThinking AI

How do cacheable MCP tool lists change your token bill?

AI Architect

Key takeaways

  • Every list endpoint now returns ttlMs and cacheScope, so a client can cache tool and resource lists instead of polling them.
  • Servers should return tools in a deterministic order, and the spec says plainly this is to improve LLM prompt cache hit rates.
  • Tool definitions ride in the prompt on every agent step, so an unstable tool list invalidates the cached prefix over and over.
  • cacheScope of public or private decides whether a shared intermediary may hold the response, which matters once a gateway sits between client and server.

The 2026-07-28 revision of the Model Context Protocol is mostly discussed for removing sessions and the handshake. Two entries filed under minor changes will show up on your invoice faster than either of those.

What actually changed in the list endpoints?

Two things, both small in the text and large in effect.

The revision requires ttlMs and cacheScope on results from tools/list, prompts/list, resources/list, resources/read and resources/templates/list, through a new CacheableResult interface. The spec describes ttlMs as a freshness hint that lets clients cache responses and reduce polling, and cacheScope as controlling whether shared intermediaries may cache the response. Both are described as complementing the existing listChanged notifications rather than replacing them.

Separately, the changelog says servers should return tools from tools/list in a deterministic order to enable client-side caching and improve LLM prompt cache hit rates. That second clause is the interesting one. A protocol document does not usually reach into the economics of the model call it feeds.

Why does tool order touch your bill?

Because tool definitions live in the part of the prompt you were hoping to cache.

Prompt caching matches a prefix byte for byte from the first token. An agent sends its toolset on every step, near the front, ahead of the conversation. That block is usually the largest stable thing in the prompt, which makes it the main reason caching is worth turning on for agent workloads at all.

Where an MCP toolset sits in a cached prompt

Where an MCP toolset sits in a cached promptDiagram: 6 ordered layers. System instructions, then Tool definitions from tools/list, then Reference documents and examples, then cache breakpoint (breakpoint), then Conversation and tool results, then Current user input.1System instructionsChanges on deploy, if ever2Tool definitions from tools/listThe block this revision is about3Reference documents and examplescache breakpoint4Conversation and tool results5Current user input
Show as text
Where an MCP toolset sits in a cached prompt. Diagram: 6 ordered layers. System instructions, then Tool definitions from tools/list, then Reference documents and examples, then cache breakpoint (breakpoint), then Conversation and tool results, then Current user input.
#LayerNote
1System instructionsChanges on deploy, if ever
2Tool definitions from tools/listThe block this revision is about
3Reference documents and examples
·cache breakpoint (breakpoint)everything above is the cache key
4Conversation and tool results
5Current user input
Tool definitions sit above the breakpoint, which is why their byte order decides whether the whole prefix survives to the next step.

If the server returns the same tools in a different order between two calls, the serialised prompt differs. The prefix stops matching at the first changed byte, and everything after it is reprocessed at full input price. Nothing errors. You see a hit rate that sits at some unremarkable number and no obvious cause, which is the failure mode this site documented before the spec addressed it.

Is this a real saving or a rounding error?

It depends entirely on how much of your prompt is toolset, and for agent loops that fraction is often large.

A server exposing thirty tools with full JSON Schema for each can run to thousands of tokens, competing for the same room as everything else in your context window. That block is sent on every step of every loop. Anthropic’s documentation prices a cache read at a fraction of a base input token, so the difference between a matching prefix and a broken one is close to the full cost of those tokens, repeated for every step the agent takes.

Caching a tool list under revision 2026-07-28

Caching a tool list under revision 2026-07-28Sequence diagram between MCP client and MCP server. 1. MCP client to MCP server: tools/list. 2. MCP server to MCP client: result + ttlMs + cacheScope. 3. MCP client to MCP server: tools/call (list served from cache). 4. MCP server to MCP client: result.MCP clientMCP servertools/listresult + ttlMs + cacheScopeDeterministic order, so the serialised bytes repeat.tools/call (list served from cache)No second tools/list until ttlMs expires or listChanged fires.result
Show as text
Caching a tool list under revision 2026-07-28. Sequence diagram between MCP client and MCP server. 1. MCP client to MCP server: tools/list. 2. MCP server to MCP client: result + ttlMs + cacheScope. 3. MCP client to MCP server: tools/call (list served from cache). 4. MCP server to MCP client: result.
#FromToMessage
1MCP clientMCP servertools/list
2MCP serverMCP clientresult + ttlMs + cacheScope. Deterministic order, so the serialised bytes repeat.
3MCP clientMCP servertools/call (list served from cache). No second tools/list until ttlMs expires or listChanged fires.
4MCP serverMCP clientresult

The polling saving is smaller and still real. A client that called tools/list every turn now has a stated window in which it does not need to, and a notification to tell it when the window is wrong.

What should you be sceptical about?

Two things, because the change is a SHOULD rather than a MUST.

Deterministic ordering is a recommendation, so a server can ignore it and remain compliant. If you are the client, you cannot assume stability just because the server advertises the current revision. Measure it: call tools/list twice in separate processes and compare the serialised bytes rather than the parsed objects.

ttlMs also carries no guarantee that the value is sensible. A server is free to return a number that reflects nothing, and a client that trusts a long TTL on a list that changes hourly will act on a stale toolset until a listChanged notification arrives. Treat the hint as a hint, keep the subscription, and pick your own ceiling if the server’s number looks optimistic.

Where is MCP heading on cost?

A protocol adding cache-control fields to its list endpoints is a protocol that expects to be called a great deal, by software paying per token. The pull request for CacheableResult reads like ordinary HTTP caching arriving in a JSON-RPC protocol, roughly a decade after the web settled the same argument.

My read is that this is the more useful signal in the revision. Removing sessions made MCP simpler to implement. Adding cache hints to list results is an admission about where the money actually goes in an agent. It goes on the tokens the protocol puts in front of a model, and the spec is now optimising for that, which suggests the next round of changes will be shaped by inference cost rather than by protocol elegance.

Do this

Make your MCP toolset cache-friendly

Three of these are server side and two are client side. The measurement step is the one people skip, and it is the only way to know any of it worked.

  1. Return tools in a fixed order and keep it fixed

    Sort by name, or pin an explicit order, and do not let the order fall out of a map or a set. An order that varies between processes produces a hit rate that looks inexplicably mediocre rather than an obvious failure.

  2. Serialise deterministically as well as ordering deterministically

    Sort object keys inside each tool definition. A stable list of unstably serialised objects is still a different byte sequence, and the cache matches bytes rather than meaning.

  3. Set ttlMs to how long the list is genuinely valid

    Pick a real number rather than a placeholder. A short TTL costs you round trips, and a long one on a list that actually changes means clients act on a stale toolset until listChanged reaches them.

  4. Set cacheScope private unless the list is identical for every caller

    If tools vary by user, tenant or credential, a shared intermediary caching that result serves one caller's toolset to another. Public is only correct when the response carries nothing caller-specific.

  5. On the client, honour ttlMs instead of polling

    Cache the list for the stated window and refresh on listChanged. Calling tools/list every turn wastes a round trip and gains nothing the notification does not already give you.

  6. Log cache reads against writes and watch the ratio by deploy

    Providers return both counts per request. If the ratio does not move after this work, the prefix is being invalidated somewhere else, and you now know to look above the breakpoint.

Frequently asked questions

Why would tool ordering affect cost at all?
Prompt caching matches a prefix byte for byte from the first token. Tool definitions are usually near the front of that prefix. If the server returns them in a different order between calls, the serialised prompt differs, the prefix stops matching, and the whole cached block is reprocessed at full price.
Is ttlMs a cache-control header?
No. It is a freshness hint carried in the result body, and the spec describes it as complementing the existing listChanged notifications rather than replacing them. A client may still be told the list changed before the TTL expires.
What does cacheScope actually control?
Whether a shared intermediary may cache the response. Private means the result is specific to that caller and a gateway must not serve it to anyone else. Public means it can be shared. If you run a proxy in front of MCP servers, this is the field that decides correctness.
Does this apply to stdio servers or only HTTP?
The cache fields are on the result objects, so they travel on either transport. The practical benefit is larger over HTTP, where a shared intermediary can exist and where polling costs a network round trip.
Do I have to do anything if I only write clients?
Yes. Honour ttlMs instead of calling tools/list on every turn, and keep whatever order the server gave you rather than re-sorting into your own.

Sources

  1. Model Context Protocol, Key Changes in revision 2026-07-28Model Context Protocol · 2026-07-28
  2. SEP-2549: CacheableResult for list endpointsModel Context Protocol · 2026
  3. Prompt cachingAnthropic

mcpprompt-cachingagentscost