Skip to content

mcp: add ServerOptions.DefaultCacheable - #1128

Open
arimu1 wants to merge 5 commits into
modelcontextprotocol:mainfrom
arimu1:fix/1094-default-cacheable
Open

mcp: add ServerOptions.DefaultCacheable#1128
arimu1 wants to merge 5 commits into
modelcontextprotocol:mainfrom
arimu1:fix/1094-default-cacheable

Conversation

@arimu1

@arimu1 arimu1 commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds ServerOptions.DefaultCacheable *Cacheable so multi-tenant / private servers can override the SDK's forced cacheable defaults (cacheScope: "public", ttlMs: 0) on SDK-generated results.

  • Nil keeps today's historical defaults (no behavior change).
  • Non-nil values are stamped by setDefaultCacheableValues on server/discover, tools/list, prompts/list, resources/list, resources/templates/list, and resources/read (after the handler returns).
  • Receiving middleware can still overwrite Cacheable per result after the SDK stamps values (useful for per-request / per-tenant policy).

Fixes #1094

Motivation

Servers whose list/discover payloads are tenant-scoped want private (and a real TTL) as the SDK baseline, not only via post-hoc middleware type-switches. A single option covers all current SDK stamp sites and any future call sites that use the same helper.

Test plan

  • go test ./mcp/ -run 'TestServerDefaultCacheable|TestSetDefaultCacheableValues' -count=1
  • go test ./mcp/ -count=1
  • go test ./... -count=1
  • Confirmed historical defaults when DefaultCacheable is nil
  • Confirmed private/60s stamped on list + read results when set
  • Confirmed nil-defaults path still preserves pre-set TTLMs (read handler) while forcing CacheScope: "public"

Comment thread mcp/server_test.go Outdated
}
}

func TestSetDefaultCacheableValues(t *testing.T) {

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.

lets remove this test

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.

You did not remove the test i intended

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Removed TestSetDefaultCacheableValues (this was the one you intended). Behavior is covered by TestServerDefaultCacheable under the new callback API, including empty CacheScope"public".

@arimu1

arimu1 commented Aug 3, 2026

Copy link
Copy Markdown
Contributor Author

Removed TestServerDefaultCacheable as requested, and rebased onto current main. Production ServerOptions.DefaultCacheable behavior and the unit test TestSetDefaultCacheableValues are unchanged.

@arimu1
arimu1 force-pushed the fix/1094-default-cacheable branch from 7d4f460 to 7a5a2c0 Compare August 3, 2026 23:31
Comment thread mcp/protocol.go
Comment on lines +1197 to +1202
func (c *Cacheable) setDefaultCacheableValues(defaults *Cacheable) {
if defaults != nil {
c.TTLMs = defaults.TTLMs
c.CacheScope = defaults.CacheScope
return
}

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.

the issue here is that if defaults does not set the CacheScope, it will not be set to public

@arimu1
arimu1 force-pushed the fix/1094-default-cacheable branch from 7a5a2c0 to 393674c Compare August 4, 2026 14:27
@arimu1

arimu1 commented Aug 4, 2026

Copy link
Copy Markdown
Contributor Author

@guglielmo-san Thanks — fixed setDefaultCacheableValues so an empty CacheScope on non-nil defaults falls back to "public" (same as nil defaults). Added regression test defaults with empty CacheScope fall back to public.

Comment thread mcp/server.go Outdated
Comment on lines +173 to +180
// DefaultCacheable, if non-nil, supplies the [Cacheable] values stamped on
// SDK-generated results (server/discover, list methods, and resources/read
// after the handler returns). If nil, those results use the historical
// defaults: CacheScope "public" and TTLMs 0.
//
// Receiving middleware can still overwrite Cacheable on a per-result basis
// after the SDK stamps these values.
DefaultCacheable *Cacheable

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.

What do you think about using a callback instead? I think it would give more flexibility.

// DefaultCacheable, if non-nil, is called for each SDK-generated
// cacheable result (server/discover, *_list, resources/read) to
// determine the Cacheable values stamped on the response. The
// request is provided so policy can vary by method, session,
// tenant, or authentication state.
//
// If nil, SDK-generated results use CacheScope "public" and
// TTLMs 0, matching the historical defaults.

DefaultCacheable func(ctx context.Context, req Request) Cacheable

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Adopted as proposed: DefaultCacheable func(ctx context.Context, req Request) Cacheable. See tip 15b7b8f.

Comment thread mcp/server_test.go Outdated
}
}

func TestSetDefaultCacheableValues(t *testing.T) {

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.

You did not remove the test i intended

arimu1 added 4 commits August 5, 2026 20:14
Allow servers to override the Cacheable defaults stamped on
SDK-generated results (discover, list methods, resources/read).
Nil keeps historical public/0 defaults.

Fixes modelcontextprotocol#1094
ServerOptions.DefaultCacheable may set only TTLMs. Empty CacheScope on
defaults must still fall back to "public" instead of stamping "".

Signed-off-by: arimu1 <19286898+arimu1@users.noreply.github.com>
Replace the static *Cacheable option with a callback that receives
context and Request so cache policy can vary by method, session,
tenant, or auth. Empty CacheScope from the callback still falls back
to "public". Remove TestSetDefaultCacheableValues per review; cover
behavior via TestServerDefaultCacheable.

Fixes modelcontextprotocol#1094
@arimu1
arimu1 force-pushed the fix/1094-default-cacheable branch from 393674c to 15b7b8f Compare August 5, 2026 13:15
@arimu1

arimu1 commented Aug 5, 2026

Copy link
Copy Markdown
Contributor Author

@guglielmo-san Thanks for the feedback — adopted the callback API:

DefaultCacheable func(ctx context.Context, req Request) Cacheable
  • Nil keeps historical public / ttlMs: 0 defaults.
  • Callback return values are stamped on SDK-generated results (server/discover, *_list, resources/read); empty CacheScope still falls back to "public".
  • Removed TestSetDefaultCacheableValues (the unit test you intended). Coverage is via restored TestServerDefaultCacheable (historical defaults, private/TTL, empty-scope fallback).

Tip: 15b7b8f720c78d008e0f18f1961e1cb99c9afc0e
go test ./mcp/... passes.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

No option to override forced Cacheable defaults (cacheScope public, ttlMs 0) on SDK-generated results

2 participants