Phase 13 - Lesson 09

MCP Transports — stdio vs Streamable HTTP vs SSE Migration

This lesson includes a graded coding exercise that runs in your browser, unlocked with lifetime access.

stdio funciona localmente y en ningún otro lugar. Streamable HTTP (2025-03-26) es el estándar remoto. El antiguo transporte HTTP+SSE está descontinuado y se eliminará a mediados de 2026. Elegir el transporte incorrecto cuesta una migración; elegir el correcto garantiza un servidor MCP hospedable de forma remota con continuidad de sesión y protección contra DNS-rebinding.

Type: Learn Languages: Python (stdlib, esqueleto de endpoint Streamable HTTP) Prerequisites: Phase 13 · 07, 08 (servidor y cliente MCP) Time: ~45 minutos

Learning Objectives

  • Elegir entre stdio y Streamable HTTP según el modelo de despliegue (local vs remoto, proceso único vs flota).
  • Implementar el patrón de endpoint único de Streamable HTTP: POST para peticiones, GET para el flujo de la sesión.
  • Aplicar la validación de Origin y la semántica de session-id para evitar ataques de DNS-rebinding.
  • Migrar un servidor HTTP+SSE heredado a Streamable HTTP antes de las fechas límite de eliminación a mediados de 2026.

The Problem

El primer transporte remoto de MCP (noviembre de 2024) fue HTTP+SSE: dos endpoints, uno para los POST del cliente y un canal de Server-Sent-Events para el flujo del servidor al cliente. Funcionaba. Pero también era tosco: dos endpoints por sesión, cachés rotas frente a algunas CDN y una dependencia estricta de conexiones SSE de larga duración que algunos WAF finalizan de forma agresiva.

La especificación del 2025-03-26 lo reemplazó con Streamable HTTP: un único endpoint, POST para peticiones del cliente, GET para establecer un flujo de sesión, ambos compartiendo una cabecera Mcp-Session-Id. Todos los servidores creados o migrados desde entonces usan Streamable HTTP. El antiguo modo SSE se está descontinuando: Atlassian Rovo lo eliminó el 30 de junio de 2026; Keboola el 1 de abril de 2026; y la mayoría de los servidores empresariales restantes lo harán para finales de 2026.

Y stdio sigue siendo importante para los servidores locales. Claude Desktop, VS Code y todos los clientes con formato de IDE inician servidores a través de stdio. El modelo mental correcto: stdio para "esta máquina", Streamable HTTP para "a través de la red". Sin mezclar ambos.

The Concept

stdio

  • Transporte de proceso hijo. El cliente inicia el servidor y se comunica a través de stdin/stdout.
  • Un objeto JSON por línea. Delimitado por saltos de línea.
  • Sin session id; la identidad del proceso es la sesión.
  • No requiere autenticación (el proceso hijo hereda el límite de confianza del padre).
  • Nunca se debe usar para servidores remotos: se necesitaría SSH o socat para crear el túnel, momento en el cual es mejor usar Streamable HTTP.

Streamable HTTP

Endpoint único /mcp (or cualquier ruta). Admite tres métodos HTTP:

  • POST /mcp. El cliente envía un mensaje JSON-RPC. El servidor responde con una única respuesta JSON o con un flujo SSE de una o más respuestas (útil para respuestas por lotes y notificaciones relacionadas con esa petición).
  • GET /mcp. El cliente abre un canal SSE de larga duración. El servidor lo utiliza para peticiones del servidor al cliente (sampling, notificaciones, solicitud de información).
  • DELETE /mcp. El cliente finaliza explícitamente la sesión.

Las sesiones se identifican mediante la cabecera Mcp-Session-Id que el servidor establece en la primera respuesta y que el cliente repite en cada petición subsiguiente. Los id de sesión DEBEN ser criptográficamente aleatorios (más de 128 bits); los id elegidos por el cliente se rechazan por seguridad.

Single endpoint vs two

