Retour au blog
Architecture agentique9 min

MCP en production : ce qui va vous faire mal avec la spec 2026-07-28

ÉS
Équipe SIFO Consulting
Agence multi-agents, Sfax (Tunisie)

On a passé trois mois à migrer cinq serveurs MCP clients vers la nouvelle spec. Je vous écris ça parce que la release candidate du 2026-07-28 est publiée depuis quelques jours, et que la plupart des équipes qu'on croise n'ont pas encore réalisé ce qui les attend.

Spoiler : si votre serveur MCP stocke du state en mémoire — et 80 % des serveurs qu'on a audités le font — vous avez environ deux mois pour vous mettre en règle avant que vos clients commencent à râler.

Le truc qui change tout : le protocole devient stateless

Je vais aller droit au but. La release 2026-07-28 prend une décision radicale : MCP est maintenant stateless au niveau du protocole. Six SEPs (Specification Enhancement Proposals) travaillent ensemble pour atteindre ça. C'est le changement le plus important depuis le lancement du protocole en 2024 (annonce officielle).

Concrètement ? Votre serveur peut désormais tourner derrière un load balancer round-robin standard. N'importe quelle requête peut atterrir sur n'importe quel replica. Le client cache tools/list aussi longtemps que votre ttlMs le permet. Plus de sticky sessions, plus de "mais pourquoi le client retombe pas sur le même nœud".

L'ancien monde, c'était ça :

Client ─── persistent SSE session ───► MCP Server (sticky session)
                                              │
                                              ├─ in-memory state
                                              └─ subscriptions

Si vous vouliez scaler horizontalement, il fallait soit dupliquer le state (cauchemar), soit forcer la session-affinity au niveau infra (compliqué et fragile). On a vu des équipes investir trois sprints juste pour faire tenir ça correctement avec un Redis et de la sérialisation custom.

Le nouveau monde, c'est :

Client ──HTTP + Mcp-Method header──► [Round-robin LB]
                                          │
                                          ▼
                              Replica 1 / 2 / N
                                          │
                                          ▼
                              Store partagé (Redis / SQL)

On a fait la bascule sur un serveur d'un client début avril. Le coût ops a baissé d'un tiers rien que parce que l'autoscaler Kubernetes a enfin pu faire son boulot. Les pods se créent et se détruisent sans qu'on doive se soucier de qui parle à qui.

Si votre code contient Map<sessionId, ...> quelque part, vous savez ce qui vous reste à faire d'ici juillet.

L'auth, enfin sérieuse

L'ancien modèle d'auth MCP, c'était sympa pour un PoC. Pour un déploiement enterprise, c'était limite gênant. La nouvelle spec aligne tout sur OAuth 2.1 + OpenID Connect, avec deux changements qu'il faut comprendre :

