MCP 2026-07-28: la specifica stateless
Il 28 luglio 2026 il Model Context Protocol ha chiuso la sua più grande revisione dal lancio. Il titolo: MCP è stateless. L'handshake initialize e l'header Mcp-Session-Id non esistono più; ogni richiesta porta la propria identità dentro _meta; qualsiasi istanza del server dietro un load balancer può rispondere a qualsiasi chiamata. MCP serverless non è più un workaround — è la forma del protocollo.
- Cosa è cambiato davvero nella specifica 2026-07-28 — le quattro rimozioni e le quattro aggiunte che contano
- Multi Round-Trip Requests (MRTR): come un server stateless fa una domanda di follow-up all'utente senza sessione
- Il framework Extensions e le due estensioni ufficiali: MCP Apps e Tasks
- Hardening dell'autorizzazione: OAuth 2.1, validazione iss RFC 9207, e cosa richiede ora la Dynamic Client Registration
- Un percorso di migrazione concreto che non rompe i tuoi client 2025-11-25 — con le versioni beta degli SDK da installare oggi
La versione in un paragrafo
Prima: handshake initialize → cookie Mcp-Session-Id → coppia client/server sticky per tutta la durata della sessione. Dopo: nessun handshake, nessun session id, nessuna stickiness. Identità e capability del client viaggiano su ogni richiesta dentro un oggetto _meta. Un nuovo metodo server/discover sostituisce lo scambio iniziale di capability. Lo stato applicativo — un carrello, un task in corso — vive in handle che il tool restituisce e il client rimanda alla chiamata successiva, esattamente come un id di risorsa REST. Quel singolo cambiamento è ciò che sblocca deployment serverless ed edge, scaling orizzontale reale, e la possibilità che due implementazioni concorrenti stiano dietro lo stesso URL.
Cosa è stato rimosso
- Header Mcp-Session-Id — e l'intera nozione di sessione a livello di protocollo
- Handshake initialize / initialized — sostituito da _meta su ogni richiesta + server/discover on demand
- Roots, Sampling, e Logging — deprecati. Roots: passa i path come parametri del tool. Sampling: chiama tu stesso l'LLM. Logging: usa stderr o OpenTelemetry.
- tasks/list — rimosso anche dentro la nuova estensione Tasks, perché elencare i task senza sessione crea leak cross-tenant
Le deprecazioni di Roots/Sampling/Logging sono quelle che la maggior parte dei server esistenti tocca davvero. Tutte e tre assumevano un canale server↔client persistente e bidirezionale. In un mondo stateless il client possiede l'LLM, i path, e il sink dei log — il server risponde solo alla chiamata del tool.
Cosa è stato aggiunto
- Un RPC stateless che i client chiamano quando devono sapere cosa offre un server. Sostituisce le capability che il vecchio handshake restituiva. Metti in cache la risposta usando i nuovi campi ttlMs / cacheScope sulla risposta stessa — la specifica eredita la semantica HTTP Cache-Control.
- Mcp-Method e Mcp-Name (es. tools/call, search) permettono a un load balancer di fare routing senza parsare JSON-RPC. MCP-Protocol-Version sostituisce la sessione come negoziatore di versione.
- La risposta stateless all'elicitation. Se un tool serve input mid-execution, il server restituisce un InputRequiredResult che porta la domanda e un blob requestState opaco. Il client rilancia la chiamata con inputResponses più il requestState echoato — e qualsiasi istanza del server può prendersi il carico.
- Namespaced con reverse-DNS, versionati in modo indipendente, negoziati attraverso una capability map extensions. Le estensioni ufficiali escono per prime: MCP Apps (UI HTML sandboxate, SEP-1865) e Tasks (operazioni long-running con tasks/get, tasks/update, tasks/cancel; SEP-2663). Tutto il resto che prima richiedeva una modifica del core della specifica ora spedisce come estensione.
- inputSchema e outputSchema dei tool accettano ora oneOf / anyOf / allOf, condizionali, e $ref. Se stavi appiattendo il tuo schema per farlo entrare nel vecchio sottoinsieme di MCP, smetti.
- traceparent, tracestate, e baggage viaggiano in _meta. Il tracing distribuito lungo una catena client → connector → server finalmente funziona out of the box.
- Minimo 12 mesi tra Active → Deprecated → Removed. Qualsiasi cosa deprecata il 28 luglio 2026 continua a funzionare fino almeno al 28 luglio 2027, e la rimozione richiede la sua SEP dedicata.
L'unico cambio JSON che frega tutti
Il codice di errore per risorsa mancante è passato da -32002 a -32602 (Invalid Params). Se il tuo client ha un ramo if (err.code === -32002) da qualche parte, smette silenziosamente di scattare il 28 luglio. È il bug di integrazione più comune nell'RC.
Prima / Dopo
// PRIMA (2025-11-25): handshake stateful
POST /mcp { "method": "initialize", "params": { "capabilities": {...} } }
→ imposta Mcp-Session-Id: abc123
POST /mcp Mcp-Session-Id: abc123
{ "method": "tools/call", "params": { "name": "search", ... } }
// il server assume di "conoscerti" grazie al session cookie
// DOPO (2026-07-28): richiesta auto-descrittiva
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-..."
}
}
// qualsiasi istanza può servirla; nessuna sessione, nessuna stickiness
Multi Round-Trip Requests, in concreto
La parte elegante della specifica. Un server che deve chiedere "quale calendario?" mid-execution non deve tenere un socket aperto. Risponde:
{
"resultType": "input_required",
"inputRequests": {
"calendarId": { "type": "string", "prompt": "Which calendar?" }
},
"requestState": "base64(<opaque server-signed blob>)"
}
Il client mostra il prompt, raccoglie gli inputResponses, e rilancia la richiesta originale con entrambi i campi. Il server tratta requestState come autoritativo — spesso firmandolo — quindi non deve ricordare il tentativo precedente. Ecco tutto il trucco dietro l'elicitation stateless: lo stato viaggia sul filo, non sul server.
Le due estensioni ufficiali
- MCP Apps (SEP-1865): un server può spedire una UI HTML, renderizzata in un iframe sandboxato dal client. Ogni azione dentro la UI passa comunque per lo stesso audit path JSON-RPC di una normale chiamata tool — nessuna scrittura di back-door. Pensa a un report interattivo + conferma-prima-di-eseguire, non a pagine web arbitrarie.
- Tasks (SEP-2663): il pattern delle operazioni long-running, ridisegnato per un mondo senza sessione. tools/call restituisce un task handle; il client guida tasks/get e tasks/update per pollare o streammare, e tasks/cancel per abortire. tasks/list è intenzionalmente sparito — enumerare i task senza sessione è un leak cross-tenant.
- Breaking change: la vecchia API sperimentale Tasks del 2025-11-25 non è compatibile con la nuova estensione. Se hai spedito codice contro di essa, tratta la migrazione come una riscrittura, non come un upgrade.
Autorizzazione: la pulizia OAuth
La vecchia specifica era OAuth-ish. La nuova ha la forma OAuth 2.1 / OIDC:
- I client devono validare il parametro
isssulle risposte di autorizzazione secondo la RFC 9207 — la fix per gli attacchi mix-up che hanno colpito i server MCP a inizio anno. - La Dynamic Client Registration ora richiede ai client di dichiarare un
application_typeOpenID Connect, così un identity provider può applicare regole diverse per client native vs web vs machine. - I refresh token seguono lo standard flow OIDC — il che significa che l'SSO enterprise (Entra, Okta, PingID) funziona senza middleware custom per la prima volta.
Lettura pratica: se stavi costruendo colla OAuth custom per far entrare MCP dentro Okta, puoi cancellarne la maggior parte.
Installa la beta oggi
Python — mcp v2.0.0b1 (un solo endpoint serve entrambe le revisioni)
uv add "mcp[cli]==2.0.0b1" # oppure pip install "mcp[cli]==2.0.0b1"
TypeScript — package separati, opt-in esplicito per lo 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
Promessa di compatibilità dal team SDK: "niente si rompe oggi, e niente si rompe il 28 luglio." I nuovi client auto-negoziano al ribasso verso il vecchio handshake quando trovano un server 2025-11-25; il server Python v2 risponde a entrambe le revisioni dallo stesso endpoint di default; TypeScript e Go richiedono un opt-in esplicito per esporre la variante stateless. TypeScript v1.x riceve bug fix e security update per almeno sei mesi.
Playbook di migrazione
- Continuano a funzionare fino al 28 luglio 2027. Non costruire nuovi server contro di essi. Per i path: accettali come argomenti del tool. Per le chiamate LLM: usa il tuo client. Per i log: scrivi su stderr e lascia che l'harness li aggreghi.
- Se oggi il tuo server ricorda 'l'utente è a metà di un checkout,' restituisci un basket_id dalla chiamata al tool e richiedilo alla successiva. Stato sul filo, non in memoria.
- Anche se tieni il vecchio handshake per ora, esporre server/discover è ciò che permette ai client 2026-07-28 di saltare initialize del tutto. È il singolo cambio che sblocca serverless.
- Fai grep di 32002 in ogni codebase che possiedi. È la trappola silenziosa della migrazione.
- Manda clientInfo e capabilities in _meta su ogni richiesta. Propaga traceparent già che ci sei — vorrai avere i trace la prima volta che qualcosa si rompe in produzione.
- MCP Apps vale la pena quando una UI batte un turno di chat (conferme su data-grid, approvazioni chart-driven). Tasks vale la pena ogni volta che un'operazione può superare l'HTTP idle timeout del client. Nessuna delle due è gratis — entrambe aggiungono superficie client.
- Non viene aggiornato. Riscrivi contro l'estensione, tieni vivo il vecchio endpoint durante il rollout, e rimuovilo secondo il tuo calendario.
Gotcha che stanno colpendo davvero le persone nell'RC
- I load balancer sticky ‘funzionano’ ancora — finché non funzionano più. Un server stateless dietro un LB sticky sembra ok in dev e distrugge la cache hit rate in prod. Disattiva la stickiness esplicitamente.
- requestState è opaco per il client — ma non è storage gratis. I server che ci impacchettano dentro mezzo megabyte di contesto faranno esplodere la memoria del client. Firma un handle piccolo, tieni il resto server-side chiavato sull'handle.
- Gli iframe di MCP Apps sono sandboxati, non sanitizzati. Un server malicious può ancora esfiltrare qualsiasi cosa l'utente scriva nella sua UI. Tratta un MCP App come codice di terze parti — allowlista quali server sono autorizzati a renderizzare UI.
- server/discover non ha requisito di auth nella specifica base. Qualsiasi cosa esponi lì è scopribile da ogni client che raggiunge il tuo URL. Non mettere metadati di tool interni là dentro.
- L'upgrade a JSON Schema 2020-12 significa che i client che hanno scritto a mano un validator contro il vecchio sottoinsieme possono ora silently under-validate. Usa una libreria JSON Schema vera, non fatta a mano.
Dove atterra questo sulla mappa AILmanac
- MCP e connessione ai tool — il connector lato API. Ancora attuale; il connector astrae il transport, quindi il cambio di wire è invisibile a quella forma di richiesta. Solo i server con cui il connector parla migrano.
- MCP in Claude Code — come Claude Code parla MCP con server locali + remoti. Il modello stateless è la ragione per cui puoi finalmente puntare Claude Code a un endpoint MCP serverless senza timeout strani.
- Il MCP Token Tax — il deferred loading è la leva token-side; il framework extensions è la leva protocollo-side per lo stesso problema.
- Securing MCP Servers — la guida NSA di maggio 2026 sulla sicurezza MCP e l'hardening di autorizzazione dell'RC si rinforzano a vicenda. Leggi entrambi.
Controllo veloce
Check yourself
0/4Vocabolario che vedrai su GitHub questa settimana
Fonti e approfondimenti
- The 2026-07-28 MCP Specification Release Candidate — l'annuncio primario, con rimozioni, aggiunte, e lista SEP.
- Beta SDKs for the 2026-07-28 MCP Spec RC — versioni beta Python, TypeScript, Go, C# e la promessa di backward-compat.
- Bringing MCP 2026-07-28 to Claude — nota di rollout Anthropic per Claude e Claude Code.
- MCP 2026-07-28: From Local Tool to Distributed Protocol — il walk-through di migrazione third-party più affilato.
- MCP Just Went Stateless — What the 2026 Spec Changes About Scaling — la prospettiva Microsoft sullo stateless MCP su App Service.
- MCP Is Going Stateless. Here's What That Means — presa Arcade.dev da practitioner, utile per le implicazioni ops.
- NSA CSI: MCP Security Design Considerations (PDF) — guida NSA di maggio 2026 sull'hardening. Da leggere in coppia con i cambi di autorizzazione di questa specifica.