主导航

ChatGPT 中的 MCP Apps 兼容性

构建可在 ChatGPT 中运行的便携式 MCP Apps UI

概述

ChatGPT 支持用于嵌入式应用 UI 的 MCP Apps 开放标准。

MCP Apps UI 在 iframe 内运行,并通过标准桥接(基于 postMessageui/* JSON-RPC)与宿主进行通信。ChatGPT 实现了这一相同的 iframe 与桥接模型,因此您可以构建一次 UI,并在 ChatGPT 及其他支持 MCP Apps 的宿主中运行。

现有的 Apps SDK API 继续受支持,新的实验性功能将首先在 Apps SDK 中发布。OpenAI 协助塑造了基于 ChatGPT Apps 的 MCP Apps 标准,新功能在经过形态和功能验证后会纳入 MCP 规范中。

默认使用 MCP Apps 标准键(keys)和桥接进行构建。当需要 ChatGPT 特有功能时,请使用 window.openai

对于新应用(以及现有应用内的新 UI 界面),请从 MCP Apps 标准入手

  1. 声明您的 UI:使用 _meta.ui.resourceUri
  2. 使用标准宿主桥接(基于 postMessageui/* JSON-RPC)进行初始化、通知和宿主交互。

可选

  1. 分层添加 ChatGPT 扩展:仅当需要共享规范未涵盖的功能时,通过 window.openai 进行添加。

MCP Apps 宿主桥接 (ui/*)

MCP Apps 定义了一个标准的 iframe 桥接

  • 传输:基于 window.postMessage 的 JSON-RPC 2.0 消息
  • 命名空间:用于 UI 与宿主交互的 ui/* 方法和通知
  • 工具调用:使用 MCP 工具界面(例如 tools/call),而不是宿主特定的 UI 全局变量

这与 Apps SDK 的关系

Apps SDK 是构建和分发 ChatGPT Apps 的受支持方式。ChatGPT 同时实现了 MCP Apps UI 标准,因此您的 UI 可以跨支持 MCP Apps 的宿主运行。

在实践中

  • 当存在等效项时,使用 MCP Apps 标准键和桥接方法(_meta.ui.resourceUri, ui/*)。
  • 仅在需要 ChatGPT 特有功能时使用 OpenAI 扩展。

这类似于 Web 平台:厂商特定的 API 有助于尽早发布,但一旦标准存在,文档应优先引导使用标准格式。这是为了实现可移植性,而非弃用。

通过 window.openai 提供的可选 ChatGPT 扩展

某些功能是 ChatGPT 特有的。当使用它们时,请将其视为可选扩展,它们在 ChatGPT 中增强了功能,且不会妨碍您的 UI 在其他 MCP Apps 宿主中运行。

示例包括

  • 即时结账 (window.openai.requestCheckout)
  • 文件处理 (window.openai.uploadFile, window.openai.selectFiles, window.openai.getFileDownloadUrl)
  • 宿主模态框 (window.openai.requestModal)

迁移与映射指南

本节将常见的 Apps SDK 模式映射为对应的 MCP Apps 标准等效项。

工具元数据

目标MCP Apps 标准ChatGPT 兼容性别名
将工具链接到 UI 资源_meta.ui.resourceUri_meta["openai/outputTemplate"]

宿主桥接

目标MCP Apps 标准ChatGPT 扩展(可选)
接收工具输入ui/initialize + ui/notifications/tool-inputwindow.openai.toolInput
接收工具结果ui/notifications/tool-resultwindow.openai.toolOutput
从 UI 调用工具tools/callwindow.openai.callTool
发送后续消息ui/messagewindow.openai.sendFollowUpMessage
更新模型可见的 UI 上下文ui/update-model-contextwindow.openai.setWidgetState

围绕 MCP Apps 标准进行构建以实现可移植性,然后在需要提升 ChatGPT 体验的地方分层添加 ChatGPT 扩展。

扩展最佳实践

  • 功能检测:在调用扩展之前进行检测。
  • 优雅降级:当扩展不可用时进行优雅降级。
const openai = typeof window !== "undefined" ? window.openai : undefined;

if (openai?.requestModal) {
  await openai.requestModal({
    /* ... */
  });
} else {
  // Fallback behavior for hosts without this extension.
}
© . This website operates independently and is not affiliated with or endorsed by OpenAI, Inc. All brand names, logos, and trademarks are the property of their respective owners.