ChatGPT MCP Events: crea paso a paso tu primera automatización de plugin activada por eventos
Con MCP Events, ChatGPT se suscribe a los cambios de tus sistemas y actúa sobre ellos. Esta guía plantea la construcción como un bucle Advertise-Subscribe-Verify-Deliver (ASVD). Anuncias la capacidad y events/list, haces que las suscripciones sean idempotentes, verificas los callbacks, firmas las entregas como Standard Webhooks y pruebas todo antes del lanzamiento. También indica en qué puntos el borrador de la especificación y los SDK siguen cambiando.
Con MCP Events, ChatGPT se suscribe a las actualizaciones de tu servidor MCP. Los usuarios eligen qué quieren monitorizar y qué debe hacer ChatGPT cuando llega una actualización. Si tu equipo ya tiene un servidor MCP o una API SaaS en marcha, verás que un conector ahora puede iniciar una automatización por sí solo, sin esperar a que alguien escriba un prompt.
Recorreremos la construcción en el mismo orden en que escribirás el código. Lo llamamos el bucle Advertise-Subscribe-Verify-Deliver (ASVD): anunciar los eventos que emites, hacer que las suscripciones sean idempotentes, verificar cada callback antes de activarlo y, por último, entregar eventos firmados con reintentos que sepan cuándo detenerse. También señalaremos en qué puntos la especificación sigue siendo un borrador, porque algunos de esos detalles pendientes acaban en tu código.
Qué son MCP Events y qué admite realmente ChatGPT
La documentación para desarrolladores de OpenAI lo describe de forma breve: ChatGPT se suscribe a actualizaciones de tu servidor MCP, como mensajes nuevos, cambios de contenido o cambios de estado, y el usuario decide qué ocurre a continuación. El borrador de diseño apunta más alto. Busca que un cliente MCP pueda suscribirse a eventos de un sistema de origen, como un mensaje de Slack, un push de GitHub o un incidente de PagerDuty, para que el agente reaccione aunque el usuario no esté presente.
El dato de diseño más importante es lo que ChatGPT deja fuera. ChatGPT admite la entrega por webhook y la verificación de callbacks del borrador de la especificación MCP Events. El polling, el streaming y las notificaciones de control gap y terminated del borrador no están soportados en esta integración.
| Función del borrador | Soportada por ChatGPT | Qué construir para ChatGPT |
|---|---|---|
| Entrega por webhook | Sí | Constrúyela, fírmala y reinténtala |
| Verificación de callback | Sí | Constrúyela antes de activar cualquier suscripción |
| Polling | No | Omítelo en esta integración |
| Streaming (modo push) | No | Omítelo en esta integración |
| Notificaciones de control gap y terminated | No | Omítelas en esta integración |
Svix, una empresa de infraestructura de webhooks, considera a ChatGPT el primer cliente importante en admitir MCP Events. También señala que tu servidor entrega los eventos a ChatGPT como Standard Webhooks. Una guía de construcción de terceros en DEV Community afirma que el soporte en ChatGPT comenzó en el OpenAI DevDay del 29 de septiembre de 2026, con la versión de protocolo 2026-07-28. Confirma ambos datos en la documentación de OpenAI antes de fijar nada en el código basándote en ellos.
Así que construye para webhooks y nada más. Las rutas de código de polling y de push-stream requerirían mantenimiento mientras existan y no aportan nada a esta integración.
Antes de empezar: la realidad de los SDK y el estado de la especificación
Después del DevDay, un desarrollador informó en la OpenAI Developer Community de que el SDK oficial de Python (mcp 2.2.0) aún no admitía MCP Events, y de que el SDK de TypeScript tampoco. Puede que eso haya cambiado, así que lee las notas de versión actuales. Aun así, nosotros reservaríamos tiempo para escribir a mano parte de la infraestructura.
Go está en mejor situación. Una incidencia abierta en el SDK de Go indica que su soporte para métodos personalizados ya permite implementar events/list, events/subscribe y events/unsubscribe. Lo que falta es una forma de anunciar la capacidad events de nivel superior.
La propia especificación sigue en movimiento. El estatuto del grupo de trabajo explica que hoy los clientes se enteran de las actualizaciones del servidor mediante polling o manteniendo abierta una conexión SSE, y que el grupo planea especificar un mecanismo de callback estandarizado para que los servidores puedan enviar notificaciones de forma activa. El 2026-10-16 el grupo pasó a llamarse Tasks and Events WG y asumió el ámbito de Tasks que antes tenía el Agents WG. Cuenta con más revisiones.
Nuestro consejo es escribir ahora controladores personalizados ligeros y mantenerlos aislados. Dale un módulo propio a los controladores de métodos JSON-RPC, y haz lo mismo con el almacenamiento de suscripciones y con la firma y la entrega. Cuando llegue el soporte en los SDK, sustituyes la capa de protocolo y tu lógica de negocio no se toca.
Paso 1 de ASVD (Advertise): declara la capacidad y define events/list
Declara la capacidad events
Tu servidor tiene que anunciar la capacidad events de nivel superior durante la inicialización. Te sugerimos tratar esta declaración como un requisito bloqueante para el lanzamiento, no como un detalle para completar más adelante. En el SDK de Go es justo la carencia que describe la incidencia abierta, así que comprueba su estado antes de elegir una solución alternativa.
Diseña cada tipo de evento para dos lectores
Te sugerimos diseñar cada entrada de events/list en torno a estas partes:
- Un nombre claro que se mantenga estable con el tiempo.
- Una descripción que sirva tanto al usuario como al modelo. El usuario la lee al elegir qué monitorizar; el modelo la lee al decidir qué hacer.
- Un inputSchema que defina los filtros que puede establecer un suscriptor.
- Un payloadSchema que describa exactamente lo que vas a enviar.
El ejemplo siguiente es ilustrativo. Comprueba los nombres exactos de los campos en la documentación de OpenAI antes de copiarlo.
{
"name": "ticket.status_changed",
"description": "A support ticket in a project you can access changed status.",
"inputSchema": {
"type": "object",
"properties": {
"project_id": { "type": "string" },
"status": { "type": "string", "enum": ["open", "pending", "closed"] }
},
"required": ["project_id"]
},
"payloadSchema": {
"type": "object",
"properties": {
"ticket_id": { "type": "string" },
"new_status": { "type": "string" },
"summary": { "type": "string" }
}
}
}Mantén los filtros acotados y con sentido para el usuario. Un proyecto o un estado de ticket funcionan bien, de modo que cada persona recibe los eventos que pidió y poco más. Trata el payloadSchema como un contrato público: versiónalo, no lo rompas y mantén los payloads ligeros.
Limita los eventos al usuario autenticado
El borrador establece que la autorización usa el mismo principal MCP que tus herramientas. En la práctica, muestra solo los tipos de evento que el usuario autenticado tiene permiso para ver y acepta solo filtros que apunten a recursos a los que ese usuario puede acceder.
Paso 2 de ASVD (Subscribe): events/subscribe y events/unsubscribe idempotentes
Los clientes reintentan. Las redes pierden respuestas. Si una solicitud de suscripción repetida crea una segunda suscripción, cada evento se envía dos veces y la automatización de alguien se dispara dos veces. Diseña ambos métodos de forma que volver a llamarlos no cambie nada.
Subscribe
Guarda cada suscripción con su tipo de evento, filtros normalizados, URL de callback, secreto de firma y propietario. Construye una clave determinista a partir del propietario, el tipo de evento, los filtros normalizados y la URL de callback. Cuando un usuario autorizado repite la solicitud, recibe la suscripción existente.
authorize(owner_id, event_name, filters) // always first, even on repeats
key = hash(owner_id, event_name, canonical_json(filters), callback_url)
if store.exists(key): return store.get(key)
verify_callback(callback_url) // ASVD Step 3
sub = store.create(key, secret=new_secret(), status="active")
return subLa autorización se ejecuta antes de la comprobación de existencia a propósito. Si las inviertes, un usuario cuyo acceso se haya revocado podría reenviar una llamada de suscripción antigua y recuperar la suscripción sin que nadie lo note.
Unsubscribe
Debe ser seguro llamar dos veces a unsubscribe. Si la suscripción ya no existe, devuelve éxito, no un error. Quien llamó quería eliminarla, y ya está eliminada.
Persistencia y autorización
Guarda las suscripciones en almacenamiento duradero. Un mapa en memoria lo pierde todo en el siguiente despliegue, y las entregas se detienen sin ningún error visible. Comprueba la autorización al suscribir y de nuevo al entregar, porque el acceso puede revocarse entre ambos momentos.
También necesitas una vía de limpieza. La documentación de OpenAI indica que no se debe reintentar una entrega que devuelve 410. Nuestra interpretación es que el receptor ya no quiere la suscripción, así que márcala como retirada en lugar de dejar que falle con cada evento futuro.
Paso 3 de ASVD (Verify): confirma el callback con el desafío firmado
Antes de que cualquier suscripción se active, envía un desafío de verificación firmado a la URL de callback y confirma la respuesta esperada. Así tu servidor nunca envía eventos a un endpoint que no haya demostrado ser el receptor previsto.
Si la verificación falla, la documentación de OpenAI indica que se devuelva el error JSON-RPC -32015 (CallbackEndpointError) con un data.reason categorizado, como challenge_failed o timeout.
Presta atención a las divergencias en este punto. El borrador de diseño actual dice que sus revisiones anteriores usaban del -32011 al -32015, un subrango que la especificación nunca asigna, y que las implementaciones de esas revisiones deben renumerar. Dicho de forma sencilla, el código de la documentación de OpenAI procede de una revisión anterior del borrador. Por ahora sigue la documentación de OpenAI, porque ChatGPT es el cliente para el que construyes, y define el código una sola vez como constante con nombre para que un cambio futuro se resuelva editando una línea.
Pon un tiempo de espera limitado a la solicitud del desafío y registra la categoría del motivo en cada fallo. Cuando un usuario te diga que su automatización nunca arrancó, esa línea de log es el primer sitio donde mirar. Si ya instrumentas las ejecuciones de agentes, nuestro manual de trazas OpenTelemetry GenAI es el lugar natural para la telemetría de verificación y entrega.
Paso 4 de ASVD (Deliver): firma y envía los eventos como Standard Webhooks
Las entregas siguen la especificación Standard Webhooks. Según Svix, X-MCP-Subscription-Id es la única cabecera específica de MCP, y le indica al receptor con qué suscripción, y por tanto con qué secreto, debe verificar la firma.
Tamaño y forma
La documentación de OpenAI indica que se envíe un evento por solicitud, con un cuerpo completo de no más de 256 KiB (262,144 bytes). ChatGPT puede agrupar eventos entregados por separado en una sola ejecución de tarea, según la configuración de agrupación de la tarea. No tomes 256 KiB como objetivo. Standard Webhooks recomienda mantener los payloads pequeños, normalmente por debajo de 20 KB. Envía identificadores y un resumen breve, y deja que ChatGPT llame a tus herramientas cuando necesite el registro completo.
Reintentos y condiciones de parada
La documentación de OpenAI indica que los fallos transitorios se reintenten con backoff exponencial y un número limitado de intentos, conservando el ID del evento y generando una nueva marca de tiempo de firma y una nueva firma en cada intento. Mantener el mismo ID de evento le da al receptor algo con lo que deduplicar, y la marca de tiempo y la firma nuevas evitan que la solicitud se rechace por obsoleta.
La documentación de OpenAI también indica que no se reintenten las entregas que devuelven 410 o 413. Cuando una entrega se rechaza de este modo, te sugerimos revisar el estado de tus suscripciones y el diseño del payload en lugar de volver a enviar la solicitud.
| Resultado de la entrega | Qué debe hacer tu servidor |
|---|---|
| 2xx | Marcar como entregado |
| Timeout o 5xx transitorio | Reintentar con backoff exponencial, mismo ID de evento, nueva marca de tiempo y nueva firma, intentos limitados, según la documentación de OpenAI |
| 410 | No reintentar, según la documentación de OpenAI; retirar la suscripción es una respuesta razonable |
| 413 | No reintentar, según la documentación de OpenAI; trátalo como un error de diseño del payload |
Standard Webhooks recomienda un tiempo de espera de solicitud de 15 a 30 segundos. Elige tu valor de forma deliberada en lugar de heredar el que traiga por defecto tu biblioteca HTTP.
Usa una biblioteca oficial
Firma con una biblioteca oficial de Standard Webhooks, como la biblioteca JavaScript de Standard Webhooks o la oficial para tu stack, en lugar de escribir tu propio código HMAC. Una biblioteca construida conforme a la especificación es la vía más segura para generar firmas que los receptores puedan verificar.
Prueba antes de lanzar: lista de comprobación ASVD previa al lanzamiento
Recorre esta lista en staging, conectado a una suscripción real de ChatGPT, antes de lanzar. Cada punto pone a prueba una etapa del bucle.
Los reintentos conservan el ID del evento, renuevan la firma y se detienen ante 410 y 413.
- [ ] Advertise, filtros: Los eventos que quedan fuera de los filtros de una suscripción nunca se entregan. Prueba con eventos que cumplan algunos filtros pero no todos.
- [ ] Subscribe, duplicados: Repetir una llamada de suscripción devuelve la suscripción existente y no crea nada nuevo.
- [ ] Subscribe, cancelación: Tras cancelar la suscripción no se envía nada más, incluidos los reintentos ya en cola. Una segunda llamada a unsubscribe devuelve éxito.
- [ ] Subscribe, reinicios: Tras un reinicio y un nuevo despliegue, las suscripciones y los secretos persisten y las entregas se reanudan.
- [ ] Subscribe, autorización: Revoca el acceso de un usuario a un recurso filtrado. Las entregas relacionadas se detienen y una llamada de suscripción repetida se rechaza.
- [ ] Verify, desafío del callback: Ejecuta un desafío que se supere y otro que falle. El fallo devuelve el código de error documentado con un data.reason.
- [ ] Deliver, eventos repetidos: Reenvía el mismo ID de evento y anota qué hace ChatGPT con él. No des por hecha una deduplicación que no hayas observado.
- [ ] Deliver, límites de tamaño: Los payloads justo por debajo y justo por encima de 256 KiB se gestionan cada uno como pretendías.
Errores comunes al construir servidores MCP Events
- Construir modos que nadie usa. El polling, el streaming y las notificaciones gap o terminated no forman parte de la integración de ChatGPT. Los heartbeats entran en la misma categoría. El borrador dice que un servidor debería enviar un heartbeat al menos cada 30 segundos, pero eso se aplica al streaming en modo push, que ChatGPT no admite.
- Hacer los reintentos al revés. Un ID de evento nuevo en cada reintento le quita al receptor su clave de deduplicación. Reutilizar la marca de tiempo y la firma antiguas invita a un rechazo por obsolescencia.
- Reintentar callejones sin salida. La documentación de OpenAI indica que no se reintenten las entregas que devuelven 410 o 413. El mismo cuerpo volverá a rebotar.
- Enviar registros completos. Los documentos completos acercan los payloads a 256 KiB, cuando Standard Webhooks sugiere quedarse por debajo de 20 KB.
- Mantener las suscripciones en memoria. Desaparecen al reiniciar y nada te avisa.
- Confiar en el texto del payload. Cuando un evento incluye texto generado por usuarios, por ejemplo un mensaje de un cliente, ese texto puede contener instrucciones dirigidas al modelo. Trata los payloads como entrada no confiable, igual que los resultados de las herramientas, y elimina ese texto o delimítalo con claridad.
Advertencias: cambios en la especificación y límites operativos
La especificación es un borrador. El código de error de OpenAI y la renumeración del borrador actual ya no coinciden, y el grupo de trabajo sigue ajustando su ámbito. Construye según la documentación de OpenAI y vuelve a leerla de forma periódica.
Tu código personalizado es temporal. El soporte en los SDK es desigual. Planifica sustituir los controladores cuando llegue el soporte oficial.
La automatización desatendida necesita salvaguardas. Antes de que una tarea activada por eventos toque sistemas de producción, decide qué acciones puede ejecutar sin la aprobación de una persona. Añade registros de auditoría y límites de frecuencia, y dale a cada suscripción su propio interruptor de apagado. Para saber más sobre cómo acotar lo que puede alcanzar una tarea activada, consulta nuestra nota sobre cómo contener el alcance de un agente comprometido. Si el trabajo activado crece hasta convertirse en procesos de varios pasos, nuestra lista de comprobación para elegir el runtime de agentes de IA duraderos puede ayudarte a decidir dónde debe residir ese estado.
Confirma los datos de segunda mano. La fecha de lanzamiento y la versión de protocolo mencionadas arriba proceden en parte de guías de terceros. Contrástalas con la documentación de OpenAI.
Puntos clave
- 1Construye siguiendo el bucle Advertise-Subscribe-Verify-Deliver (ASVD): anuncia los eventos, suscribe de forma idempotente, verifica los callbacks y entrega eventos firmados.
- 2ChatGPT solo admite la entrega por webhook y la verificación de callbacks del borrador de MCP Events, así que omite el polling, el streaming y las notificaciones gap y terminated.
- 3Ejecuta la autorización antes de devolver una suscripción existente, haz que subscribe y unsubscribe sean idempotentes y guarda las suscripciones en almacenamiento duradero.
- 4Verifica cada URL de callback con un desafío firmado antes de activarla. Guarda el código de error de fallo en una sola constante, porque el borrador lo ha renumerado.
- 5La documentación de OpenAI limita el cuerpo de cada solicitud de un solo evento a 256 KiB, pero Standard Webhooks recomienda payloads por debajo de 20 KB.
- 6La documentación de OpenAI indica no reintentar un 410 o un 413, y reintentar los fallos transitorios con el mismo ID de evento y una firma nueva.
- 7Los SDK oficiales de Python y TypeScript no admitían MCP Events en el lanzamiento y el SDK de Go aún no puede anunciar la capacidad, así que aísla los controladores personalizados.
Conclusión
Svix considera a ChatGPT el primer cliente importante en admitir MCP Events. Para los equipos que ya tienen un servidor MCP o una API SaaS, esto hace que sea un momento razonable para dejar que los cambios en sus propios sistemas inicien trabajo en ChatGPT, en lugar de esperar a que alguien escriba un prompt. La mayor parte de la construcción es ingeniería de webhooks que probablemente ya has hecho antes, organizada como el bucle ASVD.
Las partes complicadas son las que siguen en movimiento. Los códigos de error del borrador ya han cambiado una vez y el soporte en los SDK es irregular. Además, hay una cuestión de seguridad que merece una reflexión seria: ¿qué debería poder hacer una tarea desatendida con un texto de payload que no ha escrito ella?
El camino que sugerimos es modesto. Lanza un único tipo de evento, acotado y bien filtrado. Pásalo por la lista de comprobación previa al lanzamiento y después obsérvalo en producción con registros y un interruptor de apagado a mano. Mantén el código de protocolo personalizado ligero y separado de la lógica de negocio, para que un cambio futuro en la especificación cueste una pequeña edición y no una reescritura. Añade más tipos de evento cuando el primero se haya comportado de forma fiable durante un tiempo.
Preguntas frecuentes
¿Qué son los MCP Events de ChatGPT?
MCP Events permite que ChatGPT se suscriba a actualizaciones de tu servidor MCP, como mensajes nuevos, cambios de contenido o cambios de estado. La documentación de OpenAI indica que ChatGPT admite la entrega por webhook y la verificación de callbacks del borrador de la especificación MCP Events. Los usuarios eligen qué monitorizar y qué debe hacer ChatGPT cuando llega una actualización, de modo que un conector puede iniciar una automatización sin esperar a un prompt.
¿ChatGPT admite polling o streaming para MCP Events, o solo webhooks?
Solo webhooks. La documentación de OpenAI indica que ChatGPT admite la entrega por webhook y la verificación de callbacks del borrador de la especificación MCP Events. El polling, el streaming y las notificaciones de control gap y terminated del borrador no están soportados en esta integración, así que puedes prescindir de esas rutas de código.
¿Cuál es el tamaño máximo de payload de evento que acepta ChatGPT y qué tamaño deberían tener realmente los payloads?
La documentación de OpenAI indica que ChatGPT acepta un evento por solicitud con un cuerpo completo de no más de 256 KiB (262,144 bytes). Tómalo como un techo. La especificación Standard Webhooks recomienda mantener los payloads pequeños, normalmente por debajo de 20 KB. En la práctica, envía identificadores y resúmenes breves y deja que ChatGPT obtenga los registros completos a través de tus herramientas.
¿Cómo deben funcionar los reintentos y qué respuestas HTTP indican que debo dejar de reintentar?
La documentación de OpenAI indica que no se reintenten las entregas que devuelven 410 o 413. Te sugerimos tratar cualquiera de esas respuestas como una señal para cambiar algo por tu parte, como el estado de la suscripción o el diseño del payload, en lugar de volver a intentarlo. La documentación de OpenAI también indica que los fallos transitorios se reintenten con backoff exponencial y un número limitado de intentos, conservando el ID del evento y generando una nueva marca de tiempo de firma y una nueva firma en cada intento.
¿Qué error debe devolver mi servidor cuando falla la verificación del callback y por qué podría cambiar el código?
La documentación de OpenAI indica que se devuelva el error JSON-RPC -32015 (CallbackEndpointError) con un data.reason categorizado, como challenge_failed o timeout. Sin embargo, el borrador de diseño actual dice que las revisiones anteriores usaban del -32011 al -32015 y que las implementaciones deben renumerar. Sigue la documentación de OpenAI para ChatGPT, guarda el código en una sola constante y vuelve a revisar la documentación con regularidad.
¿Puedo usar hoy los SDK oficiales de MCP para Python, TypeScript o Go para construir MCP Events?
En parte. Un desarrollador de la comunidad informó de que el SDK oficial de Python (mcp 2.2.0) y el SDK de TypeScript no admitían MCP Events en el lanzamiento. En el SDK de Go puedes implementar events/list, events/subscribe y events/unsubscribe como métodos personalizados, pero sigue faltando la forma de anunciar la capacidad events de nivel superior. Consulta las versiones actuales y mantén aislados los controladores personalizados para poder sustituirlos más adelante.
Fuentes
- https://developers.openai.com/plugins/build/mcp-events
- https://github.com/modelcontextprotocol/experimental-ext-triggers-events/blob/main/docs/design-sketch-proposal.md
- https://modelcontextprotocol.io/community/working-groups/tasks-events
- https://github.com/standard-webhooks/standard-webhooks/blob/main/spec/standard-webhooks.md
- https://github.com/standard-webhooks/standard-webhooks/tree/main/libraries/javascript
- https://www.svix.com/blog/mcp-events/
- https://dev.to/hassann/mcp-events-explained-build-and-test-a-webhook-emitting-mcp-server-chatgpt-can-subscribe-to-4od8
- https://community.openai.com/t/mcp-events-for-the-official-python-mcp-sdk-tested-end-to-end-with-chatgpt/1402999
- https://github.com/modelcontextprotocol/go-sdk/issues/1325
- https://community.openai.com/t/devday-2026-announcements-and-developer-resources/1402006
Escrito por
Hamza DiazHamza Diaz es el fundador de Optijara, donde crea agentes de IA prácticos, sistemas de automatización y flujos de trabajo de Copilot para empresas de servicios. Escribe sobre operaciones de IA, estrategia de agentes e implementación real para equipos que quieren sistemas útiles en lugar de promesas vacías.
