介绍
# ChatGPT Apps Builder
从概念到生产环境,构建、测试和部署 ChatGPT 应用的完整工作流。
## 命令
- `/chatgpt-apps new` - 创建一个新的 ChatGPT 应用 - `/chatgpt-apps add-tool` - 向你的应用添加一个 MCP 工具 - `/chatgpt-apps add-widget` - 向你的应用添加一个小部件 - `/chatgpt-apps add-auth` - 配置身份验证 - `/chatgpt-apps add-database` - 设置数据库 - `/chatgpt-apps validate` - 验证你的应用 - `/chatgpt-apps test` - 运行测试 - `/chatgpt-apps deploy` - 部署到生产环境 - `/chatgpt-apps resume` - 恢复应用开发工作
---
## 目录
1. [创建新应用](#1-创建新应用) 2. [添加 MCP 工具](#2-添加-mcp-工具) 3. [添加小部件](#3-添加小部件) 4. [添加身份验证](#4-添加身份验证) 5. [添加数据库](#5-添加数据库) 6. [生成标准提示词](#6-生成标准提示词) 7. [验证应用](#7-验证应用) 8. [测试应用](#8-测试应用) 9. [部署应用](#9-部署应用) 10. [恢复应用](#10-恢复应用)
---
## 1. 创建新应用
**目的:** 从概念到可运行代码,创建一个新的 ChatGPT 应用。
### 工作流
#### 第一阶段:概念化
1. **询问应用构想** “你想构建什么样的 ChatGPT 应用?请描述它的功能以及它能解决的问题。”
2. **对照 UX 原则进行分析** - **对话杠杆作用**:用户能通过自然语言完成什么? - **原生契合度**:这如何与 ChatGPT 的对话流集成? - **可组合性**:工具能否独立工作并与其它应用组合?
3. **检查反模式** - 静态网站内容展示 - 需要外部标签页的复杂多步工作流 - 重复 ChatGPT 原生功能 - 广告或追加销售
4. **定义用例** 创建 3-5 个主要用例及用户故事。
#### 第二阶段:设计
1. **工具拓扑** - 查询工具 (readOnlyHint: true) - 变更工具 (destructiveHint: false) - 破坏性工具 (destructiveHint: true) - 小部件工具 (返回带有 _meta 的 UI) - 外部 API 工具 (openWorldHint: true)
2. **小部件设计** 对于每个小部件: - `id` - 唯一标识符 (kebab-case) - `name` - 显示名称 - `description` - 它显示什么内容 - `mockData` - 用于预览的示例数据
3. **数据模型** 设计实体和关系。
4. **身份验证要求** - 单用户 (无需身份验证) - 多用户 (Auth0 或 Supabase Auth)
#### 第三阶段:实现
生成具有此结构的完整应用程序:
``` {app-name}/ ├── package.json ├── tsconfig.server.json ├── setup.sh ├── START.sh ├── .env.example ├── .gitignore └── server/ └── index.ts ```
**关键要求:** - 来自 `@modelcontextprotocol/sdk/server/index.js` 的 `Server` 类 - 用于会话管理的 `StreamableHTTPServerTransport` - 小部件 URI:`ui://widget/{widget-id}.html` - 小部件 MIME 类型:`text/html+skybridge` - 工具响应中的 `structuredContent` - 工具上带有 `openai/outputTemplate` 的 `_meta`
#### 第四阶段:测试 - 运行设置:`./setup.sh` - 启动开发环境:`./START.sh --dev` - 预览小部件:`http://localhost:3000/preview` - 测试 MCP 连接
#### 第五阶段:部署 - 生成 Dockerfile 和 render.yaml - 部署到 Render - 配置 ChatGPT 连接器
---
## 2. 添加 MCP 工具
**目的:** 向你的 ChatGPT 应用添加一个新的 MCP 工具。
### 工作流
1. **收集信息** - 这个工具做什么? - 它需要什么输入? - 它返回什么?
2. **分类工具类型** - **查询** (readOnlyHint: true) - 获取数据 - **变更** (destructiveHint: false) - 创建/更新数据 - **破坏性** (destructiveHint: true) - 删除数据 - **小部件** - 返回 UI 内容 - **外部** (openWorldHint: true) - 调用外部 API
3. **设计输入模式** 创建具有适当类型和描述的 Zod 模式。
4. **生成工具处理器** 使用 `chatgpt-mcp-generator` 代理创建: - `server/tools/` 中的工具处理器 - Zod 模式导出 - 类型导出 - 数据库查询 (如需要)
5. **注册工具** 使用元数据更新 `server/index.ts`: ```typescript { name: "my-tool", _meta: { "openai/toolInvocation/invoking": "Loading...", "openai/toolInvocation/invoked": "Done", "openai/outputTemplate": "ui://widget/my-widget.html", // if widget } } ```
6. **更新状态** 将工具添加到 `.chatgpt-app/state.json`。
### 工具命名 使用 kebab-case:`list-items`、`create-task`、`show-recipe-detail`
### 注释指南
| 场景 | readOnlyHint | destructiveHint | openWorldHint | |----------|--------------|-----------------|---------------| | 列表/获取 | true | false | false | | 创建/更新 | false | false | false | | 删除 | false | true | false | | 外部 API | 视情况而定 | 视情况而定 | true |
---
## 3. 添加小部件
**目的:** 添加带有 HTML/CSS/JS 和应用 SDK 集成的内联 HTML 小部件。
### 5 种小部件模式
1. **卡片网格** - 网格中的多个项目 2. **统计仪表板** - 关键指标显示 3. **表格** - 表格数据 4. **柱状图** - 简单的可视化 5. **详情小部件** - 单个项目详情
### 工作流
1. **收集信息** - 小部件用途和数据 - 视觉设计 (卡片、表格、图表等) - 交互性需求
2. **定义数据形状** 使用 TypeScript 接口记录预期的结构。
3. **添加小部件配置** ```typescript const widgets: WidgetConfig[] = [ { id: "my-widget", name: "My Widget", description: "Displays data", templateUri: "ui://widget/my-widget.html", invoking: "Loading...", invoked: "Ready", mockData: { /* sample */ }, }, ]; ```
4. **添加小部件 HTML** 生成 HTML,包含: - 预览模式支持 (`window.PREVIEW_DATA`) - OpenAI 应用 SDK 集成 (`window.openai.toolOutput`) - 事件监听器 (`openai:set_globals`) - 轮询回退机制 (100ms, 10s 超时)
5. **创建/更新工具** 通过 `widgetId` 将工具链接到小部件。
6. **测试小部件** 使用模拟数据在 `/preview/{widget-id}` 预览。
### 小部件 HTML 结构
```javascript (function() { let rendered = false;
function render(data) { if (rendered || !data) return; rendered = true; // Render logic }
function tryRender() { if (window.PREVIEW_DATA) { render(window.PREVIEW_DATA); return; } if (window.openai?.toolOutput) { render(window.openai.toolOutput); } }
window.addEventListener('openai:set_globals', tryRender);
const poll = setInterval(() => { if (window.openai?.toolOutput || window.PREVIEW_DATA) { tryRender(); clearInterval(poll); } }, 100); setTimeout(() => clearInterval(poll), 10000);
tryRender(); })(); ```
---
## 4. 添加身份验证
**目的:** 使用 Auth0 或 Supabase Auth 配置身份验证。
### 何时添加 - 多用户 - 每个用户的持久私有数据 - 用户特定的 API 凭证
### 提供商
**Auth0:** - 企业级 - OAuth 2.1, PKCE 流程 - 社交登录 (Google, GitHub 等)
**Supabase Auth:** - 设置更简单 - 默认邮箱/密码 - 与 Supabase 数据库集成
### 工作流
1. **选择提供商** 根据需求询问用户偏好。
2. **指导设置** - **Auth0:** 创建应用程序,配置回调 URL,获取凭证 - **Supabase:** 已随数据库设置一起配置
3. **生成身份验证代码** 使用 `chatgpt-auth-generator` 代理创建: - 会话管理中间件 - 用户主体提取 - 令牌验证
4. **更新服务器** 添加身份验证中间件以保护路由。
5. **更新环境** ```bash # Auth0 AUTH0_DOMAIN=your-tenant.auth0.com AUTH0_CLIENT_ID=... AUTH0_CLIENT_SECRET=... # Supabase (from database setup) SUPABASE_URL=... SUPABASE_ANON_KEY=... ```
6. **测试** 验证登录流程和用户隔离。
---
## 5. 添加数据库
**目的:** 使用 Supabase 配置 PostgreSQL 数据库。
### 何时添加 - 持久用户数据 - 多实体关系 - 查询/过滤功能
### 工作流
1. **检查 Supabase 设置** 验证账户和项目是否存在。
2. **收集凭证** - 项目 URL - 匿名密钥 (公开) - 服务角色密钥 (服务器端)
3. **定义实体** 对于每个实体,指定: - 字段和类型 - 关系 - 索引
4. **生成模式** 使用 `chatgpt-database-generator` 代理创建 SQL,包含: - `id` (UUID 主键) - `user_subject` (varchar, 已索引) - `created_at` (timestamptz) - `updated_at` (timestamptz) - 用于用户隔离的 RLS 策略
5. **设置连接池** ```typescript import { createClient } from '@supabase/supabase-js'; const supabase = createClient( process.env.SUPABASE_URL!, process.env.SUPABASE_SERVICE_ROLE_KEY! ); ```
6. **应用迁移** 在 Supabase 仪表板中或通过迁移工具运行 SQL。
### 查询模式
始终按 `user_subject` 过滤:
```typescript const { data } = await supabase .from('tasks') .select('*') .eq('user_subject', userSubject); ```
---
## 6. 生成标准提示词
**目的:** 生成测试提示词以验证 ChatGPT 是否正确调用工具。
### 为什么重要 - 衡量精确度/召回率 - 支持迭代 - 发布后监控
### 3 个类别
1. **直接提示词** - 显式工具调用 - “显示我的任务列表” - “创建一个名为...的新任务”
2. **间接提示词** - 基于结果,ChatGPT 应推断出工具 - “我今天需要做什么?” - “帮我整理我的工作”
3. **负面提示词** - 不应触发工具 - “什么是任务?” - “给我讲讲项目管理”
### 工作流
1. **分析工具** 审查每个工具的用途和输入。
2. **生成提示词** 对于每个工具,创建: - 5+ 个直接提示词 - 5+ 个间接提示词 - 3+ 个负面提示词 - 2+ 个边缘案例提示词
3. **最佳实践** - 工具描述以“Use this when...”开头 - 清楚说明局限性 - 在描述中包含示例
4. **保存输出** 写入 `.chatgpt-app/golden-prompts.json`: ```json { "toolName": { "direct": ["prompt1", "prompt2"], "indirect": ["prompt1", "prompt2"], "negative": ["prompt1", "prompt2"], "edge": ["prompt1", "prompt2"] } } ```
---
## 7. 验证应用
**目的:** 部署前的验证套件。
### 10 项验证检查
1. **必需文件** - package.json - tsconfig.server.json - setup.sh (可执行) - START.sh (可执行) - server/index.ts - .env.example
2. **服务器实现** - 使用来自 MCP SDK 的 `Server` - 拥有 `StreamableHTTPServerTransport` - 使用 Map 进行会话管理 - 正确的请求处理程序
3. **小部件配置** - `widgets` 数组存在 - 每个具有 id, name, description, templateUri, mockData - URI 匹配模式 `ui://widget/{id}.html`
4. **工具响应格式** - 返回 `structuredContent` (不仅仅是 `content`) - 小部件工具具有带有 `openai/outputTemplate` 的 `_meta`
5. **资源处理器格式** - MIME 类型:`text/html+skybridge` - 返回带有序列化和 CSP 的 `_meta`
6. **小部件 HTML 结构** - 预览模式支持 - 应用 SDK 的事件监听器 - 轮询回退机制 - 渲染守卫
7. **端点存在性** - `/health` - 健康检查 - `/preview` - 小部件索引 - `/preview/:widgetId` - 小部件预览 - `/mcp` - MCP 端点
8. **Package.json 脚本** - 拥有 `build:server` - 拥有带有 HTTP_MODE=true 的 `start` - 拥有带有监视模式的 `dev` - 无 web 构建脚本 (web/, ui/, client/)
9. **注释验证** - readOnlyHint 设置正确 - 删除操作的 destructiveHint - 外部 API 的 openWorldHint
10. **数据库验证** (如果启用) - 表具有必需字段 - user_subject 已索引 - RLS 策略已启用
### 常见错误
| 错误 | 修复方法 | |-------|-----| | 缺少 structuredContent | 添加到工具响应中 | | 小部件 URI 错误 | 使用 ui://widget/{id}.html | | 无会话管理 | 添加 Map<string, Transport> | | 缺少 _meta | 添加到工具定义和响应中 | | MIME 类型错误 | 使用 text/html+skybridge |
**关键:** 在进行其他验证之前,首先检查文件是否存在!
---
## 8. 测试应用
**目的:** 使用 MCP Inspector 和黄金提示 运行自动化测试。
### 4 类测试
1. **MCP 协议** - 服务器正常启动,无错误 - 处理初始化请求 - 正确列出工具 - 正确列出资源
2. **架构 验证** - 工具架构是有效的 Zod 格式 - 必填字段已标记 - 类型与实现匹配
3. **小部件测试** - 所有小部件在预览模式下渲染 - 模拟数据正确加载 - 无控制台错误
4. **黄金提示测试** - 直接提示触发正确的工具 - 间接提示按预期工作 - 否定提示不触发工具
### 工作流
1. **在测试模式下启动服务器** ```bash HTTP_MODE=true NODE_ENV=test npm run dev ```
2. **运行 MCP Inspector** 测试协议合规性: - 初始化连接 - 列出工具 - 使用有效输入调用每个工具 - 检查响应
3. **架构验证** 验证架构可编译且与实现匹配。
4. **黄金提示测试** 使用 ChatGPT 测试提示: - 记录调用了哪个工具 - 与预期工具进行比较 - 计算精确率/召回率
5. **生成报告** ```json { "passed": 42, "failed": 3, "categories": { "mcp": "✅", "schema": "✅", "widgets": "✅", "prompts": "⚠️ 3 failures" }, "timing": "2.3s" } ```
### 修复失败项
对于每次失败,请解释: - 失败内容 - 失败原因 - 修复方法(附带代码示例)
---
## 9. 部署应用
**目的:** 将 ChatGPT 应用部署到 Render,配置 PostgreSQL 和健康检查。
### 前置条件
- ✅ 验证通过 - ✅ 测试通过 - ✅ Git 仓库干净 - ✅ 环境变量就绪
### 工作流
1. **起飞前检查** - 运行验证 - 运行测试 - 检查数据库连接(如果已启用)
2. **生成 render.yaml** ```yaml services: - type: web name: {app-name} runtime: docker plan: free healthCheckPath: /health envVars: - key: PORT value: 3000 - key: HTTP_MODE value: true - key: NODE_ENV value: production - key: WIDGET_DOMAIN generateValue: true # Add auth/database vars if needed ```
3. **生成 Dockerfile** ```dockerfile FROM node:20-slim WORKDIR /app COPY package*.json ./ RUN npm ci --only=production COPY dist ./dist EXPOSE 3000 CMD ["node", "dist/server/index.js"] ```
4. **部署** **选项 A:自动(如果 Render MCP 可用)** 使用 Render MCP 代理进行部署。 **选项 B:手动** - 推送到 GitHub - 在 Render 控制台中连接仓库 - 设置环境变量 - 部署
5. **验证部署** - 健康检查:`https://{app}.onrender.com/health` - MCP 端点:`https://{app}.onrender.com/mcp` - 工具发现功能正常 - 小部件渲染正常
6. **配置 ChatGPT 连接器** - URL:`https://{app}.onrender.com/mcp` - 在 ChatGPT 中测试
---
## 10. 恢复应用
**目的:** 继续构建进行中的 ChatGPT 应用。
### 工作流
1. **加载状态** 读取 `.chatgpt-app/state.json`: ```json { "appName": "My Task Manager", "phase": "Implementation", "tools": ["list-tasks", "create-task"], "widgets": ["task-list"], "auth": false, "database": true, "validated": false, "deployed": false } ```
2. **显示进度** 显示当前状态: - 应用名称 - 当前阶段 - 已完成项(工具、小部件) - 待处理项(身份验证、验证、部署)
3. **提供后续步骤** 基于当前阶段: **概念阶段:** - "让我们设计工具和小部件" - "我们要开始实施吗?" **实施阶段:** - "添加另一个工具?" - "添加一个小部件?" - "设置身份验证?" - "设置数据库?" **测试阶段:** - "生成黄金提示?" - "运行验证?" - "运行测试?" **部署阶段:** - "部署到 Render?" - "配置 ChatGPT 连接器?"
4. **继续工作** 根据用户的选择,调用相应的工作流部分。
---
## 最佳实践
1. **在每个主要步骤后始终保存状态** 2. **在继续之前进行验证**(尤其是在部署之前) 3. **使用代理进行代码生成** (chatgpt-mcp-generator, chatgpt-auth-generator 等) 4. **在每个阶段进行测试**(预览小部件、测试工具、运行黄金提示) 5. **保持对话性** - 自然地引导用户完成工作流 6. **在选择时解释权衡** (Auth0 vs Supabase 等) 7. **在引入新概念时展示示例**
---
## 状态管理
`.chatgpt-app/state.json` 文件跟踪进度:
```json { "appName": "string", "description": "string", "phase": "Concept" | "Implementation" | "Testing" | "Deployment", "tools": ["tool-name"], "widgets": ["widget-id"], "auth": { "enabled": boolean, "provider": "auth0" | "supabase" | null }, "database": { "enabled": boolean, "entities": ["entity-name"] }, "validated": boolean, "tested": boolean, "deployed": boolean, "deploymentUrl": "string | null", "goldenPromptsGenerated": boolean, "lastUpdated": "ISO timestamp" } ```
---
## 命令参考
```bash # Setup ./setup.sh
# Development ./START.sh --dev # Dev mode with watch ./START.sh --preview # Open preview in browser ./START.sh --stdio # STDIO mode (testing) ./START.sh # Production mode
# Testing npm run validate # Type checking curl http://localhost:3000/health
# Deployment git push origin main # Trigger Render deploy ```
---
## 入门指南
当用户调用任何 chatgpt-app 命令时:
1. 检查 `.chatgpt-app/state.json` 是否存在 2. 如果存在 → 使用 **恢复应用** 工作流 3. 如果不存在 → 使用 **新建应用** 工作流
始终引导用户遵循自然流程: **概念 → 实施 → 测试 → 部署**