Why must an MCP DiscoverResult carry ttlMs and cacheScope, and what does cacheScope mean?
answer
- no handshake means discovery repeats
- required, not optional hints
- one number, one sharing rule
- depends on who asked?
- capabilities may vary by authorization
basics
~20 sDiscoverResult extends CacheableResult, so both fields are required. ttlMs tells the client how many milliseconds it may reuse the answer; cacheScope is "public" or "private" and says whether the cached copy may be shared across users or must be kept per-authorization.
solid answer
~50 sIn MCP revision 2026-07-28 there is no handshake to amortise, so a client that wants a server's profile has to ask for it — and without a cache rule it would ask again on every interaction. `DiscoverResult` therefore extends `CacheableResult`, which makes `ttlMs` and `cacheScope` **required** rather than optional hints. `ttlMs` is the server's statement of how long the answer stays valid; after it elapses the client re-calls `server/discover`. `cacheScope` is the safety half: `"public"` means the answer does not depend on who asked, so a host may share one cached copy across all its users, while `"private"` means the answer is specific to the authorization presented and must be cached per-caller. That distinction matters because a server's advertised capability set MAY vary by the authorization on the request, so publishing a privileged view of a server to every user would be a real leak.
go deeper
Remember the two fields and their jobs: ttlMs is how long the answer may be reused, and cacheScope says whether that cached answer may be shared between users.
Explain that DiscoverResult extends CacheableResult so both fields are required, and that public versus private turns on whether the answer depends on the caller's authorization.
Show the leak you are preventing: capabilities may vary by the authorization presented, so a wrongly public scope lets one privileged discovery expose privileged capabilities to every user of the host.
Own the caching design across a host — cache keys that include authorization identity, refresh on version rejections and change notifications, and the operational cost of a fleet whose servers all declare short TTLs.
## Why the fields exist Statelessness has a cost. Under the removed `initialize` handshake, a client paid once per connection to learn what a server was and then reused that knowledge for the life of the connection. In revision 2026-07-28 there is no connection-scoped knowledge at all — every request is self-contained — so the only way to keep discovery from becoming per-interaction chatter is an explicit cache contract. `CacheableResult` is that contract, and `DiscoverResult` extends it. Both `ttlMs` and `cacheScope` are **required** on the result; a server cannot decline to state a cache policy. ## ttlMs `ttlMs` is a duration in milliseconds: how long a client may reuse this answer without asking again. It is the server's own estimate of how stable its profile is. A server whose capability set is fixed at build time can name a long TTL; one whose capabilities depend on a fast-moving upstream should name a short one. A client that honours the TTL calls `server/discover` when it first meets a server, keeps the result, and re-fetches once the window elapses. Nothing forces a client to *use* the cache — it may re-discover on every interaction, or never discover at all, since the call is optional for clients — but honouring the TTL is what makes discovery cheap at scale. ## cacheScope `cacheScope` takes one of two values: - **`"public"`** — the answer does not depend on who asked. Every caller would get the same versions, capabilities and instructions. A host may keep one shared copy for all its users, and an intermediary could in principle cache it too. - **`"private"`** — the answer is specific to the authorization the request carried, so it must be cached per-caller and never handed to a different one. The reason `"private"` has to exist is a rule elsewhere in the same revision: the tool, prompt and resource sets MUST NOT vary per connection, but they MAY vary by the authorization presented. An admin token and a read-only token can legitimately see different views of the same server. If such a server declared `"public"`, the first admin to discover it would seed a cache that every other user then reads — leaking the existence and shape of privileged capabilities. ## How a server should choose The safe default for any server whose answer can differ by caller is `"private"`. `"public"` is a claim, and it should only be made when the discovery answer is genuinely identical for anonymous and authorized callers alike. Note the scope covers the whole result: if only one field varies by caller, the result is private. ## How a client should implement it Key the cache by the server *and*, when the scope is private, by the authorization identity the request carried — not merely by server URL, and certainly not by the reported server name, which is untrusted and not unique. Expire on `ttlMs`. Re-discover early whenever something suggests the profile moved: a request rejected for an unsupported protocol version, or a change notification arriving on an opted-in `subscriptions/listen` stream indicating the tool, prompt or resource set changed. ## The shape of a wrong answer Two mistakes recur. The first is treating `ttlMs` and `cacheScope` as optional hints — they are required fields of `CacheableResult`, and a discovery result without them is malformed. The second is reading `cacheScope` as an HTTP caching directive that browsers or proxies enforce. It is an MCP-level instruction to the client about how it may reuse and share the value; the protocol cannot enforce it, and the same holds for the many other results in the specification that extend `CacheableResult`.
- When would a server be wrong to declare cacheScope "public" on its discovery result?Whenever any part of the answer depends on the caller. In revision 2026-07-28 a server's tool, prompt and resource sets MAY vary by the authorization presented, so a server that shows extra capabilities to an admin token must say "private" — otherwise one privileged discovery seeds a shared cache that reveals those capabilities to everyone.
- How should a client key its cache of discovery results?By the server it talked to plus, for a private scope, the authorization identity the request carried. Never key on the reported serverInfo name — it is untrusted and not unique across servers. Expire the entry when ttlMs elapses, and re-discover early if a request is rejected for an unsupported version.
- Does honouring ttlMs mean a client must call server/discover at all?No. Discovery is mandatory for servers to implement but optional for clients to call, because every request carries its own protocol version and capabilities in _meta. ttlMs governs how long a client that did discover may reuse the answer; it does not create an obligation to fetch one.
saying these in an interview costs you the question
- Calls ttlMs and cacheScope optional hints on the result
- Says cacheScope is an HTTP Cache-Control directive proxies enforce
- Assumes every server's discovery answer is identical for all callers
- Caches a private discovery result across different users
- Thinks a cached result removes the need to send version metadata per request