Skip to main content
Glama

Demo de MCP de Todo para ChatGPT (Apps SDK + React)

Una aplicación de tareas (todo) minimalista para ChatGPT: un servidor MCP que expone herramientas y una interfaz de usuario HTML interactiva, construida con React + Vite y empaquetada como un único archivo. Incluye una pequeña capa de OAuth de desarrollo para que el asistente de conectores de ChatGPT pueda completar el descubrimiento.

Referencia oficial: Apps SDK Quickstart.

Inicio rápido

npm install
npm start          # builds widget (prestart) then runs server on port 8787 by default
  • Endpoint MCP: http://localhost:8787/mcp

  • Para ChatGPT: exponer con HTTPS (p. ej., ngrok) y crear un conector que apunte a https://<tu-host>/mcp.

  • Si las URLs de descubrimiento muestran el esquema/host incorrecto detrás de un túnel, configura:

    export PUBLIC_BASE_URL=https://tu-host-ngrok.example

Related MCP server: mcp-todo-demo

Estructura del proyecto

Ruta

Rol

server.js

Router HTTP: descubrimiento de OAuth + CORS + StreamableHTTPServerTransport de MCP en /mcp

oauth-dev.js

Descubrimiento de OAuth 2.1 solo para desarrollo + DCR/PKCE (reemplazar con un IdP real para producción)

widget/

Código fuente de Vite + React para la interfaz dentro del chat

dist/todo-widget.html

HTML de archivo único compilado (ignorado por git); cargado por server.js al iniciar


Arquitectura y conceptos

Modelo de una frase

ChatGPT actúa como el cliente MCP. Se comunica mediante MCP sobre HTTPS con tu servidor Node en /mcp. El servidor registra herramientas (lo que el modelo puede llamar) y un recurso (HTML para el widget). El widget se ejecuta en un iframe y se comunica con ChatGPT a través de un puente JSON-RPC mediante postMessage. Los metadatos de OAuth en el mismo origen permiten a ChatGPT adjuntar el conector; esto es independiente de la ejecución de herramientas MCP, pero necesario para la incorporación.

Protocolo de contexto del modelo (MCP)

MCP es una forma estándar para que un host (ChatGPT) descubra e invoque herramientas y lea recursos en un servidor. Este repositorio utiliza @modelcontextprotocol/sdk: una instancia de McpServer registra capacidades y se conecta a un transporte que mapea mensajes MCP a HTTP (StreamableHTTPServerTransport).

MCP base vs. ayudantes del Apps SDK

  • @modelcontextprotocol/sdk: McpServer central, esquemas, transporte.

  • @modelcontextprotocol/ext-apps: registerAppTool y registerAppResource normalizan los metadatos de la UI (qué recurso HTML mostrar para una herramienta) y establecen el tipo MIME de HTML para Apps (RESOURCE_MIME_TYPE).

