Skip to content

implementing SEP-2549 TTL for List Results#889

Open
michaelneale wants to merge 1 commit into
mainfrom
micn/sep-2549-ttl-list-results
Open

implementing SEP-2549 TTL for List Results#889
michaelneale wants to merge 1 commit into
mainfrom
micn/sep-2549-ttl-list-results

Conversation

@michaelneale

Copy link
Copy Markdown
Contributor

implementing #875

(assisted by mic and goose)

@michaelneale michaelneale requested a review from a team as a code owner June 5, 2026 09:39
@github-actions github-actions Bot added T-test Testing related changes T-core Core library changes T-macros Macro changes labels Jun 5, 2026
@michaelneale michaelneale force-pushed the micn/sep-2549-ttl-list-results branch 3 times, most recently from a6151ad to f8edae7 Compare June 5, 2026 09:55
@github-actions github-actions Bot removed the T-macros Macro changes label Jun 5, 2026
alexhancock
alexhancock previously approved these changes Jun 5, 2026

@alexhancock alexhancock left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pre-approving so you can merge when the below is addressed!

The cache hints (ttlMs and cacheScope) are written to _meta, but the spec defines them as first-class result fields

Per SEP-2549, ttlMs and cacheScope are properties on the result itself (CacheableResult), so the wire shape is { "tools": [...], "ttlMs": 300000, "cacheScope": "public" } (example, L112) — not nested under _meta

Fix list:

  • Top-level fields: make ttl_ms/cache_scope real #[serde(rename = "ttlMs"/"cacheScope")] fields on the result struct instead of meta.insert(...).
  • resources/read: the same meta.insert pattern is duplicated below in ReadResourceResult, writing into each ResourceContents. The spec attaches the hints to ReadResourceResult itself, so they should live on the result (otherwise they vanish when contents is empty). Scope guidance L90.
  • ttlMs rules: u64 correctly blocks negatives on the producing side 👍, but there's no read-side normalization (absent → 0, negative → 0, server MUST emit >= 0). Rules L39-43.

Comment thread crates/rmcp/src/model.rs
@github-actions github-actions Bot added the T-config Configuration file changes label Jun 6, 2026
@michaelneale michaelneale requested a review from alexhancock June 7, 2026 02:19

@jamadeo jamadeo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this does the right thing over the wire, but wouldn't it be a good bit simpler if added on the top level struct itself?

Comment thread crates/rmcp/src/model.rs
@michaelneale michaelneale changed the title implementing SEP-2549 implementing SEP-2549 TTL for List Results Jun 10, 2026
@github-actions github-actions Bot added T-examples Example code changes T-macros Macro changes labels Jun 12, 2026
@michaelneale

michaelneale commented Jun 12, 2026

Copy link
Copy Markdown
Contributor Author

ok - this is a breaking change now (well needs new semver version) - not sure of next steps @DaleSeo to get CI happy in that (deliberate) case?

Comment thread crates/rmcp/src/model.rs
Comment on lines +1296 to +1305
/// Time, in milliseconds, that this result may be treated as fresh (SEP-2549).
#[serde(
default,
deserialize_with = "deserialize_ttl_ms",
skip_serializing_if = "Option::is_none"
)]
pub ttl_ms: Option<u64>,
/// Scope describing who may cache this result (SEP-2549).
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cache_scope: Option<CacheScope>,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@michaelneale Sorry, I think my earlier suggestion to model these as plain Option fields was wrong. I had not read SEP-2549 carefully enough.

The SEP states:

Servers MUST provide a ttlMs on Results returned by tools/list, prompts/list, resources/list, resources/read, and resources/templates/list.

It also metions:

cacheScope is required because there is no safe default for older servers. The server must explicitly declare the intended cache scope to prevent unintended caching of user-specific data.

Given that, should we make them required with default values?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that will work for the types. if you do that, then its impossible to talk to an older server since their messages will fail to deserialize.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, @howardjohn. I was only considering new servers built with the latest SDK, but you're right. This type is also used by new clients deserializing responses from older servers. I agree that making these fields required would break that compatibility.

Then, I'd like to suggest adding a comment near these fields to explain why they're optional, even though the SEP states that servers MUST provide them.

@DaleSeo

DaleSeo commented Jun 18, 2026

Copy link
Copy Markdown
Member

ok - this is a breaking change now (well needs new semver version) - not sure of next steps @DaleSeo to get CI happy in that (deliberate) case?

The semver CI failure is expected for this PR because it adds public fields. Could you just mark this as a breaking change with a feat!: commit message? That will give release-plz the right breaking-change signal for the changelog and version bump.

@alexhancock

Copy link
Copy Markdown
Contributor

@michaelneale I think with a rebase and #889 (comment) this would be good to go? Would be good to get it in

@DaleSeo

DaleSeo commented Jul 10, 2026

Copy link
Copy Markdown
Member

Hey @michaelneale, do you have any updates? I'm afraid this could block other spec work.

@jamadeo jamadeo force-pushed the micn/sep-2549-ttl-list-results branch from 169b43d to e96796f Compare July 10, 2026 14:14
@github-actions github-actions Bot removed the T-examples Example code changes label Jul 10, 2026
@jamadeo jamadeo force-pushed the micn/sep-2549-ttl-list-results branch from e96796f to 1e432d0 Compare July 10, 2026 14:50
@github-actions github-actions Bot added the T-dependencies Dependencies related changes label Jul 10, 2026
DaleSeo
DaleSeo previously approved these changes Jul 10, 2026

@DaleSeo DaleSeo left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jamadeo Thanks for wrapping this up!

Comment thread crates/rmcp/src/model.rs
Comment on lines +1290 to +1292
/// Scope describing who may cache this result (SEP-2549).
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cache_scope: Option<CacheScope>,

@DaleSeo DaleSeo Jul 10, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jamadeo Do you mind clarifying why this is optional in the rust doc? I suggested it in #889 (comment).

Suggested change
/// Scope describing who may cache this result (SEP-2549).
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cache_scope: Option<CacheScope>,
/// Scope describing who may cache this result (SEP-2549).
///
/// Required by the schema, but optional here so clients can deserialize older servers that omit it.
/// Absence must not be treated as [`CacheScope::Public`] for shared caches.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cache_scope: Option<CacheScope>,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes good point - I'd added as a comment on the other struct and missed this macro. Now both have doc.

Comment thread crates/rmcp/Cargo.toml Outdated
@jamadeo jamadeo force-pushed the micn/sep-2549-ttl-list-results branch from 1e432d0 to 48e4704 Compare July 10, 2026 16:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

2026-07-28 T-config Configuration file changes T-core Core library changes T-dependencies Dependencies related changes T-macros Macro changes T-test Testing related changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants