Spec explainer
What are ttlMs and cacheScope in MCP?
Last verified: 10 August 2026 · spec 2026-07-28 · ruleset 1.4.2
ttlMs and cacheScope are required fields on five MCP result types as of 2026-07-28. ttlMs is a freshness hint in milliseconds telling clients how long they may reuse a result; cacheScope is exactly "public" or "private" and decides whether a shared intermediary may cache it.The short answer
{
"jsonrpc": "2.0", "id": 1,
"result": {
"tools": [ … ]
}
}{
"jsonrpc": "2.0", "id": 1,
"result": {
"resultType": "complete",
"tools": [ … ],
"ttlMs": 60000,
"cacheScope": "public"
}
}“Require ttlMs and cacheScope fields on results returned by tools/list, prompts/list, resources/list, resources/read, and resources/templates/list via a new CacheableResult interface.”
Both fields are required, not optional hints — omitting either is a MUST-level failure. Mechanically it is one of the smallest changes in the revision, which is exactly why it is worth doing early: it is a few lines per list handler and it clears two of the most common validator failures.
Which methods carry them
Five, grouped by the spec under a new CacheableResult interface:
tools/listprompts/listresources/listresources/readresources/templates/list
Note what is not on that list. tools/call does not carry caching metadata — a tool invocation is an action, not a lookup, and the spec does not invite intermediaries to cache one. The five above are the discovery and read surface, which is the part a client calls repeatedly with identical arguments.
ttlMs in detail
“ttlMs is a freshness hint (in milliseconds) allowing clients to cache responses.”
It is a hint, not a contract. A client may re-fetch sooner, and it may not cache at all. What the server is promising is narrower: that reusing the result for up to this long is a reasonable thing to do.
// Tools are defined in code and ship with the deploy —
// they cannot change between requests to the same build.
{ "ttlMs": 3600000, "cacheScope": "public" } // 1 hour
// Resource list assembled from a database that users write to.
{ "ttlMs": 5000, "cacheScope": "private" } // 5 seconds
// A list you cannot reason about — be conservative, not clever.
{ "ttlMs": 0, "cacheScope": "private" } // no reusettlMs: 0 is a legitimate answer and a much better one than guessing. Zero is a non-negative number, so it satisfies MCP-CAC-004, and it says “don't reuse this” explicitly rather than by omission. Reach for a real number once you can justify it.cacheScope in detail
“cacheScope ("public" or "private") controls whether shared intermediaries may cache the response.”
“cacheScope ("public" or "private").”
The value set is closed. "public" and "private" are the only two valid values — not "no-cache", "none", true, or any HTTP Cache-Control token borrowed by analogy. MCP-CAC-003 exists because that borrowing is a real and easy mistake for anyone who has written HTTP caching before.
Why this arrived in the same revision as statelessness
The two changes are one design. Removing sessions means a client can no longer learn a tool list once during a handshake and hold it for the life of a connection — it re-asks, potentially on every request, and each of those calls is a round trip that the legacy protocol did not have to make.
Caching is what pays for that. And caching only became sound because of statelessness: once list endpoints stopped varying per connection, two identical requests genuinely have the same answer, so an intermediary can serve one from the other.
“A `cacheScope` of `"public"` indicates that the response does not contain user-specific data and can be safely shared.”
Read the two rules together and the dependency is explicit. If your tools/list still varies per connection — the failure MCP-STL-008 catches — then no cacheScope value you write is honest, because the premise the field rests on is false.
The public/private mistake worth avoiding
This is the one place in the caching rules where getting it wrong is a security problem rather than a performance one.
cacheScope: "public". A shared proxy caches the first response and serves it to the next user, who now sees a tool list that was filtered for someone else.MCP-CAC-005 is the rule that flags this, and it is the only caching rule marked security-relevant. It is graded as a warning rather than a failure because detecting personalisation from outside is inference, not certainty — but a security-relevant finding caps the report grade at D regardless.
private — even if the difference looks harmless today, because the caching layer that acts on the field has no way to re-check that judgement later.The 5 caching rules we check
| Rule | What we check | Level | If it fails |
|---|---|---|---|
| MCP-CAC-001 | ttlMs present on all five cacheable results | MUST | fail |
| MCP-CAC-002 | cacheScope present on all five cacheable results | MUST | fail |
| MCP-CAC-003 | cacheScope is exactly "public" or "private" | MUST | fail |
| MCP-CAC-004 | ttlMs is a non-negative number | MUST | fail |
| MCP-CAC-005 | Authenticated or personalised results are not marked cacheScope: public | MAY | warn |
All five carry a verbatim spec sentence. MCP-CAC-005 is the security-relevant one.
Check your list responses
The validator calls each of the five cacheable methods and reports whether ttlMs and cacheScope are present, correctly typed, and consistent with what the response actually contains.
Frequently asked
What is ttlMs in MCP?
ttlMs is a freshness hint, in milliseconds, that a server attaches to a cacheable result so clients know how long they may reuse it before re-fetching. It became required in the 2026-07-28 revision on tools/list, prompts/list, resources/list, resources/read and resources/templates/list, via a new CacheableResult interface.
What is cacheScope in MCP?
cacheScope is a required field on the same five results whose value is exactly "public" or "private". It controls whether shared intermediaries may cache the response: "public" asserts the response contains no user-specific data and can be safely shared, while "private" restricts caching to the requesting client.
Which MCP methods require ttlMs and cacheScope?
Five: tools/list, prompts/list, resources/list, resources/read and resources/templates/list. They are the methods the spec groups under the CacheableResult interface. Other results, including tools/call, do not carry these fields.
What value should I use for ttlMs?
The spec defines the field's meaning but does not prescribe a number, so this is an engineering decision rather than a conformance one. Base it on how often the underlying list actually changes: a static tool list can afford a long hint, while a list assembled from a fast-moving external source should use a short one. The field must be a non-negative number.
Is it safe to set cacheScope to public?
Only when the response genuinely contains no user-specific data. Marking a personalised result public invites a shared intermediary to serve one user's response to another, which is a data-leak class rather than a mere caching inefficiency. If a tool list, resource list or resource body varies by who asked, it must be private.
Why did MCP add caching metadata in 2026-07-28?
Because the same revision made the protocol stateless. Once list responses stopped varying per connection, they became genuinely cacheable — and a stateless protocol re-sends the context a handshake used to establish once, so caching the repeated list calls is what keeps that trade cheap.