Skip to main content
Glama

ChatGPT Todo MCP 演示 (Apps SDK + React)

一个为 ChatGPT 设计的极简 todo 应用:一个 MCP 服务器,通过 React + Vite 构建并嵌入为单文件包,暴露了工具和一个交互式 HTML UI。包含一个简单的 开发 OAuth 层,以便 ChatGPT 的连接器向导可以完成发现过程。

官方参考:Apps SDK 快速入门。

快速开始

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

  • 对于 ChatGPT:使用 HTTPS 暴露(例如 ngrok),并创建一个指向 https://<your-host>/mcp 的连接器。

  • 如果发现 URL 在隧道后显示错误的方案/主机,请设置:

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

Related MCP server: mcp-todo-demo

项目布局

路径

角色

server.js

HTTP 路由器:OAuth 发现 + CORS + /mcp 上的 MCP StreamableHTTPServerTransport

oauth-dev.js

仅供开发的 OAuth 2.1 发现 + DCR/PKCE(生产环境请替换为真实的 IdP)

widget/

用于聊天内 UI 的 Vite + React 源码

dist/todo-widget.html

构建后的单文件 HTML(已忽略 git);由 server.js 在启动时加载


架构与概念

一句话模型

ChatGPT 作为 MCP 客户端。它通过 HTTPS 上的 MCP 与您在 /mcp 上的 Node 服务器 通信。服务器注册 工具(模型可以调用的内容)和一个 资源(小部件的 HTML)。小部件运行在 iframe 中,并通过 postMessage 上的 JSON-RPC 网桥 与 ChatGPT 通信。同一源上的 OAuth 元数据允许 ChatGPT 附加连接器;它与 MCP 工具执行是分开的,但对于入驻是必需的。

模型上下文协议 (MCP)

MCP 是主机(ChatGPT)发现和调用服务器上的 工具 并读取 资源 的标准方式。此仓库使用 @modelcontextprotocol/sdk:一个 McpServer 实例注册功能,并连接到一个将 MCP 消息映射到 HTTP 的 传输层 (StreamableHTTPServerTransport)。

基础 MCP 与 Apps SDK 辅助工具

  • @modelcontextprotocol/sdk:核心 McpServer、模式、传输层。

  • @modelcontextprotocol/ext-apps:registerAppTool 和 registerAppResource 用于规范化 UI 元数据(工具显示哪个 HTML 资源)并设置 Apps HTML MIME 类型 (RESOURCE_MIME_TYPE)。

