MCP 2026-07-28 : la spec stateless
Le 28 juillet 2026, le Model Context Protocol a verrouillé sa plus grosse révision depuis le lancement. Le titre : MCP est stateless. La poignée de main initialize et le header Mcp-Session-Id ont disparu ; chaque requête porte sa propre identité dans _meta ; n'importe quelle instance de serveur derrière un load balancer peut répondre à n'importe quel appel. Le MCP serverless n'est plus un contournement — c'est la forme du protocole.
- Ce qui a réellement changé dans la spec 2026-07-28 — les quatre suppressions et les quatre ajouts qui comptent
- Multi Round-Trip Requests (MRTR) : comment un serveur stateless demande une question de suivi à l'utilisateur sans session
- Le framework Extensions et les deux extensions officielles : MCP Apps et Tasks
- Durcissement de l'autorisation : OAuth 2.1, validation iss RFC 9207, et ce que Dynamic Client Registration exige maintenant
- Un chemin de migration concret qui ne casse pas vos clients 2025-11-25 — avec les versions beta des SDK à installer aujourd'hui
La version en un paragraphe
Avant : poignée de main initialize → cookie Mcp-Session-Id → paire client/serveur collante pendant la vie de la session. Après : pas de poignée de main, pas d'ID de session, pas de collant. L'identité et les capacités du client roulent sur chaque requête à l'intérieur d'un objet _meta. Une nouvelle méthode server/discover remplace l'échange initial de capacités. L'état applicatif — un panier, une tâche en cours — vit dans des handles que l'outil retourne et que le client repasse au prochain appel, exactement comme un ID de ressource REST. Ce seul changement est ce qui débloque le déploiement serverless et edge, le vrai scaling horizontal, et la capacité de deux implémentations concurrentes à s'asseoir derrière la même URL.
Ce qui a été supprimé
- Header Mcp-Session-Id — et toute la notion de session au niveau du protocole
- Poignée de main initialize / initialized — remplacée par _meta sur chaque requête + server/discover à la demande
- Roots, Sampling et Logging — dépréciés. Roots : passez les chemins comme paramètres d'outil. Sampling : appelez le LLM vous-même. Logging : utilisez stderr ou OpenTelemetry.
- tasks/list — supprimé même à l'intérieur de la nouvelle extension Tasks, parce que lister les tâches sans session fuit entre les tenants
Les dépréciations Roots/Sampling/Logging sont celles que la plupart des serveurs existants touchent réellement. Toutes trois supposaient un canal serveur↔client bidirectionnel persistant. Dans un monde stateless, le client possède le LLM, les chemins et le puits de logs — le serveur ne fait que répondre à l'appel d'outil.
Ce qui a été ajouté
- Un RPC stateless que les clients appellent chaque fois qu'ils ont besoin de savoir ce qu'un serveur offre. Remplace les capacités que l'ancienne poignée de main retournait. Mettez en cache la réponse avec les nouveaux champs ttlMs / cacheScope sur la réponse elle-même — la spec hérite des sémantiques HTTP Cache-Control.
- Mcp-Method et Mcp-Name (par ex. tools/call, search) laissent un load balancer router sans parser JSON-RPC. MCP-Protocol-Version remplace la session comme négociateur de version.
- La réponse stateless à l'élicitation. Si un outil a besoin d'entrée en cours d'exécution, le serveur retourne un InputRequiredResult portant la question et un blob opaque requestState. Le client réémet l'appel avec inputResponses plus le requestState renvoyé — et n'importe quelle instance de serveur peut le reprendre.
- Reverse-DNS namespacé, versionné indépendamment, négocié à travers une carte de capacité extensions. Les extensions officielles livrent en premier : MCP Apps (UI HTML sandboxées, SEP-1865) et Tasks (opérations à long run avec tasks/get, tasks/update, tasks/cancel ; SEP-2663). Tout le reste qui exigeait auparavant un changement de spec core livre maintenant comme extension.
- Les inputSchema et outputSchema d'outils acceptent maintenant oneOf / anyOf / allOf, les conditionnels et $ref. Si vous aplatissiez votre schéma pour tenir dans l'ancien sous-ensemble MCP, arrêtez.
- traceparent, tracestate et baggage voyagent dans _meta. Le tracing distribué à travers une chaîne client → connecteur → serveur fonctionne enfin nativement.
- 12 mois minimum entre Actif → Déprécié → Supprimé. Tout ce qui est déprécié le 28 juillet 2026 continue à fonctionner jusqu'à au moins le 28 juillet 2027, et la suppression nécessite sa propre SEP.
Le seul changement JSON qui piège tout le monde
Le code d'erreur missing-resource est passé de -32002 à -32602 (Invalid Params). Si votre client a une branche if (err.code === -32002) quelque part, elle cesse silencieusement de se déclencher le 28 juillet. C'est le bug d'intégration le plus courant dans le RC.
Avant / Après
// BEFORE (2025-11-25): stateful handshake
POST /mcp { "method": "initialize", "params": { "capabilities": {...} } }
→ sets Mcp-Session-Id: abc123
POST /mcp Mcp-Session-Id: abc123
{ "method": "tools/call", "params": { "name": "search", ... } }
// server assumes it "knows" you because of the session cookie
// AFTER (2026-07-28): self-describing request
POST /mcp Mcp-Method: tools/call
Mcp-Name: search
MCP-Protocol-Version: 2026-07-28
{
"method": "tools/call",
"params": { "name": "search", "arguments": {...} },
"_meta": {
"clientInfo": { "name": "claude-code", "version": "..." },
"capabilities": { "extensions": { "com.anthropic.apps": "1" } },
"traceparent": "00-..."
}
}
// any instance can serve it; no session, no stickiness
Multi Round-Trip Requests, concrètement
La partie élégante de la spec. Un serveur qui a besoin de demander "quel calendrier ?" en cours d'exécution n'a pas besoin de tenir un socket ouvert. Il répond :
{
"resultType": "input_required",
"inputRequests": {
"calendarId": { "type": "string", "prompt": "Which calendar?" }
},
"requestState": "base64(<opaque server-signed blob>)"
}
Le client montre le prompt, rassemble inputResponses, et refire la requête originale avec les deux champs. Le serveur traite requestState comme faisant autorité — souvent en le signant — donc il n'a pas besoin de se souvenir de la tentative antérieure du tout. C'est toute l'astuce derrière l'élicitation stateless : l'état voyage sur le fil, pas sur le serveur.
Les deux extensions officielles
- MCP Apps (SEP-1865) : un serveur peut livrer une UI HTML, rendue dans une iframe sandboxée par le client. Chaque action à l'intérieur de l'UI passe toujours par le même chemin d'audit JSON-RPC qu'un appel d'outil normal — pas d'écritures par la porte de derrière. Pensez rapport interactif + confirmation-avant-exécution, pas pages web arbitraires.
- Tasks (SEP-2663) : le pattern d'opération à long run, redessiné pour un monde sans session. tools/call retourne un handle de tâche ; le client conduit tasks/get et tasks/update pour poller ou streamer, et tasks/cancel pour avorter. tasks/list est intentionnellement parti — énumérer les tâches sans session est une fuite entre tenants.
- Changement cassant : l'API Tasks expérimentale de 2025-11-25 n'est pas compatible avec la nouvelle extension. Si vous avez livré contre elle, traitez la migration comme une réécriture, pas une mise à niveau.
Autorisation : le ménage OAuth
L'ancienne spec était OAuth-ish. La nouvelle est OAuth 2.1 / OIDC-forme :
- Les clients doivent valider le paramètre
isssur les réponses d'autorisation selon RFC 9207 — la correction des attaques de confusion qui ont touché les serveurs MCP plus tôt cette année. - Dynamic Client Registration exige maintenant que les clients déclarent un
application_typeOpenID Connect, pour qu'un fournisseur d'identité puisse appliquer des règles différentes pour les clients natifs vs web vs machine. - Les refresh tokens suivent le flux OIDC standard de refresh — signifiant que le SSO entreprise (Entra, Okta, PingID) fonctionne sans middleware personnalisé pour la première fois.
Lecture pratique : si vous construisiez de la colle OAuth personnalisée pour faire tenir MCP dans Okta, vous pouvez en supprimer la plupart.
Installez la beta aujourd'hui
Python — mcp v2.0.0b1 (un seul endpoint sert les deux révisions)
uv add "mcp[cli]==2.0.0b1" # or pip install "mcp[cli]==2.0.0b1"
TypeScript — paquets séparés, opt-in explicite pour stateless
npm install @modelcontextprotocol/server@beta npm install @modelcontextprotocol/client@beta
Go — v1.7.0-pre.1
go get github.com/modelcontextprotocol/go-sdk@v1.7.0-pre.1
C# — v2.0.0-preview.1
dotnet add package ModelContextProtocol --prerelease
Promesse de compatibilité de l'équipe SDK : "rien ne casse aujourd'hui, et rien ne casse le 28 juillet non plus." Les nouveaux clients auto-négocient vers l'ancienne poignée de main quand ils touchent un serveur 2025-11-25 ; le serveur Python v2 répond aux deux révisions depuis le même endpoint par défaut ; TypeScript et Go exigent un opt-in explicite pour exposer la variante stateless. TypeScript v1.x obtient des corrections de bugs et mises à jour de sécurité pendant au moins six mois.
Playbook de migration
- Ils marchent toujours jusqu'au 28 juillet 2027. Ne construisez pas de nouveaux serveurs contre eux. Pour les chemins : acceptez-les comme arguments d'outil. Pour les appels LLM : utilisez votre propre client. Pour les logs : écrivez sur stderr et laissez le harnais agréger.
- Si votre serveur se souvient aujourd'hui que 'l'utilisateur est à mi-chemin d'un checkout', retournez un basket_id de l'appel d'outil et exigez-le au prochain. État sur le fil, pas en mémoire.
- Même si vous gardez l'ancienne poignée de main pour l'instant, exposer server/discover est ce qui laisse les clients 2026-07-28 sauter initialize entièrement. C'est le seul changement qui débloque le serverless.
- Grep chaque base de code que vous possédez pour 32002. C'est le piège de l'échec silencieux de la migration.
- Envoyez clientInfo et capabilities dans _meta sur chaque requête. Propagez traceparent tant que vous y êtes — vous voudrez les traces la première fois que quelque chose casse en production.
- MCP Apps vaut la peine quand une UI bat un tour de chat (confirmations de grille de données, approbations pilotées par graphique). Tasks vaut la peine chaque fois qu'une opération pourrait dépasser le timeout d'inactivité HTTP du client. Aucun n'est gratuit — les deux ajoutent de la surface côté client.
- Il n'est pas mis à niveau. Réécrivez contre l'extension, gardez l'ancien endpoint vivant pendant le rollout, et supprimez-le à votre propre calendrier.
Pièges que les gens rencontrent réellement dans le RC
- Les load balancers collants 'marchent' encore — jusqu'à ce qu'ils ne marchent plus. Un serveur stateless derrière un LB collant a l'air bien en dev et déchiquette le taux de cache hit en prod. Désactivez la collant explicitement.
- requestState est opaque au client — mais ce n'est pas du stockage gratuit. Les serveurs qui empaquettent un demi-mégaoctet de contexte dedans feront exploser la mémoire client. Signez un petit handle, stockez le reste côté serveur clavé sur le handle.
- Les iframes MCP Apps sont sandboxées, pas sanitisées. Un serveur malveillant peut encore exfiltrer tout ce que l'utilisateur tape dans son UI. Traitez une MCP App comme du code tiers — allowlist les serveurs autorisés à rendre des UI du tout.
- server/discover n'a pas d'exigence d'auth dans la spec de base. Tout ce que vous exposez là est découvrable par n'importe quel client qui atteint votre URL. Ne mettez pas de métadonnées d'outil interne là.
- La mise à niveau JSON Schema 2020-12 signifie que les clients qui ont écrit un validateur à la main contre l'ancien sous-ensemble peuvent maintenant sous-valider silencieusement. Utilisez une vraie bibliothèque JSON Schema, pas du hand-roll.
Où cela atterrit sur la carte AILmanac
- MCP et connexion aux outils — le connecteur côté API. Toujours actuel ; le connecteur abstrait le transport, donc le changement de fil est invisible pour cette forme de requête. Seuls les serveurs auxquels le connecteur parle migrent.
- MCP dans Claude Code — comment Claude Code parle MCP aux serveurs locaux + distants. Le modèle stateless est la raison pour laquelle vous pouvez enfin pointer Claude Code sur un endpoint MCP serverless sans timeouts bizarres.
- La taxe token MCP — le chargement différé est le levier côté token ; le framework extensions est le levier côté protocole pour le même problème.
- Sécuriser les serveurs MCP — les orientations de sécurité MCP de la NSA de mai 2026 et le durcissement d'autorisation du RC se renforcent mutuellement. Lisez les deux.
Vérification rapide
Check yourself
0/4Vocabulaire que vous verrez sur GitHub cette semaine
Sources et lectures complémentaires
- La spec MCP 2026-07-28 Release Candidate — l'annonce primaire, avec les suppressions, ajouts et liste SEP.
- SDK beta pour le RC de la spec MCP 2026-07-28 — versions beta Python, TypeScript, Go, C# et la promesse de rétrocompatibilité.
- Apporter MCP 2026-07-28 à Claude — note de déploiement d'Anthropic pour Claude et Claude Code.
- MCP 2026-07-28 : de l'outil local au protocole distribué — le walk-through de migration tiers le plus aiguisé.
- MCP vient de devenir stateless — ce que la spec 2026 change au scaling — perspective Microsoft sur MCP stateless sur App Service.
- MCP devient stateless. Voici ce que ça veut dire — prise praticienne d'Arcade.dev, utile pour les implications ops.
- NSA CSI : considérations de conception de sécurité MCP (PDF) — orientations de durcissement de la NSA de mai 2026. Associez avec les changements d'autorisation de cette spec.