Приложения для ChatGPT на Apps SDK
Создаёт каркас и код приложения для ChatGPT: MCP-сервер с инструментами и виджетом, по актуальной документации, с проверкой и запуском в режиме разработчика.
- Что делает
- Создаёт каркас и код приложения для ChatGPT: MCP-сервер с инструментами и виджетом, по актуальной документации, с проверкой и запуском в режиме разработчика.
- Когда брать
- Когда нужно создать, переделать или отладить приложение на ChatGPT Apps SDK с MCP-сервером и виджетом либо подготовить его к публикации.
- Когда не брать
- Если нужно приложение не для ChatGPT или не требуется MCP-сервер.
- Пример запроса
- Сделай каркас приложения для ChatGPT, которое ищет заметки и показывает их виджетом, с MCP-сервером на TypeScript.
- Нужно подключить
- терминал, репозиторий с кодом, Node.js
- Работает лучше с
- доступ к документации OpenAI (скилл openai-docs), ngrok для проверки в ChatGPT
Как включить
- Скачайте архив и распакуйте его.
- Положите папку
chatgpt-appsв~/.agents/skills/. - Вызовите скилл командой
$chatgpt-appsили найдите его через/skills.
Текст
---
name: chatgpt-apps
description: Создавай, подготавливай каркас, рефактори и отлаживай приложения на ChatGPT Apps SDK, сочетающие MCP-сервер и интерфейс-виджет. Используй, когда Codex нужно спроектировать инструменты, зарегистрировать ресурсы интерфейса, подключить мост MCP Apps или API совместимости ChatGPT, применить метаданные Apps SDK, CSP или настройки домена, либо получить каркас проекта, соответствующий документации. Предпочитай процесс «сначала документация»: перед генерацией кода вызови скилл openai-docs или инструменты MCP документации для разработчиков OpenAI.
---
ChatGPT Apps
Обзор
Создавай каркас реализаций ChatGPT Apps SDK по принципу «сначала документация, сначала пример», а затем генерируй код, следующий актуальным шаблонам Apps SDK и моста MCP Apps.
Используй этот скилл, чтобы получить:
- Определение основного архетипа приложения и решение о структуре репозитория
- План инструментов (названия, схемы, аннотации, результаты)
- Рекомендацию по исходной точке из внешних источников (официальный пример, пример ext-apps или локальный запасной каркас)
- Каркас MCP-сервера (регистрация ресурсов, обработчики инструментов, метаданные)
- Каркас виджета (сначала мост MCP Apps, затем совместимость и расширения
window.openai) - Повторно используемый стартовый каркас на Node +
@modelcontextprotocol/ext-appsдля запасных вариантов с минимумом зависимостей - Отчёт о проверке по минимальному контракту рабочего репозитория
- Шаги локальной разработки и подключения коннектора
- Краткую сводку для заинтересованных лиц о том, что делает приложение (по запросу)
Обязательный процесс «сначала документация»
Всегда используй $openai-docs первым, когда создаёшь или меняешь приложение на ChatGPT Apps SDK.
- Вызови
$openai-docs(предпочтительно) или обратись к MCP-серверу документации OpenAI напрямую. - Перед написанием кода получи актуальную документацию Apps SDK, особенно (базовые страницы):
apps-sdk/build/mcp-serverapps-sdk/build/chatgpt-uiapps-sdk/build/examplesapps-sdk/plan/toolsapps-sdk/reference- Получи
apps-sdk/quickstart, когда создаёшь каркас нового приложения или делаешь первую версию реализации, и проверь репозиторий или страницу официальных примеров, прежде чем придумывать каркас с нуля. - Получи документацию по развёртыванию и подаче заявки, если задача включает локальное тестирование в ChatGPT, хостинг или публичный запуск:
apps-sdk/deployapps-sdk/deploy/submissionapps-sdk/app-submission-guidelines- Ссылайся на URL документации, которой пользовался, когда объясняешь проектные решения или сгенерированные каркасы.
- Если актуальная документация и старые шаблоны репозитория расходятся, предпочитай документацию и прямо указывай на псевдонимы совместимости.
- Если поиск по документации обрывается по тайм-ауту или даёт плохие совпадения, получи канонические страницы Apps SDK напрямую по URL и продолжай; не позволяй сбою поиска блокировать создание каркаса.
Если $openai-docs недоступен, используй:
mcp__openaiDeveloperDocs__search_openai_docsmcp__openaiDeveloperDocs__fetch_openai_doc
Прочитай references/apps-sdk-docs-workflow.md: там предлагаемые запросы к документации и краткий контрольный список. Прочитай references/app-archetypes.md, чтобы отнести запрос к одной из небольшого числа поддерживаемых форм приложений, прежде чем выбирать примеры или каркасы. Прочитай references/repo-contract-and-validation.md, когда создаёшь или проверяешь репозиторий, чтобы результат оставался в рамках стабильного контракта «рабочего приложения». Прочитай references/search-fetch-standard.md, когда приложение похоже на коннектор, работает только с данными, ориентировано на синхронизацию или должно хорошо работать со знаниями компании или глубоким исследованием. Прочитай references/upstream-example-workflow.md, когда начинаешь приложение с нуля или решаешь, адаптировать ли внешний пример или использовать локальный запасной каркас. Прочитай references/window-openai-patterns.md, когда задаче нужно поведение виджета, специфичное для ChatGPT, или когда переносишь примеры из репозиториев, использующие вспомогательные функции-обёртки app.*.
Рекомендации по промтам
Используй промты, которые прямо связывают этот скилл с $openai-docs, чтобы итоговый каркас опирался на актуальную документацию.
Предпочтительные шаблоны промтов:
Используй $chatgpt-apps вместе с $openai-docs, чтобы создать каркас приложения ChatGPT для <use case> с MCP-сервером на <TS/Python> и виджетом на <React/vanilla>.Используй $chatgpt-apps вместе с $openai-docs, чтобы адаптировать ближайший официальный пример Apps SDK в приложение ChatGPT для <use case>.Используй $chatgpt-apps и $openai-docs, чтобы переделать это демо Apps SDK в производственную структуру с аннотациями инструментов, CSP и версионированием URI.Используй $chatgpt-apps вместе с $openai-docs, чтобы сначала спланировать инструменты, а затем сгенерировать код MCP-сервера и виджета.
Отвечая, перед написанием кода запроси или выведи эти вводные:
- Сценарий использования и основные пользовательские потоки
- Инструменты только для чтения или изменяющие данные
- Цель: демо или производство
- Частное или внутреннее использование или подача в публичный каталог
- Язык серверной части и стек интерфейса
- Требования к авторизации
- Домены внешних API для списков разрешений CSP
- Целевой хостинг и подход к локальной разработке
- Готовность организации к владению и проверке (для задач с подачей заявки)
Классифицируй приложение, прежде чем выбирать код
Прежде чем выбирать примеры, структуру репозитория или каркасы, отнеси запрос к одному основному архетипу и назови его.
tool-onlyvanilla-widgetreact-widgetinteractive-decoupledsubmission-ready
Выводи архетип, если только недостающая деталь действительно не блокирует работу. Используй архетип, чтобы выбрать:
- нужен ли интерфейс вообще
- сохранять ли раздельную структуру
server/+web/ - что предпочесть: официальные примеры OpenAI, примеры ext-apps или локальный запасной каркас
- какие проверки важнее всего
- должны ли
searchиfetchбыть набором инструментов только для чтения по умолчанию
Критерии выбора — в references/app-archetypes.md.
Порядок исходных точек по умолчанию
Для приложений с нуля предпочитай такие исходные точки по порядку:
- Официальные примеры OpenAI, когда близкий пример уже соответствует запрошенному стеку или шаблону взаимодействия.
- **Примеры
@modelcontextprotocol/ext-apps, соответствующие версии**, когда пользователю нужна более низкоуровневая или более переносимая основа MCP Apps. - **
scripts/scaffold_node_ext_apps.mjs** — только когда подходящего близкого примера нет, пользователь хочет крошечную заготовку на Node с простым HTML или нежелательны доступ к сети и получение примеров.
Не генерируй большой собственный каркас с нуля, если близкий внешний пример уже существует. Скопируй самый подходящий небольшой пример, удали посторонний демонстрационный код, затем подгони его под актуальную документацию и запрос пользователя.
Порядок сборки
0. Определи архетип приложения
Выбери один основной архетип до планирования инструментов и выбора исходной точки.
- Предпочитай один основной архетип, а не смесь нескольких.
- Если запрос широкий, выведи самый маленький архетип, который всё же его удовлетворяет.
- Переходи к
submission-readyтолько когда пользователь просит публичный запуск, подачу в каталог или развёртывание, готовое к проверке. - Назови выбранный архетип в ответе, чтобы пользователь мог при необходимости поправить его на раннем этапе.
1. Спланируй инструменты до кода
Определи набор инструментов по намерениям пользователя.
- Одна задача — один инструмент.
- Пиши описания инструментов, начинающиеся с поведенческих подсказок «Используй это, когда…».
- Делай входные данные явными и удобными для машин (перечисления, обязательные поля, границы).
- Реши, является ли каждый инструмент только данными, только отрисовкой или и тем и другим.
- Задавай аннотации точно (
readOnlyHint,destructiveHint,openWorldHint; добавляйidempotentHint, когда это верно). - Если приложение похоже на коннектор, работает только с данными, ориентировано на синхронизацию или предназначено для знаний компании или глубокого исследования, по умолчанию используй стандартные инструменты
searchиfetch, а не придумывай собственные аналоги только для чтения. - Для учебных и демонстрационных приложений предпочитай одну идею на инструмент, чтобы модель могла чётко выбрать подходящий пример.
- Группируй демонстрационные инструменты по учебной цели: данные в виджет, действия виджета обратно в разговор или инструменты, сигналы о среде хоста и раскладки, поведение жизненного цикла и потоковой передачи.
Прочитай references/search-fetch-standard.md, когда могут быть уместны search и fetch.
2. Выбери архитектуру приложения
Выбери самую простую структуру, подходящую для цели.
- Используй минимальный демонстрационный шаблон для быстрых прототипов, семинаров или проверки концепции.
- Используй шаблон с разделением данных и отрисовки для производственного интерфейса, чтобы виджет не перерисовывался при каждом вызове инструмента.
Для нетривиальных приложений предпочитай шаблон с разделением:
- Инструменты данных возвращают повторно используемый
structuredContent. - Инструменты отрисовки прикрепляют
_meta.ui.resourceUriи необязательный_meta["openai/outputTemplate"]. - Описания инструментов отрисовки указывают предварительные условия (например, «Сначала вызови
search»).
2a. Начни с внешнего примера, если подходящий есть
Для работы с нуля по умолчанию опирайся на внешние примеры, когда они близки к запрошенному приложению.
- Сначала проверь официальные примеры OpenAI для приложений, обращённых к ChatGPT, отточенных шаблонов интерфейса, компонентов React, потоков загрузки файлов, потоков с модальными окнами или приложений, похожих на примеры из документации.
- Используй примеры
@modelcontextprotocol/ext-apps, когда запрос ближе к «сырой» связке моста и сервера MCP Apps или когда шаблоны пакетов, соответствующие версии, важнее отточенности под ChatGPT. - Выбери самый подходящий небольшой пример и скопируй только нужные файлы; не переноси целое демонстрационное приложение без изменений.
- После копирования приведи пример в соответствие с полученной актуальной документацией: названиями и описаниями инструментов, аннотациями,
_meta.ui.*, CSP, версионированием URI и инструкциями локального запуска. - Одним предложением укажи, какой пример выбрал и почему.
Критерии выбора и адаптации — в references/upstream-example-workflow.md.
2b. Используй стартовый скрипт, когда полезен запасной вариант с минимумом зависимостей
Используй scripts/scaffold_node_ext_apps.mjs только когда пользователю нужна быстрая заготовка на Node с нуля, простой HTML-виджет подходит, и ни один внешний пример не является лучшей исходной точкой.
- Запускай его только после получения актуальной документации, затем приведи сгенерированные файлы в соответствие с ней.
- Если выбираешь скрипт вместо внешнего примера, объясни, почему запасной вариант лучше для этого запроса.
- Пропускай его, когда есть близкий официальный пример, когда у пользователя уже есть структура приложения, когда нужен стек не на Node, когда он прямо хочет сначала React или когда нужен только план или проверка, а не код.
- Скрипт генерирует минимальный сервер
@modelcontextprotocol/ext-appsи виджет на простом HTML, который по умолчанию использует мост MCP Apps. - Сгенерированный виджет оставляет последующие сообщения на стандартном мосту
ui/messageи используетwindow.openaiтолько для необязательных сигналов хоста и расширений. - После запуска подгони сгенерированный результат под актуальную документацию и запрос пользователя: поправь названия и описания инструментов, аннотации, метаданные ресурсов, версионирование URI и README с инструкциями по запуску.
3. Создай каркас MCP-сервера
Сгенерируй сервер, который:
- Регистрирует ресурс или шаблон виджета с MIME-типом интерфейса MCP Apps (
text/html;profile=mcp-app) или константой SDK (RESOURCE_MIME_TYPE) при использовании@modelcontextprotocol/ext-apps/server - Регистрирует инструменты с понятными названиями, схемами, заголовками и описаниями
- Осознанно возвращает
structuredContent(для модели и виджета),content(пояснения для модели) и_meta(данные только для виджета) - Делает обработчики идемпотентными или явно документирует неидемпотентное поведение
- Включает строки статуса инструментов (
openai/toolInvocation/*), когда это полезно в ChatGPT
Держи structuredContent кратким. Крупные или чувствительные данные, нужные только виджету, переноси в _meta.
4. Создай каркас интерфейса виджета
Сначала используй мост MCP Apps ради переносимости, затем добавляй специфичные для ChatGPT API window.openai, когда они ощутимо улучшают взаимодействие.
- Слушай
ui/notifications/tool-result(JSON-RPC поверхpostMessage) - Отрисовывай по
structuredContent - Используй
tools/callдля вызовов инструментов, инициированных компонентом - Используй
ui/update-model-contextтолько когда состояние интерфейса должно менять то, что видит модель
Используй window.openai для совместимости и расширений (загрузка файлов, модальные окна, режим отображения и т. д.), а не как единственный путь интеграции для новых приложений.
Ограничения по поверхности API
- Некоторые примеры оборачивают мост объектом
app(например,@modelcontextprotocol/ext-apps/react) и предоставляют вспомогательные имена вродеapp.sendMessage(),app.callServerTool(),app.openLink()или методы получения данных хоста. - Считай такие обёртки деталями реализации или удобным слоем, а не каноническим публичным API, которому нужно учить по умолчанию.
- В рекомендациях для ChatGPT предпочитай актуальную документированную поверхность:
window.openai.callTool(...),window.openai.sendFollowUpMessage(...),window.openai.openExternal(...),window.openai.requestDisplayMode(...)и прямые глобальные значения вродеwindow.openai.theme,window.openai.locale,window.openai.displayMode,window.openai.toolInput,window.openai.toolOutput,window.openai.toolResponseMetadataиwindow.openai.widgetState. - Если ссылаешься на вспомогательные функции-обёртки из примеров репозиториев, сопоставляй их с документированными примитивами
window.openaiили моста MCP Apps и подчёркивай, что обёртка не является нормативной поверхностью API. - Используй
references/window-openai-patterns.mdдля сопоставления обёрток с каноническим API и для шаблонов выделения вспомогательных функций React.
5. Добавь метаданные ресурса и безопасность
Задавай метаданные ресурса виджета или шаблона осознанно:
_meta.ui.cspс точнымиconnectDomainsиresourceDomains_meta.ui.domainдля развёртываний, готовых к подаче заявки_meta.ui.prefersBorder(или псевдоним совместимости OpenAI при необходимости)- Необязательный
openai/widgetDescription, чтобы сократить лишние пояснения
Избегай frameDomains, если встраивание iframe не является основой продукта.
5a. Обеспечь минимальный контракт рабочего репозитория
Каждый сгенерированный репозиторий должен выполнять небольшой стабильный контракт, прежде чем ты сочтёшь работу законченной.
- Структура репозитория соответствует выбранному архетипу.
- MCP-сервер и инструменты подключены к доступной конечной точке
/mcp. - У инструментов понятные описания, точные аннотации и метаданные интерфейса, где они нужны.
- Приложения в духе коннектора, работающие только с данными, ориентированные на синхронизацию и в духе знаний компании используют стандартные формы инструментов
searchиfetch, когда это уместно. - Виджет правильно использует мост MCP Apps, когда есть интерфейс.
- В репозитории достаточно скриптов или команд, чтобы пользователь мог запустить и проверить его локально.
- В ответе прямо сказано, какая проверка была выполнена, а какая нет.
Подробный контрольный список и лестницу проверок смотри в references/repo-contract-and-validation.md.
6. Проверь локальный цикл
Проверяй по минимальному контракту рабочего репозитория, а не только «созданы ли файлы».
- Сначала выполняй самые дешёвые проверки:
- статический разбор контракта
- проверки синтаксиса или компиляции, когда это возможно
- локальную проверку работоспособности
/mcp, когда это возможно - Затем переходи к проверкам во время выполнения:
- проверь описания инструментов и отрисовку виджета в MCP Inspector
- протестируй приложение в режиме разработчика ChatGPT через HTTPS-туннель
- проверь повторные попытки и повторные вызовы инструментов, чтобы подтвердить идемпотентное поведение
- проверь обновления виджета после событий хоста и последующих вызовов инструментов
- Если ты сдаёшь только каркас и не устанавливаешь зависимости, всё равно выполни дешёвые проверки и точно скажи, что не запускал.
Лестницу проверок смотри в references/repo-contract-and-validation.md.
7. Подключи и протестируй в ChatGPT (режим разработчика)
Для локальной разработки включи явные шаги настройки ChatGPT (а не только код и команды запуска).
- Запусти MCP-сервер локально на
http://localhost:<port>/mcp - Открой локальный сервер через публичный HTTPS-туннель (например,
ngrok http <port>) - При подключении из ChatGPT используй HTTPS-адрес туннеля плюс путь
/mcp - В ChatGPT включи режим разработчика в разделе Settings → Apps & Connectors → Advanced settings
- В настройках приложений ChatGPT создай новое приложение для удалённого MCP-сервера и вставь публичный URL MCP
- Скажи пользователям обновить приложение после изменений инструментов или метаданных MCP, чтобы ChatGPT перезагрузил актуальные описания
Примечание: в некоторых материалах документации и на скриншотах ещё встречается старая терминология «коннектор». Предпочитай актуальную формулировку продукта («приложение», app), но в пошаговых инструкциях упоминай оба названия.
8. Спланируй рабочий хостинг и развёртывание
Когда пользователь просит развернуть или подготовить к запуску, подготовь рекомендации по хостингу MCP-сервера (и ресурсов виджета, если они размещаются отдельно).
- Размещай за стабильной публичной HTTPS-конечной точкой (не туннелем) с надёжным TLS
- Сохраняй низкую задержку потоковой передачи на
/mcp - Храни секреты вне репозитория (переменные окружения или менеджер секретов)
- Добавь журналирование, отслеживание задержки запросов и видимость ошибок для вызовов инструментов
- Добавь базовую наблюдаемость (процессор, память, объём запросов) и путь разбора неполадок
- Перед подачей заявки заново протестируй размещённую конечную точку в режиме разработчика ChatGPT
9. Подготовь подачу заявки и публикацию (только для публичных приложений)
Включай эти шаги только когда пользователь намерен попасть в публичный каталог.
- Используй
apps-sdk/deploy/submissionдля процесса подачи иapps-sdk/app-submission-guidelinesдля требований проверки - Частные и внутренние приложения оставляй в режиме разработчика, а не подавай на проверку
- Перед работой над подачей подтверди проверку организации и предварительные условия роли владельца
- Убедись, что MCP-сервер использует публичную рабочую конечную точку (без localhost и тестовых URL) и что для него настроена CSP, готовая к подаче
- Подготовь материалы для подачи: метаданные приложения, логотип и скриншоты, URL политики конфиденциальности, контакт поддержки, тестовые промты и ответы, сведения о локализации
- Если нужна авторизация, добавь безопасные для проверки демонстрационные учётные данные и проверь путь входа от начала до конца
- Отправь на проверку в панели платформы, следи за статусом проверки и публикуй только после одобрения
Рекомендации по интерактивному состоянию
Прочитай references/interactive-state-sync-patterns.md, когда у приложения долгоживущее состояние виджета, повторяющиеся взаимодействия или вызовы инструментов, инициированные компонентом (например, игры, доски, карты, дашборды, редакторы).
Используй его, чтобы выбрать шаблоны для:
- Снимков состояния плюс монотонных маркеров событий (
stateVersion,resetCountи т. п.) - Идемпотентных обработчиков, безопасных при повторе
- Разделения
structuredContentи_meta - Потоков обновления с мостом MCP Apps в приоритете и необязательной совместимостью с
window.openai - Архитектуры инструментов с разделением данных и отрисовки для более сложных интерактивных приложений
Ожидаемый результат
Когда используешь этот скилл для создания кода каркаса, выдавай результат в таком порядке, если пользователь не просит иначе:
- При прямых запросах на каркас не останавливайся на плане: дай краткий план и сразу создай файлы.
- Выбранный основной архетип приложения и почему
- План инструментов и выбор архитектуры (минимальная или с разделением)
- Выбранная исходная точка из внешних источников (официальный пример, пример ext-apps или локальный запасной каркас) и почему
- Страницы и URL документации, использованные из
$openai-docs - Дерево файлов для создания или изменения
- Реализация (сервер + виджет)
- Проверка, выполненная по минимальному контракту рабочего репозитория
- Инструкции по локальному запуску и тестированию (включая туннель и настройку приложения в режиме разработчика ChatGPT)
- Рекомендации по развёртыванию и хостингу (если запрошены или подразумеваются)
- Контрольный список готовности к подаче (для запросов на публичный запуск)
- Риски, пробелы и дальнейшие улучшения
Справочные материалы
references/app-archetypes.md— отнесение запросов к небольшому числу поддерживаемых форм приложенийreferences/apps-sdk-docs-workflow.md— запросы к документации, целевые страницы и контрольный список генерации кодаreferences/interactive-state-sync-patterns.md— повторно используемые шаблоны для приложений с состоянием и сильной интерактивностьюreferences/repo-contract-and-validation.md— минимальный контракт рабочего репозитория и лёгкая лестница проверокreferences/search-fetch-standard.md— когда и как по умолчанию использовать стандартные инструментыsearchиfetchreferences/upstream-example-workflow.md— выбор между официальными примерами, примерами ext-apps и локальным запасным каркасомreferences/window-openai-patterns.md— специфичные для ChatGPT расширения, перевод API-обёрток и шаблоны вспомогательных функций Reactscripts/scaffold_node_ext_apps.mjs— минимальный запасной стартовый каркас на Node +@modelcontextprotocol/ext-apps
Перевод: iiuniversitet. Оригинал: https://github.com/openai/skills/tree/main/skills/.curated/chatgpt-apps, лицензия Apache-2.0. Изменения: перевод на русский язык.
Оригинал на английском
---
name: chatgpt-apps
description: Build, scaffold, refactor, and troubleshoot ChatGPT Apps SDK applications that combine an MCP server and widget UI. Use when Codex needs to design tools, register UI resources, wire the MCP Apps bridge or ChatGPT compatibility APIs, apply Apps SDK metadata or CSP or domain settings, or produce a docs-aligned project scaffold. Prefer a docs-first workflow by invoking the openai-docs skill or OpenAI developer docs MCP tools before generating code.
---
# ChatGPT Apps
## Overview
Scaffold ChatGPT Apps SDK implementations with a docs-first, example-first workflow, then generate code that follows current Apps SDK and MCP Apps bridge patterns.
Use this skill to produce:
- A primary app-archetype classification and repo-shape decision
- A tool plan (names, schemas, annotations, outputs)
- An upstream starting-point recommendation (official example, ext-apps example, or local fallback scaffold)
- An MCP server scaffold (resource registration, tool handlers, metadata)
- A widget scaffold (MCP Apps bridge first, `window.openai` compatibility/extensions second)
- A reusable Node + `@modelcontextprotocol/ext-apps` starter scaffold for low-dependency fallbacks
- A validation report against the minimum working repo contract
- Local dev and connector setup steps
- A short stakeholder summary of what the app does (when requested)
## Mandatory Docs-First Workflow
Use `$openai-docs` first whenever building or changing a ChatGPT Apps SDK app.
1. Invoke `$openai-docs` (preferred) or call the OpenAI docs MCP server directly.
2. Fetch current Apps SDK docs before writing code, especially (baseline pages):
- `apps-sdk/build/mcp-server`
- `apps-sdk/build/chatgpt-ui`
- `apps-sdk/build/examples`
- `apps-sdk/plan/tools`
- `apps-sdk/reference`
3. Fetch `apps-sdk/quickstart` when scaffolding a new app or generating a first-pass implementation, and check the official examples repo/page before inventing a scaffold from scratch.
4. Fetch deployment/submission docs when the task includes local ChatGPT testing, hosting, or public launch:
- `apps-sdk/deploy`
- `apps-sdk/deploy/submission`
- `apps-sdk/app-submission-guidelines`
5. Cite the docs URLs you used when explaining design choices or generated scaffolds.
6. Prefer current docs guidance over older repo patterns when they differ, and call out compatibility aliases explicitly.
7. If doc search times out or returns poor matches, fetch the canonical Apps SDK pages directly by URL and continue; do not let search failure block scaffolding.
If `$openai-docs` is unavailable, use:
- `mcp__openaiDeveloperDocs__search_openai_docs`
- `mcp__openaiDeveloperDocs__fetch_openai_doc`
Read `references/apps-sdk-docs-workflow.md` for suggested doc queries and a compact checklist.
Read `references/app-archetypes.md` to classify the request into a small number of supported app shapes before choosing examples or scaffolds.
Read `references/repo-contract-and-validation.md` when generating or reviewing a repo so the output stays inside a stable “working app” contract.
Read `references/search-fetch-standard.md` when the app is connector-like, data-only, sync-oriented, or meant to work well with company knowledge or deep research.
Read `references/upstream-example-workflow.md` when starting a greenfield app or when deciding whether to adapt an upstream example or use the local fallback scaffold.
Read `references/window-openai-patterns.md` when the task needs ChatGPT-specific widget behavior or when translating repo examples that use wrapper-specific `app.*` helpers.
## Prompt Guidance
Use prompts that explicitly pair this skill with `$openai-docs` so the resulting scaffold is grounded in current docs.
Preferred prompt patterns:
- `Use $chatgpt-apps with $openai-docs to scaffold a ChatGPT app for <use case> with a <TS/Python> MCP server and <React/vanilla> widget.`
- `Use $chatgpt-apps with $openai-docs to adapt the closest official Apps SDK example into a ChatGPT app for <use case>.`
- `Use $chatgpt-apps and $openai-docs to refactor this Apps SDK demo into a production-ready structure with tool annotations, CSP, and URI versioning.`
- `Use $chatgpt-apps with $openai-docs to plan tools first, then generate the MCP server and widget code.`
When responding, ask for or infer these inputs before coding:
- Use case and primary user flows
- Read-only vs mutating tools
- Demo vs production target
- Private/internal use vs public directory submission
- Backend language and UI stack
- Auth requirements
- External API domains for CSP allowlists
- Hosting target and local dev approach
- Org ownership/verification readiness (for submission tasks)
## Classify The App Before Choosing Code
Before choosing examples, repo shape, or scaffolds, classify the request into one primary archetype and state it.
- `tool-only`
- `vanilla-widget`
- `react-widget`
- `interactive-decoupled`
- `submission-ready`
Infer the archetype unless a missing detail is truly blocking. Use the archetype to choose:
- whether a UI is needed at all
- whether to preserve a split `server/` + `web/` layout
- whether to prefer official OpenAI examples, ext-apps examples, or the local fallback scaffold
- which validation checks matter most
- whether `search` and `fetch` should be the default read-only tool surface
Read `references/app-archetypes.md` for the decision rubric.
## Default Starting-Point Order
For greenfield apps, prefer these starting points in order:
1. **Official OpenAI examples** when a close example already matches the requested stack or interaction pattern.
2. **Version-matched `@modelcontextprotocol/ext-apps` examples** when the user needs a lower-level or more portable MCP Apps baseline.
3. **`scripts/scaffold_node_ext_apps.mjs`** only when no close example fits, the user wants a tiny Node + vanilla starter, or network access/example retrieval is undesirable.
Do not generate a large custom scaffold from scratch if a close upstream example already exists.
Copy the smallest matching example, remove unrelated demo code, then patch it to the current docs and the user request.
## Build Workflow
### 0. Classify The App Archetype
Pick one primary archetype before planning tools or choosing a starting point.
- Prefer a single primary archetype instead of mixing several.
- If the request is broad, infer the smallest archetype that can still satisfy it.
- Escalate to `submission-ready` only when the user asks for public launch, directory submission, or review-ready deployment.
- Call out the chosen archetype in your response so the user can correct it early if needed.
### 1. Plan Tools Before Code
Define the tool surface area from user intents.
- Use one job per tool.
- Write tool descriptions that start with "Use this when..." behavior cues.
- Make inputs explicit and machine-friendly (enums, required fields, bounds).
- Decide whether each tool is data-only, render-only, or both.
- Set annotations accurately (`readOnlyHint`, `destructiveHint`, `openWorldHint`; add `idempotentHint` when true).
- If the app is connector-like, data-only, sync-oriented, or intended for company knowledge or deep research, default to the standard `search` and `fetch` tools instead of inventing custom read-only equivalents.
- For educational/demo apps, prefer one concept per tool so the model can pick the right example cleanly.
- Group demo tools by learning objective: data into the widget, widget actions back into the conversation or tools, host/layout environment signals, and lifecycle/streaming behavior.
Read `references/search-fetch-standard.md` when `search` and `fetch` may be relevant.
### 2. Choose an App Architecture
Choose the simplest structure that fits the goal.
- Use a **minimal demo pattern** for quick prototypes, workshops, or proofs of concept.
- Use a **decoupled data/render pattern** for production UX so the widget does not re-render on every tool call.
Prefer the decoupled pattern for non-trivial apps:
- Data tools return reusable `structuredContent`.
- Render tools attach `_meta.ui.resourceUri` and optional `_meta["openai/outputTemplate"]`.
- Render tool descriptions state prerequisites (for example, "Call `search` first").
### 2a. Start From An Upstream Example When One Fits
Default to upstream examples for greenfield work when they are close to the requested app.
- Check the official OpenAI examples first for ChatGPT-facing apps, polished UI patterns, React components, file upload flows, modal flows, or apps that resemble the docs examples.
- Use `@modelcontextprotocol/ext-apps` examples when the request is closer to raw MCP Apps bridge/server wiring, or when version-matched package patterns matter more than ChatGPT-specific polish.
- Pick the smallest matching example and copy only the relevant files; do not transplant an entire showcase app unchanged.
- After copying, reconcile the example with the current docs you fetched: tool names/descriptions, annotations, `_meta.ui.*`, CSP, URI versioning, and local run instructions.
- State which example you chose and why in one sentence.
Read `references/upstream-example-workflow.md` for the selection and adaptation rubric.
### 2b. Use the Starter Script When a Low-Dependency Fallback Helps
Use `scripts/scaffold_node_ext_apps.mjs` only when the user wants a quick, greenfield Node starter and a vanilla HTML widget is acceptable, and no upstream example is a better starting point.
- Run it only after fetching current docs, then reconcile the generated files with the docs you fetched.
- If you choose the script instead of an upstream example, say why the fallback is better for that request.
- Skip it when a close official example exists, when the user already has an existing app structure, when they need a non-Node stack, when they explicitly want React first, or when they only want a plan/review instead of code.
- The script generates a minimal `@modelcontextprotocol/ext-apps` server plus a vanilla HTML widget that uses the MCP Apps bridge by default.
- The generated widget keeps follow-up messaging on the standard `ui/message` bridge and only uses `window.openai` for optional host signals/extensions.
- After running it, patch the generated output to match the current docs and the user request: adjust tool names/descriptions, annotations, resource metadata, URI versioning, and README/run instructions.
### 3. Scaffold the MCP Server
Generate a server that:
- Registers a widget resource/template with the MCP Apps UI MIME type (`text/html;profile=mcp-app`) or the SDK constant (`RESOURCE_MIME_TYPE`) when using `@modelcontextprotocol/ext-apps/server`
- Registers tools with clear names, schemas, titles, and descriptions
- Returns `structuredContent` (model + widget), `content` (model narration), and `_meta` (widget-only data) intentionally
- Keeps handlers idempotent or documents non-idempotent behavior explicitly
- Includes tool status strings (`openai/toolInvocation/*`) when helpful in ChatGPT
Keep `structuredContent` concise. Move large or sensitive widget-only payloads to `_meta`.
### 4. Scaffold the Widget UI
Use the MCP Apps bridge first for portability, then add ChatGPT-specific `window.openai` APIs when they materially improve UX.
- Listen for `ui/notifications/tool-result` (JSON-RPC over `postMessage`)
- Render from `structuredContent`
- Use `tools/call` for component-initiated tool calls
- Use `ui/update-model-context` only when UI state should change what the model sees
Use `window.openai` for compatibility and extensions (file upload, modal, display mode, etc.), not as the only integration path for new apps.
#### API Surface Guardrails
- Some examples wrap the bridge with an `app` object (for example, `@modelcontextprotocol/ext-apps/react`) and expose helper names like `app.sendMessage()`, `app.callServerTool()`, `app.openLink()`, or host getter methods.
- Treat those wrappers as implementation details or convenience layers, not the canonical public API to teach by default.
- For ChatGPT-facing guidance, prefer the current documented surface: `window.openai.callTool(...)`, `window.openai.sendFollowUpMessage(...)`, `window.openai.openExternal(...)`, `window.openai.requestDisplayMode(...)`, and direct globals like `window.openai.theme`, `window.openai.locale`, `window.openai.displayMode`, `window.openai.toolInput`, `window.openai.toolOutput`, `window.openai.toolResponseMetadata`, and `window.openai.widgetState`.
- If you reference wrapper helpers from repo examples, map them back to the documented `window.openai` or MCP Apps bridge primitives and call out that the wrapper is not the normative API surface.
- Use `references/window-openai-patterns.md` for the wrapper-to-canonical mapping and for React helper extraction patterns.
### 5. Add Resource Metadata and Security
Set resource metadata deliberately on the widget resource/template:
- `_meta.ui.csp` with exact `connectDomains` and `resourceDomains`
- `_meta.ui.domain` for app submission-ready deployments
- `_meta.ui.prefersBorder` (or OpenAI compatibility alias when needed)
- Optional `openai/widgetDescription` to reduce redundant narration
Avoid `frameDomains` unless iframe embeds are core to the product.
### 5a. Enforce A Minimum Working Repo Contract
Every generated repo should satisfy a small, stable contract before you consider it done.
- The repo shape matches the chosen archetype.
- The MCP server and tools are wired to a reachable `/mcp` endpoint.
- Tools have clear descriptions, accurate annotations, and UI metadata where needed.
- Connector-like, data-only, sync-oriented, and company-knowledge-style apps use the standard `search` and `fetch` tool shapes when relevant.
- The widget uses the MCP Apps bridge correctly when a UI exists.
- The repo includes enough scripts or commands for a user to run and check it locally.
- The response explicitly says what validation was run and what was not run.
Read `references/repo-contract-and-validation.md` for the detailed checklist and validation ladder.
### 6. Validate the Local Loop
Validate against the minimum working repo contract, not just “did files get created.”
- Run the lowest-cost checks first:
- static contract review
- syntax or compile checks when feasible
- local `/mcp` health check when feasible
- Then move up to runtime checks:
- verify tool descriptors and widget rendering in MCP Inspector
- test the app in ChatGPT developer mode through HTTPS tunneling
- exercise retries and repeated tool calls to confirm idempotent behavior
- check widget updates after host events and follow-up tool calls
- If you are only delivering a scaffold and are not installing dependencies, still run low-cost checks and say exactly what you did not run.
Read `references/repo-contract-and-validation.md` for the validation ladder.
### 7. Connect and Test in ChatGPT (Developer Mode)
For local development, include explicit ChatGPT setup steps (not just code/run commands).
- Run the MCP server locally on `http://localhost:<port>/mcp`
- Expose the local server with a public HTTPS tunnel (for example `ngrok http <port>`)
- Use the tunneled HTTPS URL plus `/mcp` path when connecting from ChatGPT
- In ChatGPT, enable Developer Mode under **Settings → Apps & Connectors → Advanced settings**
- In ChatGPT app settings, create a new app for the remote MCP server and paste the public MCP URL
- Tell users to refresh the app after MCP tool/metadata changes so ChatGPT reloads the latest descriptors
Note: Some docs/screenshots still use older "connector" terminology. Prefer current product wording ("app") while acknowledging both labels when giving step-by-step instructions.
### 8. Plan Production Hosting and Deployment
When the user asks to deploy or prepare for launch, generate hosting guidance for the MCP server (and widget assets if hosted separately).
- Host behind a stable public HTTPS endpoint (not a tunnel) with dependable TLS
- Preserve low-latency streaming behavior on `/mcp`
- Configure secrets outside the repo (environment variables / secret manager)
- Add logging, request latency tracking, and error visibility for tool calls
- Add basic observability (CPU, memory, request volume) and a troubleshooting path
- Re-test the hosted endpoint in ChatGPT Developer Mode before submission
### 9. Prepare Submission and Publish (Public Apps Only)
Only include these steps when the user intends a public directory listing.
- Use `apps-sdk/deploy/submission` for the submission flow and `apps-sdk/app-submission-guidelines` for review requirements
- Keep private/internal apps in Developer Mode instead of submitting
- Confirm org verification and Owner-role prerequisites before submission work
- Ensure the MCP server uses a public production endpoint (no localhost/testing URLs) and has submission-ready CSP configured
- Prepare submission artifacts: app metadata, logo/screenshots, privacy policy URL, support contact, test prompts/responses, localization info
- If auth is required, include review-safe demo credentials and test the login path end-to-end
- Submit for review in the Platform dashboard, monitor review status, and publish only after approval
## Interactive State Guidance
Read `references/interactive-state-sync-patterns.md` when the app has long-lived widget state, repeated interactions, or component-initiated tool calls (for example, games, boards, maps, dashboards, editors).
Use it to choose patterns for:
- State snapshots plus monotonic event tokens (`stateVersion`, `resetCount`, etc.)
- Idempotent retry-safe handlers
- `structuredContent` vs `_meta` partitioning
- MCP Apps bridge-first update flows with optional `window.openai` compatibility
- Decoupled data/render tool architecture for more complex interactive apps
## Output Expectations
When using this skill to scaffold code, produce output in this order unless the user asks otherwise:
- For direct scaffold requests, do not stop at the plan: give the brief plan, then create the files immediately.
1. Primary app archetype chosen and why
2. Tool plan and architecture choice (minimal vs decoupled)
3. Upstream starting point chosen (official example, ext-apps example, or local fallback scaffold) and why
4. Doc pages/URLs used from `$openai-docs`
5. File tree to create or modify
6. Implementation (server + widget)
7. Validation performed against the minimum working repo contract
8. Local run/test instructions (including tunnel + ChatGPT Developer Mode app setup)
9. Deployment/hosting guidance (if requested or implied)
10. Submission-readiness checklist (for public launch requests)
11. Risks, gaps, and follow-up improvements
## References
- `references/app-archetypes.md` for classifying requests into a small number of supported app shapes
- `references/apps-sdk-docs-workflow.md` for doc queries, page targets, and code-generation checklist
- `references/interactive-state-sync-patterns.md` for reusable patterns for stateful or highly interactive widget apps
- `references/repo-contract-and-validation.md` for the minimum working repo contract and lightweight validation ladder
- `references/search-fetch-standard.md` for when and how to default to the standard `search` and `fetch` tools
- `references/upstream-example-workflow.md` for choosing between official examples, ext-apps examples, and the local fallback scaffold
- `references/window-openai-patterns.md` for ChatGPT-specific extensions, wrapper API translation, and React helper patterns
- `scripts/scaffold_node_ext_apps.mjs` for a minimal Node + `@modelcontextprotocol/ext-apps` fallback starter scaffold
Источник: openai/skills / chatgpt-apps ↗. Ссылка проверена 2026-10-10.