AI & MCP

SSE e Streamable HTTP: come parla un server MCP

Streamable HTTP ha sostituito il trasporto HTTP+SSE: un solo endpoint riceve JSON-RPC in POST e può rispondere con un flusso. Stdio resta per il server locale.

In sintesi

  • Il trasporto HTTP+SSE usava due endpoint; Streamable HTTP ne usa uno e risponde JSON o SSE.
  • Stdio resta la scelta per un server locale avviato dal client sulla stessa macchina.
  • L'endpoint EneUI risponde sempre application/json e non emette Mcp-Session-Id.

Streamable HTTP ha sostituito il trasporto HTTP+SSE: un solo endpoint riceve messaggi JSON-RPC in POST e può rispondere con un flusso SSE. Stdio resta la scelta per un server locale avviato dal client.

Tre trasporti, due generazioni

La prima revisione, 2024-11-05, usava due endpoint: un GET per il flusso e un POST per i messaggi. Streamable HTTP, dalla revisione 2025-03-26, li unisce in un solo percorso.

TrasportoEndpointQuandoStato
stdiostdin e stdoutprocesso localestandard
HTTP+SSEGET /sse e POST /messagesclient del 2024deprecato
Streamable HTTPPOST /mcpserver remotostandard

Cosa risponde l'endpoint EneUI

curl -s -i https://ui.eneawork.it/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"ping"}'

L'intestazione torna application/json, non text/event-stream, e manca Mcp-Session-Id. La risposta è una sola: {"jsonrpc":"2.0","id":1,"result":{}}.

Una richiesta, una risposta

Il server non tiene stato: ogni POST è indipendente e una notifica senza id chiude con 202 e corpo vuoto. Per un catalogo in sola lettura è sufficiente, e attraversa qualunque proxy senza sorprese.

Il prezzo di questa scelta

Senza flusso aperto il server non può iniziare un messaggio: niente sampling, niente notifica su una resource aggiornata, niente ripresa dopo una disconnessione. Sono tutte funzioni opzionali, ma chi le vuole deve accettare SSE.

Lo stesso percorso per browser e agenti

Un Accept: text/html fa cadere la GET nella pagina /mcp; un Accept: */* riceve il documento JSON con nome, versione, trasporto e i 9 strumenti. La negoziazione avviene nell'intestazione, non su un percorso diverso.

Il catalogo EneUI

Le risposte arrivano dalla stessa origine delle pagine: hero, icone e un blocco reale come SaaS Pricing with Billing Toggle, 1 file e 4 dipendenze di registry, verificato il 1 novembre 2026.

La limitazione

L'endpoint non implementa Mcp-Session-Id né il GET di streaming, quindi non può riprendere una risposta interrotta con Last-Event-ID. Un client che pretende un flusso deve accettare il JSON come risposta completa.

Dove continuare

Il flusso OAuth che accompagna il trasporto è in OAuth per server MCP; il dispatcher è in come costruire un server MCP; il confronto con le API REST è in MCP vs REST. La definizione del protocollo è in che cos'è MCP.

Domande frequenti

Streamable HTTP è obbligatorio in MCP?

No. Un server può usare stdio e basta. Streamable HTTP è il trasporto previsto per un endpoint remoto raggiungibile da più client.

Posso usare ancora HTTP+SSE?

Tecnicamente sì, ma il trasporto è deprecato dalla revisione 2025-03-26. Un client nuovo conviene che parli Streamable HTTP o stdio.

Perché EneUI risponde JSON invece di SSE?

Perché ogni richiesta produce una sola risposta e il JSON attraversa ogni proxy. Un flusso servirebbe solo per messaggi avviati dal server, che qui non esistono.

Cos'è Mcp-Session-Id?

È l'intestazione con cui il server assegna un identificatore di sessione al client. L'endpoint EneUI non la emette: ogni POST è indipendente.

Il browser può aprire /mcp?

Sì, ma riceve la pagina HTML: con Accept text/html la GET cade nell'applicazione, mentre un client che chiede JSON ottiene il documento di scoperta.