Volver a todas las publicaciones
yeonghyeon yeonghyeon · 29 abr 2026

Construir un ChatGPT App con Apps SDK: implementación de MCP·OAuth y notas del proceso de revisión

Construir un ChatGPT App con Apps SDK: implementación de MCP·OAuth y notas del proceso de revisión

Hola, soy yeonghyeon, lidero el desarrollo de 3Min API.

Durante las últimas semanas he estado trabajando en el registro de 3Min API en ChatGPT Apps. Tuvimos un rechazo, lo corregimos y finalmente aprobaron la app — y por el camino enviamos el mismo código a Claude Connectors. Este artículo es para otros desarrolladores que están recorriendo el mismo camino. He intentado reunir qué hace falta implementar, dónde suelen producirse los rechazos y qué ocurre realmente durante la revisión en un solo sitio.

He dejado fuera, a propósito, todo lo relacionado con un proveedor cloud o un stack de despliegue concretos. El registro de ChatGPT Apps sigue el mismo flujo independientemente de lo que tengas debajo.

Resumen — ChatGPT Apps y el MCP que lo sustenta

ChatGPT Apps es el modelo de extensión de OpenAI que te permite invocar servicios externos desde dentro de ChatGPT. Los usuarios añaden tu app desde la pantalla de ChatGPT y, dentro del flujo de conversación, pueden invocar directamente las herramientas que expone tu backend.

La base es Model Context Protocol (MCP). MCP es una especificación abierta para conectar LLMs con herramientas externas — define cómo se listan las herramientas y cómo se invocan de forma segura. ChatGPT Apps es uno de los clientes que corren sobre MCP, y Claude Connectors de Anthropic está construido sobre la misma especificación. Es decir, si implementas un servidor MCP correctamente una vez, cubres ambos ecosistemas. Nosotros enviamos el mismo código a los dos directorios, y las definiciones de herramientas y el flujo de autenticación se comparten tal cual.

Por qué nos convertimos en herramienta en vez de construir nuestro propio chatbot

Al principio sí valoramos hacer nuestro propio chatbot. Pero dando un paso atrás, los usuarios ya estaban contando su contexto de negocio a ChatGPT o Claude. Si construimos otro chatbot más, esa misma persona tiene que volver a explicar la misma historia desde cero.

Así que cambiamos de dirección. Añadimos 3Min API como una herramienta a la IA que ya estás usando. El mismo ChatGPT al que le has estado contando tus problemas de negocio puede ahora decir "te lo dejo montado en 3Min API" y hacerlo de verdad. Seguimos valorando un chatbot propio, pero la prioridad es convertirnos en herramienta.

Implementación

Elección del SDK — solo el SDK estándar de MCP

OpenAI ofrece un SDK específico para ChatGPT Apps, pero no fuimos por ese camino. Nuestro servidor depende de una sola pieza: el SDK estándar de MCP (@modelcontextprotocol/sdk). El motivo es sencillo — el mismo servidor tiene que ser reconocido tanto por ChatGPT Apps como por Claude Connectors. Manteniéndonos en el SDK estándar, el código no se bifurca cuando uno de los ecosistemas se actualiza, y podemos enviar el mismo build a los dos directorios.

Las especificaciones de OpenAI están documentadas en Build your MCP server y Connect from ChatGPT. Ambos describen, desde la perspectiva del cliente, cómo ChatGPT reconoce y llama a tu servidor — si implementas un servidor MCP estándar con cuidado, los requisitos de OpenAI se cumplen de forma natural.

Autenticación — OAuth 2.1 como base, API Key como camino auxiliar en el mismo servidor

Para ChatGPT Apps, la respuesta práctica es OAuth 2.1, vía única. La guía oficial de OpenAI lo dice con claridad: "ChatGPT does not support … custom API keys or customer-provided mTLS certificates". Si vas a publicar en el directorio de ChatGPT Apps, con OAuth 2.1 bien implementado es suficiente (también se permite el modo anónimo noauth para herramientas que no tocan datos del usuario, pero para herramientas como la nuestra, que trabajan con los endpoints y los logs de la cuenta del usuario, OAuth es obligatorio).

Dicho esto, si quieres que el mismo servidor MCP funcione también desde clientes locales como Cursor, Claude Code o Gemini CLI, la cosa cambia. El entorno local es un sitio donde el propio usuario puede guardar sus claves directamente, y allí el flujo OAuth se vuelve pesado. Por eso elegimos OAuth 2.1 como autenticación base para ChatGPT Apps y Claude Connectors, y añadir además un camino de API Key sobre el mismo servidor. La misma definición de herramientas funciona bajo ambos modos de autenticación.

OAuth 2.1 — base para ChatGPT Apps y Claude Connectors

