CityJS London 2026 Companion
По сути, MCP Apps
Вы знаете, как MCP-серверы возвращают текст, JSON и тому подобное? Что ж, MCP Apps идут еще дальше: ваши инструменты могут возвращать полноценные HTML-виджеты, которые отображаются непосредственно внутри ChatGPT. Вместо того чтобы модель вываливала на пользователя стену из JSON, он видит настоящий интерфейс. Карточки, сетки, временные шкалы — что угодно.
Это буквально просто POC (проверка концепции), ничего серьезного. Это приложение-компаньон для конференции CityJS London 2026: расписание, докладчики, поиск выступлений — все это отображается в виде насыщенного тематического интерфейса внутри ChatGPT.
Запуск
./start.shВот и все. Одна команда. Она устанавливает зависимости, запускает сервер, открывает туннель cloudflared и выдает вам URL для вставки в ChatGPT. Вам понадобятся Node.js 18+ и cloudflared (brew install cloudflared на Mac).
Вы увидите что-то вроде этого:
┌─────────────────────────────────────────────────────────┐
│ │
│ YOUR MCP ENDPOINT: │
│ │
│ https://something-random.trycloudflare.com/mcp │
│ │
│ NOW GO ADD IT TO CHATGPT: │
│ │
│ 1. Open chatgpt.com │
│ 2. Click the tools icon (wrench) in the input bar │
│ 3. Click 'Add MCP Server' │
│ 4. Paste the URL above │
│ 5. Ask: 'What's the CityJS London schedule?' │
│ │
└─────────────────────────────────────────────────────────┘Затем спрашивайте ChatGPT о чем-то вроде "покажи мне докладчиков", "расскажи мне о выступлении Дугласа Крокфорда" или "найди выступления об ИИ", и наблюдайте, как появляются виджеты.
Related MCP server: Hello Widget Example
Хорошо, но как мне узнать об MCP Apps
ИСХОДНЫЙ КОД НЕ СТРАШНЫЙ! Изучите его. Там по сути 3 соответствующих файла (и они маленькие!):
Файл | Что он делает |
MCP-сервер. Регистрирует виджеты, регистрирует инструменты, связывает их вместе. Начните отсюда. | |
HTML-виджет, который отображает временную шкалу конференции. Прочитайте тег | |
HTML-виджет, который отображает сетку карточек докладчиков. Тот же шаблон, что и выше. | |
HTML-виджет для карточки с полным профилем отдельного докладчика. |
ПРОЧИТАЙТЕ ИХ. ЭТО ВЕСЕЛО, ПРАВДА!
Как это по сути работает
MCP App — это просто MCP-сервер, который также обслуживает HTML-виджеты. Когда ChatGPT вызывает ваш инструмент, он отрисовывает ваш виджет и передает в него выходные данные инструмента. Три вещи делают это возможным:
1. Вы пишете HTML-виджет
Автономный HTML-файл со встроенными CSS и JS. Он получает данные от ChatGPT и отображает их. Это все, что он делает. Посмотрите на widgets/speakers.html — это просто функция render(data) и немного CSS.
Виджет получает данные от ChatGPT следующим образом:
// ChatGPT puts tool output here when the widget loads
tryRender(window.openai?.toolOutput);
// Or fires this event slightly later
window.addEventListener("openai:set_globals", (e) => {
tryRender(e.detail?.globals?.toolOutput);
});Он также подхватывает тему (window.openai?.theme), поэтому он автоматически соответствует светлой/темной теме ChatGPT.
2. Вы регистрируете виджет как ресурс
В server.js вы сообщаете хосту MCP: "эй, у меня есть этот виджет":
server.registerResource(
"schedule-widget",
"ui://cityjs/schedule.html",
{ mimeType: "text/html;profile=mcp-app" }, // <-- this MIME type is the magic
async () => ({
contents: [{
uri: "ui://cityjs/schedule.html",
mimeType: "text/html;profile=mcp-app",
text: scheduleWidgetHtml, // the raw HTML string
}],
})
);MIME-тип text/html;profile=mcp-app — это то, что превращает обычный MCP-сервер в MCP App. Он говорит хосту: "это виджет для отрисовки, а не просто файл".
3. Вы привязываете инструмент к виджету
Когда вы регистрируете инструмент, вы сообщаете хосту, какой виджет отрисовывать при вызове инструмента:
server.registerTool(
"get_schedule",
{
title: "Get Schedule",
description: "Get the CityJS London 2026 schedule...",
inputSchema: { day: z.enum(["day1", "day2", "day3", "all"]).optional() },
_meta: {
ui: { resourceUri: SCHEDULE_URI }, // MCP spec way
"openai/outputTemplate": SCHEDULE_URI, // ChatGPT-specific way
},
},
async ({ day }) => {
return {
structuredContent: { days }, // <-- your widget receives THIS
content: [{ type: "text", text: JSON.stringify({ days }) }], // fallback for non-UI hosts
};
}
);structuredContent — это данные, которые отрисовывает ваш виджет. content — это текстовый резервный вариант для хостов, которые еще не поддерживают UI (например, Claude). Всегда возвращайте оба.
И это по сути все. Виджет + ресурс + привязка инструмента = MCP App.
Проект
basically-mcp-apps/
start.sh <- run this. that's it.
server.js <- the MCP server. START READING HERE.
package.json
data/
data.json <- raw conference data (speakers, talks, bios)
cityjs.js <- enriches the raw data with rooms, types, etc.
widgets/
schedule.html <- conference schedule timeline widget
speakers.html <- speaker grid widget
speaker-detail.html <- individual speaker profile card widgetЗависимости
@modelcontextprotocol/sdk— SDK для MCP-сервераzod— валидация входной схемыcloudflared— создает туннель от вашего localhost в интернет, чтобы ChatGPT мог получить к нему доступNode.js 18+
Никакого React, никаких этапов сборки, никаких бандлеров, никаких фреймворков. Только HTML-файлы и Node-сервер.
Удачного хакинга!
This server cannot be deployed
Maintenance
Related MCP Connectors
MCP server for OpenAI API (chat completions, image generation, embeddings) via AceDataCloud
Build your own tools from chat: design, test and host them on a shareable MCP server URL.
1MCP server for AI dialogue using various LLM models via AceDataCloud
Driflyte MCP server which lets AI assistants query topic-specific knowledge from web and GitHub.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceA minimal MCP server demonstrating how to build ChatGPT-compatible applications using Next.js with widget rendering capabilities. Provides a starter template for integrating Next.js applications with the ChatGPT Apps SDK through the Model Context Protocol.-
- FlicenseNot gradedqualityNot gradedmaintenanceA minimal ChatGPT app demonstrating interactive greeting widgets with confetti animations and theme support, built as a template for creating MCP servers with custom UI components.-
- FlicenseNot gradedqualityDmaintenanceAn MCP server template integrated with the OpenAI Apps SDK for building ChatGPT-compatible widgets with automatic tool registration. It provides a suite of interactive UI components and ecommerce examples for creating type-safe, theme-aware widgets.-
- FlicenseNot gradedqualityDmaintenanceAn MCP server that enables AI models to render GitHub's Primer React components directly within chat interfaces using a JSON component tree. It provides tools to list available components and display interactive UI elements with full GitHub theming support.-