MCP Fusion/Protocol and runtime/Synchronisation d’état
Synchronisation d’état
Indiquez à l’agent ce qui peut être réutilisé et ce qui vient de périmer : des hints de cache-control sur les descriptions, une invalidation à portée glob sur les mutations, des notifications de ressources et le cache des listes MCP 2.0.
L’échec classique d’un agent après une mutation : il relit des données périmées, « corrige » le mauvais problème ou réapplique sa modification parce que la lecture vient de son propre contexte, et non de votre serveur. La couche de synchronisation d’état de MCP Fusion répond à une seule question : quand l’agent peut-il se fier aux données en cache, et qu’est-ce qui lui indique qu’un domaine vient de périmer ?
Ce n’est pas un cache de réponses. MCP Fusion ne stocke jamais les résultats de tools. C’est un système de signalisation temporelle, qui utilise le vocabulaire de cache HTTP que le modèle comprend déjà.
Déclarer la politique
Trois méthodes sur n’importe quelle 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()apposeimmutable;.stale()apposeno-store; il n’y a pas demax-age, parce que les modèles de langage n’ont pas d’horloge.invalidates(patterns)déclare quels domaines un appel réussi rend stale, avec des motifs dot-glob (*un segment,**n’importe quelle profondeur)- les hints sont compilés en politiques dans un
PolicyEngineà premier match gagnant, avec résolution mémoïsée
Ce qui part sur le fil
Deux interceptions au niveau protocole, pas des middlewares :
Sur tools/list, les descriptions décorées portent la directive : Retrieve an invoice by ID [Cache-Control: immutable]. L’agent voit la règle de réutilisation au moment de planifier.
Sur tools/call, seuls les appels couronnés de succès déclenchent l’invalidation (une mutation isError échouée n’émet rien). La réponse gagne une balise lisible par machine comme premier élément de contenu, placée à l’index 0 pour que la troncature ne puisse pas la rogner :
<cache_invalidation cause="billing.refund" domains="billing.get_*" />et chaque URI stale déclenche notifications/resources/updated avec un mcpfusion://stale/{pattern} synthétique, afin que les clients abonnés sachent exactement quoi jeter.
Ressources et abonnements
Les vraies ressources passent par f.resource() (ou defineResource) : un gabarit d’URI comme invoices://{id}, un handler renvoyant { text } ou { blob }, un flag subscribable et des annotations d’audience. Les URI de gabarit sont résolues par une correspondance de style RFC-6570.
Avec MCP 2.0, le flux subscriptions/listen est de première classe : un client enregistre un filtre (toolsListChanged, promptsListChanged, resourcesListChanged, des URI précises dans resourceSubscriptions), le serveur accuse réception du filtre honoré et diffuse les événements correspondants. La livraison est best-effort et ne bloque jamais le pipeline : une notification est jetée, pas soumise à du backpressure.
Cache des listes (SEP-2549)
Indépendant du staleness des tools, MCP 2.0 permet à un serveur d’attacher des métadonnées de cache aux résultats de listage : ttlMs et scope (private par client, public partagé) sur tools/list, prompts/list et les listes de ressources, configurés avec attachToServer({ listCacheTtlMs, listCacheScope }). Par défaut : 5 minutes, private. Un proxy devant votre connecteur peut alors servir les appels de listage répétés depuis son cache, ce qui est la réponse du protocole aux clients verbeux au cold start. Mettez listCacheTtlMs: 0 et les métadonnées disparaissent avec un overhead nul.
Le manifeste dynamique et l’introspection
attachToServer({ introspection: { enabled: true } }) enregistre la ressource mcpfusion://manifest.json : chaque tool, action, presenter, clé de schéma, flag destructif et flag de règle contextuelle, filtré par RBAC à chaque lecture avec un contexte frais fourni par contextFactory, pour que deux sessions lisent le manifeste auquel elles ont droit. La même machine à matérialiser puis digérer est ce que verrouille Governance.
Pourquoi pas max-age
Parce qu’il n’y a pas de temporiseur dans le modèle : il ne peut pas vérifier un en-tête de fraîcheur, on ne peut que le lui dire. immutable signifie « réutilisez dans cette conversation sauf mention contraire de ma part » ; les événements d’invalidation sont cette mention contraire. Le vocabulaire HTTP est emprunté précisément parce que les modèles sont entraînés dessus, et le suffixe [Cache-Control] voyage à l’intérieur de la description de la tool, le seul texte que l’agent lit de façon fiable avant de planifier.
Prochaines étapes
- Streaming and cancellation : la progression sur les appels longs
- Runtime architecture : où se situent ces hooks
- Tools : les méthodes du builder
