| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
The draft spec introduces TTL caching hints on list and read results. This adds the optional ttlMs (Integer) and cacheScope (CacheScope enum) fields to ListToolsResult, ListPromptsResult, ListResourcesResult, ListResourceTemplatesResult, and ReadResourceResult, following the wire-record evolution rules in CONTRIBUTING.md. Purely additive, schema-layer only: no server or client behavior changes. Server-side TTL configuration hooks are deferred to modelcontextprotocol#578.
The draft spec requires cacheable results to carry ttlMs and cacheScope on the wire. Other SDKs (Go, Python, TypeScript) all stamp defaults after handlers return: ttlMs=0 (immediately stale) and cacheScope=public. This adds the same default stamping in McpAsyncServer and McpStatelessAsyncServer for all five cacheable result types. For list results the defaults are set at the build site. For ReadResourceResult, which is built by user handlers, a withCacheDefaults helper stamps missing fields while preserving any values the handler set explicitly.
Two fixes from review: 1. Widen ttlMs from Integer to Long across all five cacheable result records. The spec defines ttlMs as a non-negative integer with no upper bound, and Jackson rejects values exceeding Integer.MAX_VALUE. Long handles any realistic TTL without interop failures. 2. Default cacheScope to PRIVATE (not PUBLIC) for resources/read in both server classes. The spec's caching guidance says resources/read results that depend on the authenticated user should be private. List results keep the PUBLIC default since they are not user-specific.
Listings previously hardcoded ttlMs to 0, so the server half of SEP-2549 could not be switched on. Listings default to a PRIVATE scope because tools/list has been filtered per caller since modelcontextprotocol#1111. ttlMs is validated non-negative on the affected result builders.
|
One API-level safety issue seems worth resolving before making PUBLIC easy to configure: listCache(ttl, scope) applies one cache scope to all four listing methods — tools, prompts, resources, and resource templates. That becomes awkward once tools/list is filtered per caller. The Javadoc correctly warns that any registered tool list filter makes a public tools listing unsafe to share, but the current API cannot express a common case like:
Calling: .listCache(Duration.ofMinutes(5), CacheScope.PUBLIC)currently marks all four result types public, including the filtered tools listing. A shared intermediary following the server hint could then reuse one principal's filtered tool list for another. The warning reduces misuse, but the type/API shape still permits an unsafe combination and makes the safe mixed-scope configuration impossible. I'd consider either:
A regression could configure listCache(..., PUBLIC) + a request-dependent tool filter and assert that the emitted ListToolsResult.cacheScope() is not public. That would make the security property enforced rather than advisory while still allowing public caching for caller-invariant lists. |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
Closes #1009. Supersedes #1062, whose three commits are kept with @aboullaite's authorship; this PR adds the server hook on top.
Adds ttlMs and cacheScope to ListToolsResult, ListPromptsResult, ListResourcesResult, ListResourceTemplatesResult and ReadResourceResult, with deprecated constructors so existing callers compile unchanged. Servers stamp ttlMs: 0 on listings and cacheScope: private on resources/read when a handler sets neither.
McpServer builders gain listCache(Duration, CacheScope) so a server can advertise a positive TTL; without it the server half of SEP-2549 could not be switched on. Listings default to private because tools/list is filtered per caller since #1111, so a shared cache must never serve one principal's listing to another.
Two deliberate deviations from the draft schema: ttlMs is a nullable Long rather than a required field so results from older servers still deserialize, and the absent-scope default for listings is private where the schema comment says public.
The client-side cache from #1123 follows as a separate PR stacked on this one.
This change was created with AI assistance.