Skip to content

Document caching behavior and warn on non-conformant draft cacheable results (SEP-2549 follow-up)#1669

Open
tarekgh wants to merge 1 commit into
modelcontextprotocol:mainfrom
tarekgh:tarekgh/sep-2549-cacheable-followups
Open

Document caching behavior and warn on non-conformant draft cacheable results (SEP-2549 follow-up)#1669
tarekgh wants to merge 1 commit into
modelcontextprotocol:mainfrom
tarekgh:tarekgh/sep-2549-cacheable-followups

Conversation

@tarekgh

@tarekgh tarekgh commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Follow-up to the SEP-2549 caching hints work in #1623, addressing two of its tracked follow-up issues.

Fixes #1645 (docs)

Tightens the <remarks> on the auto-paginating list overloads (ListToolsAsync, ListPromptsAsync, ListResourcesAsync, ListResourceTemplatesAsync) to state plainly that:

  • The SDK performs no internal caching of listing results.
  • ttlMs/cacheScope are intrinsically per page and are not surfaced on the flattened convenience overloads.
  • Callers that want to cache should use the lower-level non-auto-paginating overloads, which return those fields per page.

No behavioral change for #1645, docs only.

Fixes #1650 (conformance warning)

Logs a warning (never throws) when a server that negotiated the draft protocol version returns a cacheable result without the now required ttlMs/cacheScope fields. Covered methods: tools/list, prompts/list, resources/list, resources/templates/list, resources/read.

Details:

  • The warning is emitted at most once per method per session, so paginated listings do not produce one warning per page.
  • The raw cacheable overloads keep their synchronous argument validation and route results through a shared ValidateCacheableResultAsync helper that calls a new ValidateCacheableResult seam on McpClient.
  • The seam is a no-op by default and overridden by McpClientImpl to perform the check, gated on the negotiated draft protocol version (so older servers never warn).
  • The SDK's own server always injects conservative defaults for these fields, so this only fires against third-party non-conformant draft servers.

Note on #1646

The optional client-side caching subsystem (#1646) was reviewed and closed as not planned. No caching subsystem is added here; if demand materializes we can add it later on top of the lower-level overloads.

Tests

New CacheableResultWarningTests (10 tests, using an in-memory Pipe + StreamClientTransport so raw responses can omit the fields, which the real SDK server never does):

  • Each of the five methods warns when a draft server omits both hints.
  • Warning text reflects which field(s) are missing.
  • No warning when both hints are present, or when an older protocol version was negotiated.
  • Auto-paginating overload warns through the per-page path.
  • Multi-page paginated listing warns only once per method.

Verification

  • dotnet build clean (0 warnings / 0 errors).
  • New tests pass on net8.0/net9.0/net10.0; net472 excluded by #if !NET472.

…results

Follow-up to the SEP-2549 caching hints work in PR modelcontextprotocol#1623, addressing two of
its tracked follow-up issues:

Fixes modelcontextprotocol#1645: Tighten the doc comments on the auto-paginating list overloads
(tools/prompts/resources/resource-templates) to state plainly that the SDK
performs no internal caching of listing results, and that any caching of
ttlMs/cacheScope must be done by the caller via the lower-level
non-auto-paginating overloads, which surface those fields per page.

Fixes modelcontextprotocol#1650: Log a warning (never throw) when a server that negotiated the
draft protocol version returns a cacheable result (tools/list, prompts/list,
resources/list, resources/templates/list, resources/read) without the now
required ttlMs/cacheScope fields. The warning is emitted at most once per
method per session so paginated listings do not produce one warning per page.

The raw cacheable overloads keep their synchronous argument validation and
route results through a shared ValidateCacheableResultAsync helper that calls
the new ValidateCacheableResult seam on McpClient. The seam is a no-op by
default and overridden by McpClientImpl to perform the conformance check.

Issue modelcontextprotocol#1646 (optional client-side caching subsystem) was reviewed and closed
as not planned; no caching subsystem is added here.
@tarekgh

tarekgh commented Jun 23, 2026

Copy link
Copy Markdown
Contributor Author

Heads-up on a small expected conflict with #1610 (default draft protocol support: sessionless + handshake-less).

What overlaps:

  • src/ModelContextProtocol.Core/Client/McpClientImpl.cs: Default draft protocol support: sessionless + handshake-less (SEP-2575 + SEP-2567) #1610 rewrites a lot of the client negotiation logic. This PR adds an isolated ValidateCacheableResult override plus a [LoggerMessage] and one dedup field, so any conflict here is small and mechanical.
  • Draft protocol version constant: Default draft protocol support: sessionless + handshake-less (SEP-2575 + SEP-2567) #1610 changes McpSessionHandler.DraftProtocolVersion from "DRAFT-2026-v1" to the spec string "2026-07-28". This PR's source code gates the warning on the symbolic constant McpSessionHandler.DraftProtocolVersion, so it stays correct automatically after the rename. The only thing that needs updating is the new test file CacheableResultWarningTests.cs, which hardcodes the literal "DRAFT-2026-v1" (same one-line update every other draft test takes).

How to resolve when the two land together:

  1. Update the DraftProtocolVersion literal in CacheableResultWarningTests.cs to match whatever string Default draft protocol support: sessionless + handshake-less (SEP-2575 + SEP-2567) #1610 settles on.
  2. If Default draft protocol support: sessionless + handshake-less (SEP-2575 + SEP-2567) #1610 makes the draft handshake sessionless/handshake-less, double-check the manual initialize handshake in the test helper still applies for the negotiated-version path, or adjust the setup accordingly.

Forward-looking (not part of this PR): #1610 adds server/discover returning a DiscoverResult that also carries ttlMs/cacheScope under draft. Once it lands, the same conformance warning should be extended to that path as a follow-up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant