Appearance
ChatGPT Apps SDK 从理论到实践
本文档特点:
- 理论+实践结合: 每个官方概念都对照实际代码
- 精确定位: 标注代码行号,快速查找
- 避坑指南: 标注常见错误和正确做法
- 开箱即用: 完整代码可直接复制使用
适用人群:
- 准备开发ChatGPT App的开发者
- 需要理解Apps SDK工作原理的技术人员
- 想要快速上手MCP协议的工程师
一、架构对比
1.1 官方标准架构
根据OpenAI官方文档,Apps SDK的标准架构如下:
核心组件:
- ChatGPT客户端: 理解用户意图,决定何时调用工具
- MCP Server: 定义工具、提供Widget HTML、处理业务逻辑
- Skybridge iframe: 安全沙箱,运行Widget UI
- Widget: 自定义UI组件,可以是React/Vue/纯JS
1.2 本项目实现架构
本项目(YouTube视频学习助手)的实际架构:
1.3 数据流程详解
关键洞察:
- 数据不是预填充的,而是事件驱动推送
- ChatGPT通过
_meta字段知道要加载哪个Widget - Widget必须订阅
openai:set_globals事件才能接收数据
二、开发准备
2.1 官方要求
硬性要求:
- ChatGPT订阅账号
- Plus账号 - 可以使用Connectors和开发者模式
- Pro账号 - 可以使用Connectors和开发者模式
- Team账号 - 可以使用Connectors和开发者模式
- Enterprise账号 - 可以使用Connectors和开发者模式
- ❌ 免费账号 - 无法使用Connectors功能和开发者模式
- HTTPS端点
- 开发: 使用ngrok等隧道工具
- 生产: 部署到HTTPS域名
技术栈选择 (官方支持):
| 技术栈 | 官方SDK | 适用场景 |
|---|---|---|
| Python | @modelcontextprotocol/python-sdkFastMCP (第三方,推荐) | 快速原型、AI/ML集成 |
| TypeScript/Node.js | @modelcontextprotocol/sdk | 全栈JavaScript项目 |
| 其他语言 | 实现MCP协议即可 | Go、Rust等 |
2.2 本项目技术选型
后端:
- Python 3.11 + FastMCP 2.12.4
- HTTP with SSE (Server-Sent Events)
- 异步处理 (async/await)
前端:
- React 18 (使用
useSyncExternalStore) - esbuild (快速打包)
- 单文件HTML bundle
为什么选这个组合?
FastMCP优势:
- 官方推荐,社区活跃
- 自动处理MCP协议细节
- 内置工具装饰器,开发效率高
React 18优势:
useSyncExternalStoreHook专为订阅外部数据设计- 完美适配ChatGPT的事件驱动机制
- 生态成熟,组件丰富
⚠️ 重要限制:
- FastMCP的
ToolResult不支持_meta字段 - 必须混用低级MCP API返回
CallToolResult
三、产品定位与黄金问题集
3.1 官方方法论
什么是黄金问题集?
黄金问题集(Golden Prompt Set)是用于测试工具召回率和精确度的标准提示词列表。
为什么需要黄金问题集?
- ChatGPT通过工具的
description和instructions决定何时调用 - 精心设计的问题集可以持续验证工具是否被正确触发
- 避免误触发(精确度)和漏触发(召回率)
官方要求的三类提示词
直接提示词 (至少5个)
- 明确引用产品名称或关键动词
- 例如: "显示我的Jira看板"
间接提示词 (至少5个)
- 陈述目标但不提及工具
- 例如: "发布前我被什么阻碍了?"
负面提示词
- 不应该触发你的App
- 用于衡量精确度
3.2 本项目实践 ⭐
我们的产品定位
应用名称: Heliki Video Learning (YouTube视频学习助手)
核心用例: 快速理解YouTube视频内容
适合场景分类:
- 快速查询 - 视频元数据、统计数据
- 可视化展示 - 视频缩略图、评论列表
- 即时有价值 - 无需离开ChatGPT即可获取信息
匹配官方"良好用例"的条款:
- [x] 自然融入对话 (用户发YouTube链接时触发)
- [x] 有时间限制 (快速查看视频信息)
- [x] 提供即时有价值的信息 (标题、评论、时长)
- [x] 可视化总结 (卡片式展示)
我们的黄金问题集
直接提示词 (明确引用YouTube)
1. "分析这个YouTube视频 https://youtube.com/watch?v=xxx"
2. "这个YouTube视频讲了什么?"
3. "帮我看看这个视频的评论"
4. "提取这个视频的字幕"
5. "总结一下这个视频的内容"间接提示词 (不提YouTube,但意图明确)
1. "我想快速了解这个视频 [粘贴链接]"
2. "这个视频的评论怎么说?"
3. "视频主要讲了哪些要点?"
4. "有没有字幕可以看?"
5. "视频时长多久?"负面提示词 (不应触发)
1. "下载这个YouTube视频" (下载功能,不在范围)
2. "转换视频格式为MP4" (格式转换,不在范围)
3. "上传视频到YouTube" (上传功能,不在范围)
4. "YouTube的首页推荐有什么?" (推荐算法,不在范围)七、关键洞察总结
为什么这个实现生效?
三个关键突破:
理解了ChatGPT的事件驱动机制
- 数据不是预填充,而是通过
openai:set_globals事件异步推送 - 必须使用
useSyncExternalStore订阅事件
- 数据不是预填充,而是通过
绕过了FastMCP的限制
- FastMCP的
ToolResult不支持_meta字段 - 直接使用低级MCP API返回
CallToolResult
- FastMCP的
正确解析了数据格式
- ChatGPT传递的
toolOutput已经是解包后的数据 - 直接读取
toolOutput.video,不需要再找structuredContent
- ChatGPT传递的
易错点清单
| 错误 | 后果 | 正确做法 |
|---|---|---|
| 使用FastMCP的ToolResult | Widget无法加载 | 使用CallToolResult |
| 期待预填充数据 | toolOutput永远是null | 订阅openai:set_globals事件 |
| URI格式错误 | ChatGPT无法识别 | 使用ui://widget/前缀 |
| CSP只写域名 | 外部资源加载失败 | 使用完整HTTPS URL |
| 解析structuredContent | 数据读取失败 | 直接读取toolOutput.video |
八、参考资源
官方文档
- Apps SDK首页: https://developers.openai.com/apps-sdk
- 研究用例: https://developers.openai.com/apps-sdk/plan/use-case
- 应用设计指南: https://developers.openai.com/apps-sdk/concepts/design-guidelines
- 设置MCP服务器: https://developers.openai.com/apps-sdk/build/mcp-server
- 构建自定义UX: https://developers.openai.com/apps-sdk/build/custom-ux
官方示例
- OpenAI Apps SDK Examples: https://github.com/openai/openai-apps-sdk-examples
- Pizzaz Server (Python): 参考CallToolResult的正确用法
技术文档
- MCP Protocol: https://spec.modelcontextprotocol.io/
- React useSyncExternalStore: https://react.dev/reference/react/useSyncExternalStore
最后更新: 2025-10-20 作者: 暴躁哐哐Heliki AI社区 项目: heliki-video-learning
反馈和讨论:
