---
title: How do cacheable MCP tool lists change your token bill?
url: https://deepthinkingai.org/mcp-cacheable-tool-lists/
published: 2026-09-14
author: Shekhar Singh
topic: Agents & Protocols
tags: mcp, prompt-caching, agents, cost
site: DeepThinking AI
---

# How do cacheable MCP tool lists change your token bill?

**Summary:** MCP revision 2026-07-28 requires ttlMs and cacheScope on every list result and tells servers to return tools in a deterministic order. Both are filed as minor changes. They are the most direct cost change in the revision, because tool definitions sit in the cacheable prefix of every agent step.

## 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](https://modelcontextprotocol.io/specification/2026-07-28/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](/prompt-caching-economics/) 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**

1. System instructions
   Changes on deploy, if ever
2. Tool definitions from tools/list
   The block this revision is about
3. Reference documents and examples
--- cache breakpoint --- (everything above is the cache key)
4. Conversation and tool results
5. Current 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](/long-context-vs-retrieval/). That block is sent on every step of every loop.
[Anthropic's documentation](https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching)
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**

```mermaid
sequenceDiagram
    participant MCPclient as MCP client
    participant MCPserver as MCP server
    MCPclient->>MCPserver: tools/list
    MCPserver-->>MCPclient: result + ttlMs + cacheScope
    MCPclient->>MCPserver: tools/call  (list served from cache)
    MCPserver-->>MCPclient: result
```

- result + ttlMs + cacheScope: Deterministic order, so the serialised bytes repeat.
- tools/call  (list served from cache): No second tools/list until ttlMs expires or listChanged fires.

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.

<ReadNext
  href="/how-model-context-protocol-works/"
  kicker="Related"
  title="How the Model Context Protocol actually works"
  note="The stateless negotiation model these list endpoints now sit inside, and the trust boundary the spec leaves to you."
/>

## 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](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2549)
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.

## 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
- [Model Context Protocol, Key Changes in revision 2026-07-28](https://modelcontextprotocol.io/specification/2026-07-28/changelog). Model Context Protocol, 2026-07-28
- [SEP-2549: CacheableResult for list endpoints](https://github.com/modelcontextprotocol/modelcontextprotocol/pull/2549). Model Context Protocol, 2026
- [Prompt caching](https://docs.anthropic.com/en/docs/build-with-claude/prompt-caching). Anthropic

---
Canonical HTML: https://deepthinkingai.org/mcp-cacheable-tool-lists/