小部件被注册为逻辑 URI(例如 ui://widget/todo.html)处的资源。该 URI 不需要是公共 Web URL;主机通过 MCP resources/read 解析它。每个工具的 _meta.ui.resourceUri 都指向同一个 URI,以便 ChatGPT 知道哪个 UI 界面属于哪个工具。

HTTP 前门 (server.js)

一个 Node http.Server 处理多个层面:

  1. OAuth / 发现 (oauth-dev.js) — ChatGPT 期望的知名 URL 和令牌端点。

  2. CORS OPTIONS 用于 /mcp。

  3. 健康检查 GET /。

  4. MCP POST / GET / DELETE 在 /mcp 上,通过可流式传输的 HTTP 传输层。

  5. 404 用于未知路径。

因此,您拥有 一个进程,多个逻辑 HTTP API(OAuth HTTP + MCP HTTP)。

可流式传输的 HTTP 与服务器生命周期

传输层是为每个传入的 MCP 请求创建的,sessionIdGenerator: undefined(此演示为无状态模式)。每个请求都会构建一个新的 McpServer,并在响应关闭时销毁。

重要提示: 内存中的 todo 状态(server.js 中的 todos)存在于 模块作用域,而不是 McpServer 实例内部。因此,即使每个请求都获得一个新的 MCP 服务器对象,状态在 Node 进程的生命周期内仍然保持。

工具与 UI 契约

工具 (add_todo, complete_todo) 声明 输入模式 (Zod),以便主机验证参数。

工具结果包括:

  • content:模型/对话通常使用的 MCP 内容(例如文本)。

  • structuredContent:小部件使用的 JSON — 这里是 { tasks: [...] }。

对每次变更使用相同的 structuredContent 形状,可以保持 React UI 同步,无论调用是由 小部件中的用户 触发,还是由聊天中的 模型 触发。

OAuth (oauth-dev.js)

ChatGPT 的连接器流程会获取 OAuth 受保护资源元数据 和 授权服务器元数据(参见 Apps SDK 认证)。如果没有这些路由,设置可能会失败,提示“获取 OAuth 配置时出错”。

此仓库提供了一个 仅供开发使用 的授权服务器(发现、动态客户端注册、授权重定向、PKCE 令牌交换),其范围限定为 ChatGPT 重定向 URL。请勿在生产环境中直接使用它 — 请替换为 Auth0、Stytch、Cognito 等,并在 MCP 请求上验证令牌。

当代理/ngrok 没有按您需要的方式设置 Host / X-Forwarded-Proto 时,PUBLIC_BASE_URL 会强制元数据中的公共 https:// 源。

小部件网桥 (widget/src/bridge.ts)

构建后的 HTML 运行在 ChatGPT 的 iframe 内部。它不像普通的 SPA 那样调用您的 /mcp URL;它使用 MCP Apps UI 网桥:

  1. ui/initialize 然后 ui/notifications/initialized — 与主机握手。

  2. tools/call — 请求主机运行带有参数的命名 MCP 工具(与模型使用的工具相同)。

  3. ui/notifications/tool-result — 当 模型 运行工具时,主机可以推送结果,以便 UI 在没有来自 tools/call 的直接返回路径的情况下更新。

因此有 两条更新路径:UI 发起调用的 RPC 响应,以及模型发起调用的通知。

为什么使用单文件 HTML (Vite + vite-plugin-singlefile)

ChatGPT 从 MCP 资源读取中接收小部件作为 嵌入式 HTML,而不是作为“您的站点 + 独立的 JS 分块”。相对分块 URL 在该嵌入模型中会失效。构建过程产生 一个 dist/todo-widget.html,其中包含内联的 JS/CSS;server.js 在启动时将其读取到 todoHtml 中。

React 是一个 开发者工效学 层;可部署的工件 是静态 HTML。

端到端流程

ChatGPT 中的用户: 消息 → 模型选择工具 → ChatGPT POST 到您的 /mcp → 工具运行 → 返回 structuredContent.tasks → 主机显示/更新小部件。

小部件中的用户: React → 通过 postMessage 调用 tools/call → 主机转发到 MCP → 相同的处理程序 → RPC 结果更新状态。

连接器设置: ChatGPT 访问您源上的 /.well-known/... → 如果需要则进行 OAuth 链接 → 随后的 /mcp MCP 调用可能包含 Authorization: Bearer ...(在每个工具上强制执行该操作是生产步骤)。

自然的后续步骤

领域

方向

状态

将 todo 持久化到数据库中;按访问令牌中的已认证用户 ID 进行作用域划分。

认证

用真实的 IdP 替换 oauth-dev.js;在每个 MCP 请求上验证颁发者、受众、范围。

MCP 会话

如果您需要不同的流式传输或生命周期语义,请使用有状态会话。

工具

更丰富的描述/模式、可选的 outputSchema、更清晰的模型路由名称。

小部件

相同的网桥;改进 UX、错误处理和加载状态。

脚本

脚本

描述

npm run build

从 widget/ 构建 dist/todo-widget.html

npm start

npm run build 然后 node server.js

npm run build:widget

仅 Vite 构建

默认端口:8787 (PORT 环境变量可覆盖)。

Maintenance

ActivityInactive
ResponsivenessSyncing

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
    D
    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
    D
    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
    D
    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.
    7 npm
    ISC