MCP Fusion/Protocol and runtime/State sync

State sync

Ask AI about Vinkius

Tell the agent what may be reused and what just went stale: cache-control hints on descriptions, glob-scoped invalidation on mutations, resource notifications and MCP 2.0 list caching.

The classic failure of an agent after a mutation: it re-reads stale data, "fixes" the wrong problem, or re-applies its change because the read came from its own context, not your server. MCP Fusion's state sync layer answers a single question: when may the agent trust cached data, and what tells it that a domain just went stale?

This is not a response cache. MCP Fusion never stores tool results. It is a temporal signaling system, using HTTP cache vocabulary the model already understands.

Declaring the policy

Three methods on any tool:

typescript
f.query('billing.get_invoice')
  .cached()                          // "[Cache-Control: immutable]" on the description
  .handle(...)

f.mutation('billing.refund')
  .invalidates('billing.get_*', 'dashboard.invoices')
  .handle(...)
  • .cached() stamps immutable; .stale() stamps no-store; there is no max-age, because language models have no clock
  • .invalidates(patterns) declares which domains a successful call makes stale, with dot-glob patterns (* one segment, ** any depth)
  • hints compile into policies in a first-match-wins PolicyEngine with memoized resolution

What lands on the wire

Two protocol-layer interceptions, not middleware:

On tools/list, decorated descriptions carry the directive: Retrieve an invoice by ID [Cache-Control: immutable]. The agent sees the reuse rule at planning time.

On tools/call, only successful calls trigger invalidation (a failed isError mutation emits nothing). The response gains a machine-readable tag as its first content item, positioned at index 0 so truncation cannot clip it:

xml
<cache_invalidation cause="billing.refund" domains="billing.get_*" />

and every stale URI fires notifications/resources/updated with a synthetic mcpfusion://stale/{pattern}, so clients holding subscriptions know exactly what to drop.

Resources and subscriptions

Real resources go through f.resource() (or defineResource): a URI template like invoices://{id}, a handler returning { text } or { blob }, an subscribable flag, and audience annotations. Template URIs are resolved with RFC-6570-style matching.

On MCP 2.0 the subscriptions/listen stream is first class: a client registers a filter (toolsListChanged, promptsListChanged, resourcesListChanged, specific resourceSubscriptions URIs), the server acknowledges with the honored filter and streams matching events. Delivery is best-effort and never blocks the pipeline: a notification is dropped, not backpressured.

List caching (SEP-2549)

Separate from tool staleness, MCP 2.0 lets a server attach cache metadata to list results: ttlMs and scope (private per client, public shared) on tools/list, prompts/list and the resource lists, configured with attachToServer({ listCacheTtlMs, listCacheScope }). Default: 5 minutes, private. A proxy in front of your connector can then serve repeated list calls from its cache, which is the protocol's answer to cold-start chatty clients. Set listCacheTtlMs: 0 and the metadata disappears with zero overhead.

The dynamic manifest and introspection

attachToServer({ introspection: { enabled: true } }) registers the mcpfusion://manifest.json resource: every tool, action, presenter, schema key, destructive flag and contextual-rule flag, RBAC-filtered per read with a fresh contextFactory context, so two sessions read the manifest they are entitled to see. The same materialize-and-digest machinery is what Governance locks.

Why not max-age

Because there is no timer inside the model: it cannot check a freshness header, it can only be told. immutable means "reuse within this conversation unless I say otherwise"; invalidation events are the "otherwise". The HTTP vocabulary is borrowed precisely because models are trained on it, and the [Cache-Control] suffix rides inside the tool description, which is the only text the agent reliably reads before planning.

Next steps