Los clientes que corren en entornos gestionados no pueden esperar que los usuarios manejen claves a mano, y la política de OpenAI tampoco deja otra opción. Para que los clientes reconozcan correctamente el servidor, hay que cumplir los siguientes estándares.

  • RFC 7591 — OAuth Dynamic Client Registration. Los clientes se registran ellos mismos.
  • RFC 8414 — Authorization Server Metadata. Los endpoints de autenticación se exponen en /.well-known/oauth-authorization-server.
  • RFC 9728 — Protected Resource Metadata. Metadatos del propio recurso MCP.
  • RFC 7636 PKCE — challenge S256 que evita la interceptación del authorization code.

El flujo es el estándar. Registro dinámico del cliente → el usuario se autentica y se emite un authorization code (un solo uso, expira en 10 minutos) → intercambio del token con verificación PKCE → access token (1 hora) más refresh token (30 días, con rotación). Cuando el access token caduca, se renueva con el refresh token, y el propio refresh token también rota en cada renovación, para reducir el riesgo de robo.

La parte a la que dedicamos más atención fue garantizar que el code se consume de forma atómica una sola vez. El authorization code es un recurso muy valioso para un atacante, así que en el paso del intercambio del token hicimos que el code se reclame con una sola sentencia update, evitando cualquier race condition.

API Key — un camino auxiliar para usar el mismo código desde CLI/IDE

ChatGPT Apps llega por OAuth, pero queríamos que la misma definición de herramientas funcionara también desde clientes MCP locales como Cursor, Claude Code, Gemini CLI o Smithery, así que añadimos un camino adicional con API Key. En entornos locales el usuario puede guardar su propia clave, y enviarla con la cabecera x-api-key es el enfoque más limpio. Emitimos claves por usuario con el prefijo tm_mcp_ y mantenemos, por clave, el estado activo/inactivo y la última hora de uso.

Las 8 herramientas que exponemos y sus marcas de permisos

3Min API expone 8 herramientas a ChatGPT/Claude. Cada herramienta tiene que declarar tres anotaciones estándar de MCP. Primero, los significados.

anotaciónsignificadoejemplo en true
readOnlyHint¿Solo lectura? (no cambia datos)Consultar logs/estadísticas
destructiveHint¿Puede causar cambios irreversibles?Editar/borrar un endpoint
openWorldHint¿Habla con el mundo exterior o produce efectos secundarios?Enviar un webhook externo

Aplicando estos tres valores a nuestras 8 herramientas:

herramientaresumenreadOnlydestructiveopenWorld
helpConsulta de la guía del serviciotruefalsefalse
endpointsCRUD/despliegue de endpointsfalsetruefalse
api_callInvocación de un endpointfalsetruetrue
logsLogs de llamadas y búsquedatruefalsefalse
statsEstadísticas de usotruefalsefalse
collaboratorsClaves de colaboración/invitacionesfalsetruetrue
subscriptionInformación de suscripcióntruefalsefalse
archivesDescarga de archivostruefalsetrue

Áreas que dejamos fuera a propósito

Acciones como borrar la cuenta en sí, cambiar el método de pago o emitir/revocar las claves de autenticación MCP — todo lo que, ante un consentimiento erróneo, no se puede deshacer o que toca directamente el sistema de autenticación — no las hemos expuesto como herramientas. Dejarlas a criterio del LLM convierte una sola llamada equivocada en un incidente de seguridad, y tampoco encaja con la dirección que recomienda la guía de revisión de ChatGPT Apps.

Pruebas — conviene ejecutar los dos caminos de autenticación

Antes de enviar, probamos ambos caminos.

  • Camino OAuth — En ChatGPT web, activamos el modo desarrollador en Settings → Apps & Connectors → Advanced settings y registramos la URL de nuestro servidor MCP con 'Create app'. ChatGPT lee automáticamente el /.well-known/... de nuestro servidor para reconocer los metadatos OAuth, así que puedes recorrer tú mismo la pantalla de consentimiento hasta llegar a llamadas reales a las herramientas.
  • Camino API Key — Añadimos el servidor MCP a Claude Code, Cursor y Gemini CLI, y verificamos las llamadas a las herramientas. También nos registramos en Smithery para confirmar la presencia en el directorio.

El código es el mismo en ambos caminos, pero OAuth tiene que pasar además los metadatos well-known, la pantalla de consentimiento y la renovación de tokens, así que es un escalón más complicado. Antes de enviar, te recomiendo ejecutar al menos el paso en el que el ChatGPT real conecta con tu servidor y se descarga la lista de herramientas.

Envío a revisión — cosas que aprendimos tras un rechazo