El widget se registra como un recurso en una URI lógica (p. ej., ui://widget/todo.html). Esa URI no necesita ser una URL web pública; el host la resuelve mediante resources/read de MCP. El _meta.ui.resourceUri de cada herramienta apunta a la misma URI para que ChatGPT sepa qué superficie de UI pertenece a qué herramienta.

Puerta de entrada HTTP (server.js)

Un http.Server de Node maneja varias superficies:

  1. OAuth / descubrimiento (oauth-dev.js) — URLs bien conocidas y endpoints de tokens que ChatGPT espera.

  2. CORS OPTIONS para /mcp.

  3. Salud GET /.

  4. MCP POST / GET / DELETE en /mcp a través del transporte HTTP transmitible.

  5. 404 para rutas desconocidas.

Así que tienes un proceso, múltiples APIs HTTP lógicas (OAuth HTTP + MCP HTTP).

HTTP transmitible y ciclo de vida del servidor

El transporte se crea por cada solicitud MCP entrante, con sessionIdGenerator: undefined (modo sin estado para esta demo). Se construye un nuevo McpServer por solicitud y se destruye cuando la respuesta se cierra.

Importante: el estado de las tareas en memoria (todos en server.js) vive en el ámbito del módulo, no dentro de la instancia de McpServer. Por lo tanto, el estado persiste durante la vida útil del proceso de Node, aunque cada solicitud obtenga un nuevo objeto de servidor MCP.

Herramientas y el contrato de UI

Las herramientas (add_todo, complete_todo) declaran esquemas de entrada (Zod) para que el host valide los argumentos.

Los resultados de las herramientas incluyen:

  • content: contenido MCP habitual (p. ej., texto) para el modelo/conversación.

  • structuredContent: JSON consumido por el widget — aquí { tasks: [...] }.

Usar la misma forma de structuredContent para cada mutación mantiene la UI de React sincronizada, ya sea que la llamada haya sido activada por el usuario en el widget o por el modelo en el chat.

OAuth (oauth-dev.js)

El flujo de conectores de ChatGPT obtiene metadatos de recursos protegidos por OAuth y metadatos del servidor de autorización (ver Apps SDK auth). Sin esas rutas, la configuración puede fallar con "Error fetching OAuth configuration".

Este repositorio incluye un servidor de autorización solo para desarrollo (descubrimiento, registro dinámico de clientes, redirección de autorización, intercambio de tokens PKCE) limitado a las URLs de redirección de ChatGPT. No lo uses tal cual para producción — cámbialo por Auth0, Stytch, Cognito o similar, y verifica los tokens en las solicitudes MCP.

PUBLIC_BASE_URL fuerza el origen público https:// en los metadatos cuando los proxies/ngrok no configuran Host / X-Forwarded-Proto de la manera que necesitas.

Puente del widget (widget/src/bridge.ts)

El HTML compilado se ejecuta dentro del iframe de ChatGPT. No llama a tu URL /mcp como una SPA normal; utiliza el puente de UI de MCP Apps:

  1. ui/initialize y luego ui/notifications/initialized — saludo con el host.

  2. tools/call — pedir al host que ejecute una herramienta MCP nombrada con argumentos (las mismas herramientas que usa el modelo).

  3. ui/notifications/tool-result — cuando el modelo ejecuta una herramienta, el host puede enviar el resultado para que la UI se actualice sin una ruta de retorno directa desde tools/call.

Por lo tanto, hay dos rutas de actualización: respuestas RPC para llamadas iniciadas por la UI y notificaciones para llamadas iniciadas por el modelo.

Por qué HTML de archivo único (Vite + vite-plugin-singlefile)

ChatGPT recibe el widget como HTML incrustado desde la lectura de recursos MCP, no como "tu sitio + fragmentos JS separados". Las URLs de fragmentos relativos se romperían en ese modelo de incrustación. La compilación produce un dist/todo-widget.html con JS/CSS en línea; server.js lo lee al inicio en todoHtml.

React es una capa de ergonomía para el desarrollador; el artefacto desplegable es HTML estático.

Flujos de extremo a extremo

Usuario en ChatGPT: mensaje → el modelo selecciona una herramienta → ChatGPT hace POST a tu /mcp → la herramienta se ejecuta → devuelve structuredContent.tasks → el host muestra/actualiza el widget.

Usuario en el widget: React → tools/call vía postMessage → el host reenvía a MCP → mismos manejadores → el resultado RPC actualiza el estado.

Configuración del conector: ChatGPT accede a /.well-known/... en tu origen → vinculación de OAuth si es necesario → las llamadas MCP posteriores a /mcp pueden incluir Authorization: Bearer ... (hacer cumplir eso en cada herramienta es un paso de producción).

Próximos pasos naturales

Área

Dirección

Estado

Persistir tareas en una base de datos; limitar por ID de usuario autenticado desde el token de acceso.

Auth

Reemplazar oauth-dev.js con un IdP real; validar emisor, audiencia y alcances en cada solicitud MCP.

Sesión MCP

Sesiones con estado si necesitas diferentes semánticas de streaming o ciclo de vida.

Herramientas

Descripciones/esquemas más ricos, outputSchema opcional, nombres más claros para el enrutamiento del modelo.

Widget

Mismo puente; mejorar UX, errores y estados de carga.

Scripts

Script

Descripción

npm run build

Compilar dist/todo-widget.html desde widget/

npm start

npm run build y luego node server.js

npm run build:widget

Solo compilación de Vite

Puerto predeterminado: 8787 (la variable de entorno PORT tiene prioridad).

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

No tool schema history has been recorded yet.

Maintenance

ActivityInactive
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    A minimal MCP server demonstrating how to build ChatGPT-compatible applications using Next.js with widget rendering capabilities. Provides a starter template for integrating Next.js applications with the ChatGPT Apps SDK through the Model Context Protocol.
    -
  • F
    license
    Not graded
    quality
    C
    maintenance
    A minimal MCP server that provides an interactive to-do list with checkboxes in chat, demonstrating MCP Apps UI resource integration and tool-based state updates.
    -
  • F
    license
    Not graded
    quality
    C
    maintenance
    A minimal Next.js application demonstrating how to build an OpenAI Apps SDK compatible MCP server with widget rendering in ChatGPT.
    -
  • A
    license
    Not graded
    quality
    B
    maintenance
    A Model Context Protocol server with a built-in OAuth 2.1 authorization server and a Next.js todo app, enabling authenticated task management (create, read, update, delete tasks) via natural language through an MCP client.
    18
    ISC

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/iamzeeali/mcpserver2'

If you have feedback or need assistance with the MCP directory API, please join our Discord server