MCP Fusion/Protocol and runtime/Sincronização de estado
Sincronização de estado
Diga ao agente o que pode ser reaproveitado e o que acabou de ficar obsoleto: hints de cache-control nas descrições, invalidação com escopo glob nas mutations, notificações de recursos e cache de listas do MCP 2.0.
O fracasso clássico de um agente depois de uma mutation: ele relê dados obsoletos, "corrige" o problema errado ou reaplica a própria mudança porque a leitura veio do contexto dele, não do seu servidor. A camada de sincronização de estado do MCP Fusion responde a uma única pergunta: quando o agente pode confiar em dados em cache, e o que avisa que um domínio acabou de ficar obsoleto?
Isto não é um cache de respostas. O MCP Fusion nunca armazena resultados de tools. É um sistema de sinalização temporal, usando o vocabulário de cache HTTP que o modelo já entende.
Declarando a política
Três métodos em qualquer tool:
f.query('billing.get_invoice')
.cached() // "[Cache-Control: immutable]" on the description
.handle(...)
f.mutation('billing.refund')
.invalidates('billing.get_*', 'dashboard.invoices')
.handle(...).cached()carimbaimmutable;.stale()carimbano-store; não existemax-age, porque modelos de linguagem não têm relógio.invalidates(patterns)declara quais domínios uma chamada bem-sucedida torna stale, com padrões dot-glob (*um segmento,**qualquer profundidade)- as hints são compiladas em políticas num
PolicyEnginefirst-match-wins com resolução memoizada
O que vai para o fio
Duas interceptações na camada de protocolo, não middlewares:
Em tools/list, as descrições decoradas carregam a diretiva: Retrieve an invoice by ID [Cache-Control: immutable]. O agente vê a regra de reuso no momento de planejar.
Em tools/call, apenas chamadas bem-sucedidas disparam invalidação (uma mutation isError falha não emite nada). A resposta ganha uma tag legível por máquina como primeiro item de conteúdo, posicionada no índice 0 para que o truncamento não a corte:
<cache_invalidation cause="billing.refund" domains="billing.get_*" />e cada URI stale dispara notifications/resources/updated com um mcpfusion://stale/{pattern} sintético, para que clientes com assinaturas saibam exatamente o que descartar.
Recursos e assinaturas
Recursos reais passam por f.resource() (ou defineResource): um template de URI como invoices://{id}, um handler que retorna { text } ou { blob }, um flag subscribable e anotações de audiência. URIs de template são resolvidas com matching estilo RFC-6570.
No MCP 2.0 o stream subscriptions/listen é de primeira classe: um cliente registra um filtro (toolsListChanged, promptsListChanged, resourcesListChanged, URIs específicas em resourceSubscriptions), o servidor confirma com o filtro atendido e transmite os eventos correspondentes. A entrega é best-effort e nunca bloqueia o pipeline: uma notificação é descartada, não gera backpressure.
Cache de listas (SEP-2549)
Separado do staleness de tools, o MCP 2.0 permite que um servidor anexe metadados de cache aos resultados de listagem: ttlMs e scope (private por cliente, public compartilhado) em tools/list, prompts/list e nas listas de recursos, configurados com attachToServer({ listCacheTtlMs, listCacheScope }). Padrão: 5 minutos, private. Um proxy na frente do seu conector pode então servir chamadas de listagem repetidas do próprio cache, que é a resposta do protocolo para clientes verbosos no cold start. Defina listCacheTtlMs: 0 e os metadados desaparecem com overhead zero.
O manifesto dinâmico e a introspecção
attachToServer({ introspection: { enabled: true } }) registra o recurso mcpfusion://manifest.json: toda tool, ação, presenter, chave de schema, flag destrutivo e flag de regra contextual, filtrados por RBAC a cada leitura com um contexto fresco de contextFactory, para que duas sessões leiam o manifesto que têm direito de ver. A mesma máquina de materializar e digerir é o que Governance tranca.
Por que não max-age
Porque não existe timer dentro do modelo: ele não pode checar um header de frescor, só pode ser avisado. immutable significa "reaproveite nesta conversa a menos que eu diga o contrário"; os eventos de invalidação são o "contrário". O vocabulário HTTP é emprestado justamente porque os modelos foram treinados nele, e o sufixo [Cache-Control] viaja dentro da descrição da tool, que é o único texto que o agente lê de forma confiável antes de planejar.
Próximos passos
- Streaming and cancellation: progresso em chamadas longas
- Runtime architecture: onde esses hooks ficam
- Tools: os métodos do builder
