Guía
MCP 2026-07-28: la revisión sin estado, y lo que exige a su servidor
Fundador de Epovest
El 28 de julio de 2026, el Model Context Protocol recibió su mayor revisión desde que se le añadió la autorización. Una sola frase la resume casi entera: el protocolo ya no tiene apretón de manos. La versión, la identidad del cliente y sus capacidades viajan ahora en cada petición, y el servidor acepta o rechaza cada petición por separado.
Todo lo demás se deriva de esa frase. Aquí está lo que la revisión retira, lo que lo reemplaza y el puñado de exigencias fáciles de pasar por alto porque nada falla de forma ruidosa cuando se olvidan. Migramos nuestro propio servidor MCP a 2026-07-28 el 2 de agosto de 2026: la lista de verificación final es la que seguimos.
Lo que la revisión retira
- Las sesiones de protocolo y la cabecera
Mcp-Session-Id. Los resultados de lista ya no varían de una conexión a otra. Un servidor que necesite estado entre llamadas acuña una clave explícita y la hace circular como un argumento de herramienta corriente. - El apretón de manos
initializey el acusenotifications/initializedque lo cerraba. ping,logging/setLevelynotifications/roots/list_changed. El nivel de registro se fija ahora por petición, dentro de_meta.- El flujo GET independiente. Las notificaciones de cambio pasan por una única petición
subscriptions/listende larga duración, y el cliente se suscribe a los tipos que quiere recibir. - La reanudación de un flujo cortado.
Last-Event-IDy los identificadores de evento SSE desaparecen. Un flujo roto pierde la petición en curso, y el cliente la reemite con un identificador nuevo.
La razón declarada tiene que ver con la forma de despliegue. Un servidor que no guarda estado de sesión se coloca detrás de un balanceador de carga corriente y escala como cualquier servicio HTTP, sin almacenamiento compartido ni enrutado pegajoso. Ese era el objetivo anunciado en la hoja de ruta 2026, y esta revisión es donde aterriza.
Lo que reemplaza al apretón de manos
server/discover. Los servidores DEBEN implementarla. Responde en una sola llamada con las versiones del protocolo que el servidor sirve, sus capacidades y su identidad. Un cliente PUEDE llamarla primero para elegir versión, o prescindir de ella y tratar un error de versión sobre la marcha.
Los metadatos por petición. Cada petición lleva su propio contexto:
"_meta": {
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
"io.modelcontextprotocol/clientInfo": { "name": "example-client", "version": "1.0.0" },
"io.modelcontextprotocol/clientCapabilities": {}
}
En HTTP, la misma versión se repite en la cabecera MCP-Protocol-Version, y ambas deben coincidir.
Los intercambios en varias vueltas. Un servidor que necesita un muestreo, una consulta al usuario o la lista de raíces ya no envía su propia petición por un flujo. Devuelve un resultado con resultType: "input_required" y un campo inputRequests, y el cliente repite la petición original con los inputResponses correspondientes. La petición emitida por el servidor, como forma, sale del protocolo.
Las tareas pasan a ser una extensión. Las tareas experimentales salen del núcleo y se convierten en la extensión oficial io.modelcontextprotocol/tasks, con un tasks/get que se consulta en lugar de un tasks/result bloqueante.
Cinco exigencias fáciles de pasar por alto
Son las que superan una revisión de código y fallan ante un cliente estricto.
resultTypeen todo resultado. Un resultado corriente lleva"complete". Un cliente debe leer la ausencia del campo, en un servidor que sigue en una revisión anterior, como un"complete".- Las pistas de caché son exigidas, no opcionales.
ttlMsycacheScopepertenecen a los resultados deserver/discover,tools/list,prompts/list,resources/list,resources/templates/listyresources/read.ttlMses una duración de frescura en milisegundos;cacheScopevale"public"o"private"y decide si un intermediario compartido puede almacenar la respuesta. - Dos cabeceras de petición, que el servidor debe vigilar.
Mcp-Methoden cada petición,Mcp-Nameentools/call,resources/readyprompts/get. Reflejan valores del cuerpo para que una pasarela pueda enrutar y autorizar sin leerlo, y por eso mismo un servidor DEBE rechazar con400cualquier desacuerdo entre cabecera y cuerpo. Un valor que no cabe en una cabecera ASCII imprimible viaja codificado en base64 entre=?base64?y?=, y el servidor lo decodifica antes de comparar. - Códigos de error nuevos, en un rango reservado a la especificación.
-32020para una cabecera que contradice el cuerpo,-32021para una capacidad de cliente requerida y ausente,-32022para una versión de protocolo no servida. El último importa más de lo que parece: LLEVA la lista de versiones que el servidor sirve, y es esa lista la que permite al cliente reintentar en vez de concluir que el servidor está roto. El recurso no encontrado pasa además de-32002al-32602estándar. - Un método desconocido responde
404, con el error JSON-RPC en el cuerpo. Es esa pareja la que dice a un cliente que sondea que habla con un servidor al día, y no con un punto de entrada que simplemente no aloja esa ruta.
La autorización
El registro dinámico de clientes queda obsoleto en favor de los Client ID Metadata Documents. El identificador de cliente pasa a ser una URL https con una ruta, que apunta a un documento JSON que el cliente aloja y mantiene al día. El servidor de autorización lee ese documento, comprueba que el client_id que contiene es la URL de la que viene, y valida la dirección de retorno contra la lista que declara. Nada que registrar antes del primer flujo, nada que purgar después, y el mismo identificador sirve en todos los servidores de autorización. Un servidor anuncia la capacidad con client_id_metadata_document_supported en sus metadatos.
Una consecuencia merece decirse con claridad, porque la especificación la deja en consideración y no en regla: este mecanismo hace que el servidor de autorización lea una URL elegida por quien llama, y en un punto de entrada de tokens público, quien llama puede ser cualquiera. Resuelva la dirección usted mismo, rechace todo lo que no esté en la internet pública y fije la dirección resuelta en la petición saliente en lugar de limitarse a comprobarla. Comprobar sin fijar deja que el nombre se resuelva una segunda vez del lado del cliente HTTP, que es todo el mecanismo de un ataque de reasociación de DNS. Rechace las redirecciones, limite el tamaño del cuerpo, mantenga los tiempos de espera cortos y guarde el resultado en caché durante un plazo fijo en lugar del que pida el documento.
Dos añadidos más discretos en el mismo terreno: la respuesta de autorización DEBERÍA llevar el parámetro iss de la RFC 9207, que el cliente DEBE validar cuando está presente y que cierra el ataque de mezcla contra un cliente conectado a varios servidores de autorización; y el cliente DEBE enviar application_type en el registro dinámico, ya que un servidor OIDC lee un valor ausente como "web" y rechaza después las direcciones de retorno de una aplicación nativa.
Qué queda obsoleto, y por cuánto tiempo
La revisión introduce además un ciclo de vida de las funcionalidades: activa, obsoleta, retirada, con al menos doce meses entre una obsolescencia y la primera retirada posible, más un registro público de todo lo obsoleto. Las raíces, el muestreo, el registro de eventos, el transporte HTTP+SSE y el registro dinámico de clientes están hoy en ese estado. Siguen funcionando. Una implementación nueva no los adopta.
Servir las dos eras desde un solo punto de entrada
La mayoría de los servidores hablarán la revisión nueva y las antiguas a la vez durante un tiempo, y nada impide servirlas en el mismo sitio. La regla: es la versión DECLARADA la que elige la era, y nada más. Ninguna declaración equivale a la era del apretón de manos; una petición que declara 2026-07-28 obtiene la era sin estado.
Dos detalles deciden si aguanta.
initialize no debe negociar NUNCA 2026-07-28. Un cliente que envía initialize no habla una revisión que ya no tiene apretón de manos, sea cual sea la versión que pida en él. Concedérsela lo dejaría esperando campos que no llegarían nunca. Mantenga dos listas: las versiones que sirve, las que anuncia server/discover, y las versiones que initialize puede negociar, es decir la primera lista menos la versión sin estado.
Responda el error de versión ANTES del control de la clave. Quien llama acumulando una versión no servida y ninguna autenticación debe leer el error de versión. Un 401 no le enseña nada accionable, y la lista de versiones servidas es pública de todos modos, ya que server/discover la entrega sin autenticación.
La lista de verificación
Para pasarla por su propio servidor.
- ¿Responde
server/discover, y sin clave si sus otros métodos públicos responden sin ella? - ¿Lleva cada resultado su
resultType? - ¿Llevan
server/discoverytools/listsusttlMsycacheScope? - ¿Valida
MCP-Protocol-Versioncontra el cuerpo, yMcp-MethodyMcp-Namecontra sus valores del cuerpo, con-32020en caso de desacuerdo? - ¿Devuelve una versión no servida un
400y un-32022, llevando las versiones que usted sirve? - ¿Devuelve un método desconocido un
404con-32601? - ¿Sigue respondiendo
initializea los clientes más antiguos, y no devuelve nunca2026-07-28? - Si usted mantiene el servidor de autorización: ¿anuncia
client_id_metadata_document_supported, y fija la dirección resuelta antes de ir a leer un documento de cliente?
El servidor MCP de Epovest responde en 2026-07-28 igual que en 2025-06-18, 2025-03-26 y 2024-11-05 desde el mismo punto de entrada, y la referencia completa está en epovest.com/docs/api.md. Para conectarle un asistente, nuestra guía para convertir a Claude en su analista GEO personal detalla las dos vías de entrada.