Repository navigation
Expose optional cache outcome events on the high-level Client #3777
Description
Description
The high-level Client has a built-in response cache for methods such as tools/list, prompts/list, resources/list, resources/templates/list, and resources/read.
When one of these calls returns quickly, transport-level instrumentation alone can't tell whether the result came from the cache or from a network request. This makes it harder to diagnose MCP tool-discovery latency, measure cache effectiveness, and investigate stale resource data in applications built around LLM agents.
It would be useful to expose an optional hook that reports cache decisions directly from the high-level Client, without requiring applications to wrap client methods or instrument the cache themselves.
For example, the API could expose a small event like this:
CacheEvent(
method="tools/list",
outcome="hit",
)The initial set of outcomes should cover:
hit- a fresh cached response is returned without a transport request.miss- a normal cache lookup finds no fresh entry, so the request is sent and the response is cached according to the existing policy.bypass- the call skips cache reads and writes.refresh- the call fetches a new response regardless of whether a fresh entry exists, then updates the cache according to the existing policy.
The reported outcome should reflect what actually happened. For example, a request carrying metadata may require a network round trip even when the default cache mode is use.
Keep the event schema small and stable so applications can map events to their own metrics, logs, or traces. Events should identify the logical MCP method and cache outcome without exposing tool arguments, resource contents, full resource URIs, credentials, or private cache keys.
TTL expiry should be reflected in the resulting lookup outcome rather than counted as a second event for the same operation. Notification-driven invalidation can have a separate event if needed, with semantics distinct from a cache miss.
The hook should be opt-in and leave existing caching behavior unchanged, including TTL handling, private/public cache partitioning, pagination, derived tool metadata, and notification-driven invalidation. Observer failures must not affect request results or prevent invalidation from completing. Callback delivery semantics should be documented, and user callbacks should never run while internal cache locks are held.
This would give MCP applications a way to understand cache behavior and diagnose latency without introducing a mandatory telemetry dependency or changing the caching policy.
Tests should cover hits without transport calls, misses, bypass, refresh, TTL expiry, notification-driven invalidation, observer failures, and the absence of cached payloads or private cache keys in emitted events.
References
- MCP Python SDK - Client caching documentation
https://github.com/modelcontextprotocol/python-sdk/blob/main/docs/client/caching.md - MCP Python SDK - High-level Client implementation
https://github.com/modelcontextprotocol/python-sdk/blob/main/src/mcp/client/client.py - MCP TypeScript SDK - Cache mode and response-cache implementation reference
https://github.com/modelcontextprotocol/typescript-sdk/blob/main/packages/client/CHANGELOG.md
Activity