El envío en sí es asumible siguiendo la guía oficial de OpenAI (app-submission-guidelines) y haciéndole preguntas a ChatGPT por el camino. Pero durante el formulario, ChatGPT conecta de verdad con tu servidor para traerse la lista de herramientas, así que tu producción tiene que estar en línea en el momento del envío. También hay que aportar credenciales de prueba (correo/contraseña, o una cuenta separada de revisión) para que los revisores de OpenAI puedan llamar a las herramientas ellos mismos.

Aviso 1 — marca los permisos de las herramientas de forma conservadora

Es la causa más habitual de rechazo. En nuestro primer envío dejamos openWorldHint en false en tres herramientas que hablan con el exterior (api_call, collaborators, archives), y por eso nos rechazaron. Tras corregirlo, pasó.

De esas tres, archives emite una URL externa de descarga, así que openWorldHint=true es evidente. Las otras dos son menos directas: api_call dispara tráfico externo a través de webhooks definidos por el usuario, y collaborators envía correos de invitación a colaboradores. Llegan al exterior, pero de forma indirecta, lo justo para hacerte dudar. A posteriori, marcar las dos como true de forma conservadora era lo correcto.

El razonamiento es simple. Una vez rechazado, esperas otras dos semanas aproximadamente para la siguiente revisión. Si una herramienta tiene cualquier flujo que toque el exterior, no dudes — márcala true. En coste de tiempo es la opción más barata. Lista los efectos secundarios que produce cada herramienta una a una, comprueba si alguno sale fuera de tu sistema, y las marcas se acaban colocando solas.

Aviso 2 — las capturas no son "pantallazos", son "trabajo sobre plantilla"

El formulario de envío incluye un campo de capturas que muestra cómo se ve tu app dentro de ChatGPT. Capturar por tu cuenta y subirlo se rechaza sin excepción. Para este paso OpenAI ofrece una guía clara, y el enlace está dentro de la propia interfaz de envío. Así funciona:

  1. En el paso de las capturas dentro del formulario, el enlace de la guía te lleva a un archivo Figma oficial de OpenAI.
  2. Tienes que copiar la plantilla de capturas de ese Figma a tu propio espacio de trabajo de Figma.
  3. Después pegas la pantalla real de tu app dentro de ChatGPT en el sitio designado de la plantilla. La proporción, los márgenes y la composición ya están definidos en la plantilla — tú solo rellenas el contenido.
  4. Por último exportas el tablero terminado como imagen y la subes en el formulario de envío.

Es decir, lo que se envía no es una captura cruda, sino la pantalla de tu app colocada dentro del marco que define OpenAI. Justo antes de enviar, repasa la guía una vez más y sigue exactamente lo que indica. Si saltas este paso y subes capturas tuyas, el envío se rechaza directamente.

Notas de la revisión — incluso tras la aprobación, queda un paso

Desde el envío hasta el resultado pasaron unas dos semanas o más. Si te rechazan y reenvías tras corregir, espera una espera parecida otra vez. Puedes ver el estado en el panel de desarrolladores de OpenAI, y recibes un correo cuando rechazan o aprueban.

La aprobación no significa que ya esté en producción. También tienes que pulsar el botón Publish en el panel para que empiece a aparecer a los usuarios normales.

Una cosa más justo después del lanzamiento. Que un usuario añada tu app no significa que ChatGPT vaya a usar tus herramientas en cada conversación. Incluso en temas relevantes, vas a ver muchas respuestas que no invocan ninguna herramienta. En esos casos conviene avisar al usuario de que llame explícitamente a tu app con una mención @. Pasar ese consejo dispara mucho la tasa de uso de las herramientas.

Claude Connectors — dónde estamos

Claude Connectors corre sobre el mismo MCP. Apenas hizo falta trabajo extra de código. El proceso de revisión, eso sí, está menos pulido que el de OpenAI. No hay un panel para seguir el estado del envío, y nosotros llevamos casi un mes sin recibir aprobación ni rechazo. Vale la pena enviar a ambos a la vez, pero planifica los plazos en torno a OpenAI para ir sobre seguro.

Pruébalo

Si quieres probar las herramientas MCP de 3Min API dentro de ChatGPT, o ver cómo lo hemos publicado, basta con buscar "3Min API" en la pantalla de añadir apps de ChatGPT Apps e instalarlo. Tras autenticarte una vez, menciona @3Min API en tus conversaciones para invocar las herramientas.

Si quieres probarlo desde un cliente MCP local (Claude Code, Cursor, etc.), inicia sesión y ve a Configuración → Integración con IA para emitir una API Key, y empieza directamente. Los detalles por herramienta y los ejemplos de llamada están recogidos en la Guía de Integración con IA.

Espero que esto sirva de pequeño atajo para quienes recorren el mismo camino.