Skip to main content

MCP response caching

When agents call the same MCP tools repeatedly with similar arguments, every call travels to the upstream server and the identical result is sent back to the LLM context each time. Catalyst can cache those responses at the sidecar layer so repeated calls return instantly from memory.

Caching is opt-in and per-server — you enable it by adding a cache block to the MCPServer spec.

What is cached

MCP methodCache categoryDefault TTL
tools/callData30 s
resources/readData30 s
tools/listMetadata5 min
prompts/listMetadata5 min
resources/listMetadata5 min
resources/templates/listMetadata5 min

Mutating operations (initialize, subscribe, unsubscribe), notifications, and SSE streaming responses are never cached.

Data operations (tools/call, resources/read) return tool execution results that may change frequently — they use the shorter ttl.

Metadata operations (the list methods) return slowly-changing server capability information — they use metadataTTL, which defaults to a longer window because the set of available tools or resources rarely changes mid-session.

Enable caching

Add a cache block to your MCPServer spec:

apiVersion: dapr.io/v1alpha1
kind: MCPServer
metadata:
name: my-mcp
spec:
endpoint:
streamableHTTP:
url: https://mcp.example.com/mcp
cache:
enabled: true

This enables caching with default TTLs (30 s for data, 5 min for metadata). Apply the change:

diagrid apply -f my-mcp.yaml

Custom TTLs

Override either TTL to suit the upstream server's change rate:

spec:
cache:
enabled: true
ttl: 60s # tools/call, resources/read
metadataTTL: 10m # tools/list, prompts/list, resources/list

A shorter ttl keeps data fresher at the cost of more upstream calls; a longer metadataTTL is safe when the server's tool catalog is stable.

Cache key and caller isolation

Each cache entry is keyed on:

  • MCP server name — the MCPServer resource name
  • Method — e.g. tools/call
  • Parameters — the full JSON-RPC params object (canonicalized)
  • Caller — the App ID of the calling agent

Because the caller is part of the key, caches are always isolated per agent. Agent A's cached result is never served to Agent B, even for the same tool and arguments.

Cache invalidation

Cache entries expire by TTL. Additionally, any change to the MCPServer spec (updating the URL, rotating credentials, changing the cache config itself) triggers a full cache flush for that server — you do not need to worry about stale entries after a configuration change.

Responses that contain errors (JSON-RPC error objects or isError: true in the result) are never cached.

When not to use caching

Caching works best for tools that return the same result for the same input within a short window. Avoid enabling it for:

  • Side-effecting tools that create, update, or delete resources (e.g. create_issue, send_email). While caching won't prevent the first call, it would serve a stale response on a retry.
  • Real-time data where even a 30-second delay is unacceptable.
  • SSE (Server-Sent Events) streams — these are automatically excluded from caching regardless of configuration.

See also