Uh oh!
There was an error while loading. Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork 627
Implement SEP-2549: TTL for List Results #875
Copy link
Copy link
Closed
Labels
2026-07-28P2Medium: important but non-blocking improvementMedium: important but non-blocking improvementT-enhancementNew features and enhancementsNew features and enhancementsT-modelModel/data structure changesModel/data structure changesT-transportTransport layer changesTransport layer changes
Milestone
Description
Metadata
Metadata
Assignees
Labels
2026-07-28P2Medium: important but non-blocking improvementMedium: important but non-blocking improvementT-enhancementNew features and enhancementsNew features and enhancementsT-modelModel/data structure changesModel/data structure changesT-transportTransport layer changesTransport layer changes
Type
Projects
StatusShow more project fields
Done
SEP-2549: TTL for List Results — rust-sdk implementation
Spec PR:modelcontextprotocol/modelcontextprotocol#2549
Conformance:modelcontextprotocol/conformance#275
Track: Specification · Stage: accepted · Priority: P0 · Theme: Transport Evolution and Scalability
Needs code changes: Yes (Medium) — non-breaking (additive)
Summary
Adds two optional fields to the results of
tools/list,prompts/list,resources/list,resources/read, andresources/templates/list:ttlMs— how long a client may treat the response as fresh before re-fetching.cacheScope— controls who may cache the response.This lets clients cache feature lists and reduce reliance on server-push notifications, while
remaining fully backward compatible. TTL supplements (does not replace) the notification mechanism.
Why this needs code changes in rust-sdk
All the affected list results are generated by a single
paginated_result!macro incrates/rmcp/src/model.rs(~line 1145), used forListResourcesResult,ListResourceTemplatesResult,ListPromptsResult,ListToolsResult(andListTasksResult). Thatmacro currently emits only
_meta+next_cursor+ the items field.ReadResourceResultis aseparate struct. None of these carry
ttlMs/cacheScopeyet.This is the nice part: adding the fields to the macro covers four of the five result types at once.
Proposed work
paginated_result!macro to add#[serde(skip_serializing_if = "Option::is_none")] pub ttl_ms: Option<u64>andpub cache_scope: Option<CacheScope>(with#[serde(rename_all = "camelCase")]already on the macro output →ttlMs/cacheScope). Update the macro'swith_all_itemsconstructor to default both toNone.ReadResourceResult(not produced by the macro).pub enum CacheScopewith the spec's allowed values +#[cfg_attr(feature = "schemars", derive(JsonSchema))], matching the#[non_exhaustive]/exhaustiveconventions used elsewhere inmodel.rs.with_ttl_ms,with_cache_scope) so server handlers inhandler/server/router.rscan set them ergonomically.service/client.rs.Affected areas
crates/rmcp/src/model.rs(thepaginated_result!macro,ReadResourceResult, newCacheScope),handler/server/router.rs,service/client.rs(only if implementing client caching).Notes / risks
#[expect(clippy::exhaustive_structs)]— adding fields is fine but keep the constructor in sync.