D'abord, la validation obligatoire du paramètre iss sur les réponses d'autorisation, conformément à RFC 9207 (c'est le SEP-2468 pour les obsédés du numéro). C'est une mitigation faible-coût contre une classe d'attaque "mix-up" qui touche particulièrement le pattern MCP single-client → many-servers. Imaginez Claude Desktop qui parle à votre serveur GitHub, votre serveur Slack et votre serveur CRM custom. Sans validation iss, un token destiné à GitHub peut techniquement être présenté à votre CRM et accepté. C'est exactement le genre de bug qu'on ne voit pas en dev et qui pète à 3h du matin.

Ensuite, PKCE obligatoire pour les clients publics, et des scopes alignés OIDC. Si votre serveur MCP n'a pas de scopes définis aujourd'hui, c'est le moment de mettre du mcp:tools:execute, mcp:resources:read, etc.

Voilà à quoi ressemble notre middleware Node/TypeScript de base, qu'on copie-colle sur les nouveaux projets :

import { validateIssuer } from "@modelcontextprotocol/auth";

export async function mcpAuthMiddleware(req: Request) {
  const tokenInfo = await validateIssuer(req, {
    expectedIssuer: process.env.MCP_OAUTH_ISSUER,
    audience: process.env.MCP_RESOURCE_ID,
  });

  if (!tokenInfo.valid) {
    return new Response("Unauthorized", { status: 401 });
  }

  if (!tokenInfo.scopes.includes("mcp:tools:execute")) {
    return new Response("Insufficient scope", { status: 403 });
  }

  return null;
}

Rien de magique. Mais c'est le minimum non-négociable maintenant.

La découverte via .well-known, ou comment être trouvé par les agents

Là, je trouve que c'est le truc le plus sous-estimé de la release. Le registre officiel MCP compte presque 2 000 serveurs publics quelques mois après son ouverture. La spec 2026 formalise les MCP Server Cards : un fichier de métadonnées que vous exposez sur https://votre-serveur.com/.well-known/mcp-server.json.

{
  "name": "sifo-crm-mcp",
  "version": "2.4.1",
  "protocolVersion": "2026-07-28",
  "capabilities": {
    "tools": true,
    "resources": true,
    "prompts": false,
    "apps": true
  },
  "transport": ["http", "websocket"],
  "auth": {
    "type": "oauth2",
    "issuer": "https://auth.sifo-consulting.com",
    "scopes": ["mcp:tools:execute", "mcp:resources:read"]
  },
  "rateLimits": { "perMinute": 600 },
  "contact": "mcp-support@sifo-consulting.com"
}

Pourquoi c'est important ? Parce qu'un crawler — registre, browser, agent autonome — peut découvrir vos capacités sans ouvrir de connexion. C'est l'équivalent d'un robots.txt enrichi pour les agents. Si vous bossez sur la visibilité GEO de votre boîte (et si vous lisez ce blog, vous devriez), c'est un must.

On l'a déployé sur les serveurs MCP qu'on opère pour nos clients. Soumission au registre officiel : 20 minutes. Les premières connexions de découverte sont arrivées dans la semaine.

Les deux extensions à connaître

Il y a deux nouvelles extensions dans cette spec que je veux mentionner rapidement parce qu'elles ouvrent des cas d'usage qu'on attendait depuis longtemps.

MCP Apps, d'abord. Un serveur peut désormais retourner non plus juste du JSON, mais des fragments d'UI (HTML contraint ou JSON-spec UI) que le client affiche dans une zone dédiée. Concrètement : votre serveur MCP "billing" peut retourner un widget "facture en attente, cliquez ici pour valider" plutôt qu'un texte que l'agent doit reformater et que l'utilisateur clique péniblement.

Tasks Extension, ensuite. Pour les opérations qui durent plus de quelques secondes — rendu vidéo, batch ETL, déploiement CI/CD — il y a enfin un pattern propre enqueue → poll → result, avec sémantique de résumabilité côté client. Plus besoin de hacker des callbacks SSE custom. On en avait fait trois ou quatre à la main pour des clients, c'est franchement appréciable de pouvoir poser tout ça.

Et la politique de dépréciation

Avant, les changements breaking arrivaient sans préavis structuré. Vous deviez suivre le repo GitHub, lire les release notes en diagonale, espérer ne rien rater. Maintenant : annonce en spec N → marquage deprecated en spec N+1 → suppression possible en spec N+2 minimum. C'est ce qu'on attend d'un protocole sérieux. Pour les équipes plateforme qui prévoient un roadmap à 12 mois, ça change tout.

La trajectoire de migration qu'on suit

Pour résumer ce qu'on a appris des cinq migrations qu'on a faites depuis février : comptez deux à trois semaines pour un serveur de complexité moyenne. Voici le découpage qui marche bien :

Vous commencez par un audit (deux jours bien tassés), où vous listez tout ce qui est state en mémoire, vos scopes OAuth actuels, vos capabilities exposées. C'est l'étape la plus importante parce que vous allez découvrir des trucs que personne ne se souvient pourquoi ils sont là.

Ensuite vous externalisez le state — c'est typiquement une semaine de boulot, parce qu'il faut souvent reprendre des bouts de code écrits avec l'hypothèse "même process". On bascule en général sur Redis pour les sessions courtes et Postgres pour le state durable.

Trois jours pour l'auth hardening : validation iss, PKCE, scopes alignés. Une journée pour le Server Card et la soumission au registre. Deux jours de tests de charge avec k6 ou Vegeta pour valider que le round-robin LB tient sous load.

Ça fait deux à trois semaines pour passer d'un serveur MCP "ça marche" à un serveur MCP "ça scale". Le coût ROI est immédiat : auditabilité OAuth, horizontal scaling, et découvrabilité.

Trois pièges qui nous ont coûté du temps

Je vais finir avec les trois trucs qui nous ont fait perdre du temps, pour que vous les évitiez.

Cache tools/list trop agressif côté client. Le serveur annonce un ttlMs long pour la perf, mais oublie d'invalider quand un déploiement modifie le schéma des tools. Résultat : pendant 10 minutes, l'agent essaie d'appeler des tools avec une signature obsolète. Le fix qu'on a mis en place : exposer aussi un tools/list/etag et utiliser If-None-Match sur les requêtes. Le client revalide cheap, vous gardez le cache, tout le monde est content.

Auth issuer mal-configuré pour les serveurs multi-tenants. Le iss doit refléter le tenant, pas l'app globale. Sinon, deux tenants distincts peuvent voir leurs tokens acceptés sur la mauvaise ressource. On l'a vu en pre-prod chez un client, c'était glaçant.

Tasks extension utilisée comme excuse pour mal écrire. Si une opération peut tenir en 1 seconde, ne la mettez pas en tasks async — vous ajoutez une round-trip et un timeout potentiel pour rien. On a vu une équipe asyncifier tout son CRUD "parce que c'est plus moderne". Latence multipliée par trois sur les opérations simples. Évitez.

Pour aller plus loin


Si vous gérez un serveur MCP en production et que ce qui précède vous a fait grincer des dents, écrivez-nous. On fait l'audit en deux jours, on chiffre la migration, et vous savez à quoi vous engager pour l'été 2026.

#MCP#Anthropic#Claude#production#OAuth