使用说明
Openai应用模板(todo APP)
构建、预览和发布一个ChatGPT应用程序,该应用程序呈现一个响应式的React小部件,并与模型上下文协议(MCP)服务器通信——所有这些都来自一个存储库。
- 单文件小部件交付 –每个小部件都捆绑在
dist/<name>.html使用内联JS+CSS,因此ChatGPT可以通过以下方式嵌入它ui://widget/.... - 电池包括MCP服务器 –公开SSE+POST端点,通告工具/资源,并返回结构化todo数据和小部件元数据。
- 本地首个DX –带有HMR、Tailwind风格、React 19、TypeScript和反映ChatGPT的助手钩子的Vite开发服务器
window.openai运行时。
使用此模板作为任何需要交互式UI和ChatGPT代理可以调用的工具的小型应用程序的起点。
一览
| 工件 | 技术 | 目的 |
|---|---|---|
src/widgets/todo.tsx |
React+hooks | 交互式todo小部件,可以在与代理同步的同时乐观地更新本地状态 |
server.ts |
节点+ @modelcontextprotocol/sdk |
最小化MCP服务器暴露 todo list, add_todo, toggle_todo, delete_todo,以及小部件资源 |
build.ts |
Vite+esbuild | 发现小部件条目,将其捆绑在一起,并生成准备好的内联HTML文件 ui://widget/... |
dev.ts |
Vite loader | 允许您通过以下方式热重新加载任何小部件 http://localhost:5173?entry=<name> |
先决条件
- Node.js 18+
- npm(或者pnpm/yarn,如果你调整脚本的话)
- (可选) 吸烟 或类似的隧道,与ChatGPT共享MCP服务器
安装依赖项:
npm install
快速开始
-
构建小部件包
npm run build # → dist/todo.html (inline CSS + JS) -
运行MCP服务器
npm start # SSE GET http://localhost:8000/mcp # POST POST http://localhost:8000/mcp/messages?sessionId=... -
在本地预览小部件(可选)
npm run dev # open http://localhost:5173?entry=todo -
暴露于ChatGPT(可选)
ngrok http 8000 # use https://<subdomain>.ngrok-free.app/mcp as the connector URL
开发流程
小部件迭代
- 小工具位于
src/widgets/<name>.tsx。每个文件都应该调用createRoot并自行安装__WIDGET_ROOT_ID__. npm run dev使用HMR启动Vite。引导到http://localhost:5173?entry=<name>加载该小部件。- 挂钩下
src/hooks提供键入访问权限window.openai全局:useWidgetProps提取结构化工具输出(toolOutput.todoList在这种情况下)。useWidgetState通过以下方式使本地小部件状态与ChatGPT主机保持同步window.openai.setWidgetState.useCallTool,useRequestDisplayMode等包装MCP API。
- todo小部件显示
theme,safeArea.insets,displayMode,以及maxHeight因此,它可以匹配ChatGPT的亮/暗调色板,尊重安全区域,并根据PiP、内联或全屏布局调整自身大小,而无需您进行额外工作。
ChatGPT的构建
npm run build自动发现中的每个文件src/widgets(或嵌套index.tsx目录中的文件)并发出dist/<name>.html.- 每个HTML文件内联:
- 共享顺风风格
src/styles/main.css - 退路
window.todoData独立预览块 - 缩小的小部件包
- 共享顺风风格
- 构建脚本保持输出自包含,因此ChatGPT可以获取
ui://widget/<name>.html没有额外的资产。
MCP服务器
server.ts电线向上@modelcontextprotocol/sdk带着一个SSEServerTransport:GET /mcp启动SSE会话。POST /mcp/messages?sessionId=<id>流工具消息/响应。
- 默认情况下附带的工具:
名称 描述 参数 list_todos返回当前待办事项列表 none add_todo_item插入新待办事项 { title }toggle_todo_item翻转完成状态 { todoId }delete_todo_item删除待办事项 { todoId } - 所有工具响应包括:
structuredContent.todoList(反映小部件数据契约)_meta.openai/*描述符,以便ChatGPT知道如何呈现小部件
- 服务器在内存中保存了一个简单的
globalTodoState.当你从演示毕业时,把它换成一个真正的数据库或API。
连接到ChatGPT应用程序
-
启用 开发者模式 在ChatGPT中→ 设置→ 连接器.
-
创建新的“模型上下文协议”连接器。
-
将MCP URL指向您的服务器(本地隧道或部署的主机):
https://<your-ngrok-subdomain>.ngrok-free.app/mcp -
在ChatGPT对话中,询问类似“显示我的待办事项列表”或“在我的待办事务中添加“审核PR”之类的问题。ChatGPT将调用相应的工具,小部件将使用
ui://服务器公开的资源。
项目结构
openai-apps-template/
├─ src/
│ ├─ widgets/
│ │ └─ todo/
│ │ ├─ index.tsx # Widget entry point (self-mounting)
│ │ └─ components/
│ │ ├─ NewTodo.tsx # Input row for creating todos
│ │ └─ TodoItem.tsx # Presentational list item
│ ├─ hooks/ # window.openai + MCP helpers
│ ├─ styles/main.css # Tailwind layer shared by widgets
│ └─ utils/ # UI utilities (media queries, etc.)
├─ build.ts # Inline widget bundler
├─ dev.ts # Vite preview loader (?entry=<name>)
├─ server.ts # MCP SSE server + todo tools
├─ dist/ # Generated ui:// HTML widgets
├─ package.json
└─ README.md
脚本和配置
| 命令 | 描述 |
|---|---|
npm run build |
将每个小部件捆绑到 dist/*.html |
npm start |
启动MCP服务器(默认为端口 8000) |
npm run start:all |
构建小部件,然后启动服务器 |
npm run dev |
用于小部件HMR预览的Vite开发服务器 |
环境变量:
PORT–覆盖MCP服务器端口(默认8000).
扩展模板
- 添加另一个小部件:drop
src/widgets/notes.tsx,确保其安装到__WIDGET_ROOT_ID__,跑npm run build,然后将其作为新的资源/工具公开server.ts. - 保存待办事项数据:替换
globalTodoState使用数据库调用或REST客户端。小部件需要的唯一合同是{ todoList: TodoList },在哪里TodoList只不过{ title: string; todos: TodoItem[] }. - 增强UI状态:使用
useWidgetState乐观的更新;它已经将状态镜像回ChatGPT,因此主机在代理轮之间保持同步。 - 添加更多工具:在中注册描述符
server.ts(ListToolsRequestSchema处理程序)并在内部实现行为CallToolRequest处理程序。
故障排除
- 小部件显示过时数据 –确保MCP响应包括新鲜
structuredContent.todoList和_meta.openai/outputTemplate。只有当主机发送新的结构化数据时,小部件才会重新同步。 - “未找到构建”错误 –运行
npm run build开始前npm start所以dist/todo.html存在。 - ChatGPT中没有小部件 –验证连接器是否允许渲染小部件(
openai/widgetAccessible: true)而且ui://widget/<name>.html资源通过以下方式列出ListResources. - CORS或隧道问题 –服务器启用
Access-Control-Allow-Origin: *,但你的隧道必须同时向前GET /mcp和POST /mcp/messages.
运输愉快!如果添加新的小部件、存储适配器或部署方案,则会出现未解决的问题或PR。