El modo de dos endpoints de la antigua especificación aún se puede llamar en 2026; la especificación lo declara "compatible con el legado". Sin embargo, todos los servidores nuevos deberían ser de endpoint único. Los SDK oficiales generan endpoint único; use el modo heredado solo al comunicarse con un servidor remoto no migrado.

Origin validation and DNS-rebinding

Los navegadores no son clientes MCP (hoy en día), pero un atacante puede diseñar una página web que convenza a un navegador de hacer un POST a localhost:1234/mcp, donde escucha el servidor MCP local del usuario. Si el servidor no comprueba la cabecera Origin, la política de mismo origen (same-origin policy) del navegador no lo protegerá, ya que Origin: http://evil.com es un origen cruzado válido.

La especificación del 2025-11-25 requiere que los servidores rechacen las peticiones cuyo Origin no esté en una lista de permitidos (allowlist). La lista de permitidos suele contener el host del cliente MCP (https://claude.ai, vscode-webview://*) y variantes de localhost para interfaces de usuario locales.

Session id lifecycle

  1. El cliente envía la primera petición sin Mcp-Session-Id.
  2. El servidor asigna un id aleatorio y establece la cabecera Mcp-Session-Id en la respuesta.
  3. El cliente repite esa cabecera en todas las peticiones subsiguientes y en el GET /mcp para el flujo.
  4. El servidor puede revocar la sesión; el cliente verá un error 404 en las peticiones subsiguientes y deberá volver a inicializar.
  5. El cliente puede enviar un DELETE explícito de la sesión para un cierre limpio.

Keepalive and reconnect

Las conexiones SSE se caen. El cliente las restablece volviendo a hacer un GET con el mismo Mcp-Session-Id. El servidor DEBE encolar los eventos perdidos durante la interrupción (hasta un límite razonable) y reproducirlos a través de la cabecera last-event-id que el cliente envía de vuelta.

La Fase 13 · 13 cubre Tareas (Tasks), que permiten que el trabajo de larga duración sobreviva incluso a una reconexión completa de la sesión.

Backwards compatibility probe

Un cliente que quiera dar soporte tanto a servidores antiguos como nuevos:

  1. Realiza un POST a /mcp.
  2. Si la respuesta es 200 OK con JSON o SSE, se trata de Streamable HTTP.
  3. Si la respuesta es 200 OK con Content-Type: text/event-stream Y una cabecera Location que apunta a un endpoint secundario, se trata de HTTP+SSE heredado; siga la ruta de Location.

Cloudflare, ngrok, and hosting

Los servidores MCP remotos en producción en 2026 se ejecutan en Cloudflare Workers (con su SDK de MCP Agents), Vercel Functions o Node/Python contenedorizado. Clave: su alojamiento debe admitir conexiones HTTP de larga duración para el GET de SSE. El plan gratuito de Vercel tiene un límite de 10 segundos y no es adecuado. Cloudflare Workers admite flujos indefinidos.

Gateway composition

Cuando coloca un gateway frente a múltiples servidores MCP (Fase 13 · 17), el gateway actúa como un único endpoint Streamable HTTP que reescribe los session id y realiza la multiplexación upstream. Las herramientas se fusionan en la capa del gateway; el cliente ve un único servidor lógico.

Transport failure modes

  • stdio SIGPIPE. La muerte del proceso hijo a mitad de la escritura genera SIGPIPE; los servidores deben salir limpiamente. Los clientes deben detectar EOF y marcar la sesión como muerta.
  • HTTP 502 / 504. Cloudflare, nginx y otros proxies emiten estos errores cuando falla el upstream. Los clientes de Streamable HTTP deben reintentar una vez después de un breve tiempo de espera (backoff).
  • SSE connection drop. TCP RST, tiempo de espera del proxy o cambio de red del cliente cierran el flujo. El cliente se reconecta con Mcp-Session-Id y la cabecera opcional last-event-id para reanudar.
  • Session revocation. El servidor invalida un id de sesión; el cliente ve un error 404 en la siguiente petición. El cliente debe realizar un nuevo handshake.
  • Clock skew. Los cálculos de TTL de recursos en el cliente difieren de los del servidor. El cliente debe considerar autoritativas las marcas de tiempo (timestamps) del servidor.

When to bypass Streamable HTTP

Algunas empresas despliegan servidores MCP detrás de transportes gRPC o colas de mensajes (message-queues) dentro de sus propias redes. Esto no es estándar: la especificación de MCP no define formalmente estos esquemas. Los gateways pueden exponer una interfaz Streamable HTTP a los clientes MCP mientras usan gRPC internamente. Mantenga la interfaz externa compatible con la especificación; el gateway se encarga de la traducción.

Use It

El archivo code/main.py implementa un endpoint Streamable HTTP mínimo utilizando http.server (stdlib). Gestiona POST, GET y DELETE en /mcp, establece Mcp-Session-Id en la primera respuesta, valida Origin y rechaza peticiones de orígenes que no estén en la lista de permitidos. El manejador reutiliza la lógica de despacho del servidor de notas de la Lección 07.

Qué observar:

  • El manejador POST lee el cuerpo JSON-RPC, despacha y escribe una respuesta JSON (la variante de respuesta única; la variante SSE es estructuralmente similar).
  • La comprobación de Origin rechaza la prueba predeterminada http://evil.example pero acepta http://localhost.
  • Los id de sesión son cadenas hexadecimales aleatorias de 128 bits; el servidor mantiene el estado de cada sesión en memoria.

Ship It

Esta lección produce outputs/skill-mcp-transport-migrator.md. Dado un servidor MCP HTTP+SSE (heredado), la skill genera un plan de migración a Streamable HTTP con continuidad de session-id, comprobaciones de Origin y soporte para pruebas de compatibilidad retroativa.

Exercises

  1. Ejecute code/main.py. Realice un POST de initialize desde curl y observe la cabecera de respuesta Mcp-Session-Id. Realice una segunda petición POST repitiendo la cabecera y verifique la continuidad de la sesión.

  2. Añada un manejador GET que abra un flujo SSE. Envíe un evento notifications/progress cada cinco segundos. Reconéctese volviendo a hacer un GET con el mismo session id y confirme que el servidor lo acepta.

  3. Implemente la lógica de reproducción de last-event-id. Al reconectarse, reproduzca cualquier evento generado desde ese id.

  4. Extienda la validación de Origin para admitir un patrón comodín (https://*.example.com) y confirme que acepta https://app.example.com pero rechaza https://evil.example.com.attacker.net.

  5. Tome un servidor HTTP+SSE heredado del registro oficial (hay varios) y esboce la migración: qué cambia en el manejo de endpoints, la generación de session id y la semántica de las cabeceras.

Key Terms

Term What people say What it actually means
stdio transport "Proceso hijo local" JSON-RPC sobre stdin/stdout, delimitado por saltos de línea
Streamable HTTP "El transporte remoto" Endpoint único con POST + GET + SSE opcional, especificación del 2025-03-26
HTTP+SSE "Heredado" Modelo de dos endpoints que se eliminará a mediados de 2026
Mcp-Session-Id "Cabecera de sesión" ID aleatorio asignado por el servidor que se repite en cada petición subsiguiente
Origin allowlist "Defensa contra DNS-rebinding" Rechazar peticiones cuyo Origin no esté aprobado
Single endpoint "Una sola URL" /mcp maneja POST / GET / DELETE para todas las operaciones de sesión
last-event-id "Reproducción SSE" Cabecera utilizada para reanudar un flujo interrumpido sin perder eventos
Backwards-compat probe "Detección de viejo vs nuevo" Verificación del formato de respuesta del cliente que selecciona automáticamente el transporte
Long-lived HTTP "Flujo SSE" El servidor envía eventos durante minutos u horas en una sola conexión TCP
Session revocation "Forzar reinicialización" El servidor invalida un id de sesión; el cliente debe realizar el handshake de nuevo

Further Reading

0 lifetime access. Curriculum based on AI Engineering from Scratch by Rohit Ghumare (MIT, used under attribution).