Cacheable result types and operations
Servers MUST include caching hints on results with `resultType: "complete"` returned by the following operations: `server/discover`, `tools/list`, `prompts/list`, `resources/list`, `resources/templates/list`, and `resources/read`. Interim results with `resultType: "input_required"` are not cacheable and carry no caching hints.
Cache key construction and matching
A cached response is identified by the request method together with the request parameters that affect the result, such as the `uri` for `resources/read` or the `cursor` for paginated list requests. Clients MUST NOT serve a cached response for a request whose method or parameters differ from the request that produced it.
Multi round-trip requests must not be cached
Results produced by retrying a request through the multi round-trip requests mechanism, that is, requests carrying `inputResponses` or `requestState`, MUST NOT be cached, as they depend on inputs that are not part of the cache key.
TTL field semantics and defaults
The `ttlMs` field is a hint from the server indicating how long in milliseconds the client MAY consider the result fresh. If `ttlMs` is 0, the response SHOULD be considered immediately stale. If `ttlMs` is positive, the client SHOULD consider the result fresh for that many milliseconds. If `ttlMs` is absent, clients SHOULD assume a default of 0 and rely on their own caching heuristics or notifications. If `ttlMs` is negative, clients SHOULD ignore it and treat it as 0. Servers MUST provide a `ttlMs` value that is >= 0.
Freshness calculation formula
A client records the local time at which the response was received (t_received). The response is considered fresh while: now < t_received + ttlMs. Once the TTL expires, the response is stale and the client SHOULD re-fetch on next access.
TTL is a freshness hint, not a guarantee
TTL is a freshness hint, not a guarantee. Servers MAY change the underlying data before the TTL expires. The TTL tells the client how long it can reasonably avoid re-fetching, not how long the data is guaranteed to remain unchanged.
TTL should not trigger automatic background polling
Clients SHOULD NOT treat TTL as a polling interval that triggers automatic background refetches. The TTL is a freshness hint: the client checks freshness when it needs the data, and re-fetches only if stale. Implementations that do choose to poll MUST apply jitter and backoff.
Early re-fetching and stale response serving
Clients MAY re-fetch before the TTL expires if they have reason to believe the data has changed, such as receiving an unexpected error on a tool call indicating the method was not found or the parameters were invalid. Clients MAY serve stale responses if errors occur during re-fetching, such as network issues or server downtime.
Cache scope values and meanings
The `cacheScope` field controls who may cache a response. `"public"` means the response does not contain user-specific data and any client, shared gateway, or caching proxy MAY store and serve the cached response to any user. `"private"` means the response contains private data not meant to be shared between callers; cached responses MAY be reused for the same authorization context, but caches MUST NOT be shared across authorization contexts.
When to use public cache scope
Use `"public"` cache scope for lists of tools, prompts, and resource templates when they are identical for all users.
When to use private cache scope
Use `"private"` cache scope for `resources/read` results that depend on the authenticated user, or for filtered list results that vary per user.
TTL and notifications are complementary
A server MAY provide `ttlMs` without advertising `listChanged: true` in its capabilities, in which case the client relies entirely on TTL-based freshness. A server MAY advertise `listChanged: true` AND provide `ttlMs`, in which case the client can use the TTL to avoid unnecessary refetches between notifications, and the notification acts as an immediate invalidation signal.
Notifications invalidate cached responses
When a relevant notification is received while a cached response is still fresh, the notification invalidates the cached response and it should be considered immediately stale.
Pagination and cache independence
When a list result is paginated, each page is an independently cacheable response. Each page response carries its own `ttlMs` value, and the freshness clock for each page starts at the time that page was received. Servers MAY return different `ttlMs` values on different pages.
Paginated list re-fetching strategy
When a cached page expires, the client SHOULD re-fetch that page using its cursor. If a cursor becomes invalid, the client SHOULD discard all cached pages and re-fetch from the beginning. Clients that require a consistent snapshot of the full list SHOULD re-fetch from the beginning without a cursor.
Cache scope consistency across paginated pages
Servers MUST apply the same `cacheScope` to all response pages for a given list request. For example, if the first page of a `tools/list` response has `cacheScope: "private"`, all subsequent pages for that request MUST also be `"private"`.