Как устроено приложение JourneyBay для ChatGPT на MCP
Что такое приложение JourneyBay для ChatGPT?
Приложение JourneyBay для ChatGPT - это авторизованная MCP-интеграция для планирования поездок. ChatGPT может работать с поездками, местами, маршрутами, избранным и визовым контекстом пользователя, а отдельные результаты показывать как интерактивный UI прямо в диалоге.
TL;DR
- -Production MCP-сервер JourneyBay даёт ChatGPT 23 узких travel-инструмента: читать поездки, искать места, менять маршрут, импортировать план и возвращать полезный результат даже без виджета.
- -Карты, расписания дня, карточки мест, чек-листы и подтверждения действий открываются внутри диалога через UI-ресурсы MCP Apps.
- -OAuth 2.1 с PKCE, девять scopes, проверка прав на каждом tool call, фильтрация ответа, rate limits и audit events ограничивают доступ точнее, чем одно общее разрешение на аккаунт.
- -Тот же remote MCP transport можно подключать к другим совместимым клиентам, но OAuth и UI нужно проверять отдельно для каждого хоста.
Полезное приложение для путешествий внутри ChatGPT - это не ещё один чат-бот. Это точка, где фраза «перенеси музей на третий день» превращается в контролируемое изменение того же маршрута, который пользователь видит в JourneyBay.
В заметках о релизе JourneyBay 2.0 маршрут показан со стороны путешественника. Здесь я разбираю серверную часть и условия, которые должны выполниться до доступа ChatGPT к поездке.
Именно вокруг этой границы я строил интеграцию JourneyBay. ChatGPT определяет подходящую операцию; сервер JourneyBay проверяет пользователя и разрешение, выполняет действие и возвращает короткий ответ для модели. Если результат лучше воспринимать глазами, рядом появляется интерактивная карта или расписание.
Ниже - не пересказ анонса, а разбор production-пути: набор инструментов, граница между моделью и UI, а также авторизация, без которой MCP-интеграцию нельзя подключать к реальным данным.
Что приложение действительно умеет
Профиль OpenAI сейчас открывает 23 пользовательских инструмента. Вместо одного универсального manage_trip у каждого действия своя узкая задача:
- прочитать список поездок, детали маршрута, расписание дня, чек-лист, избранное и историю чата;
- найти места, открыть карточку, получить рекомендации и визовый контекст;
- создать поездку, добавить или удалить активность, изменить порядок дня, обновить заметку и архивировать поездку;
- сгенерировать или скорректировать маршрут и отправить сообщение travel-ассистенту JourneyBay;
- импортировать в JourneyBay полный маршрут, составленный в диалоге.
Такое разделение нужно не ради красивого списка. Для вопроса о расписании модель выбирает get_day_schedule и не получает право что-либо менять. Удаление активности попадает в другой handler, требует scope на запись и помечено как destructive action.
Ещё четыре MCP resource дают компактный контекст: список поездок, выбранная поездка, избранное и travel-профиль. Они тоже проверяют разрешения. Если у подключения нет favorites:read, ресурс избранного не вернёт сохранённые места.
Получается предсказуемее, чем передавать любой запрос в один общий chat endpoint. Имя инструмента, schema, необходимые scopes и safety annotations образуют контракт между моделью и приложением. Актуальная документация OpenAI рекомендует тот же подход: отдельный инструмент для каждой понятной пользовательской цели вместо множества несвязанных режимов в одном endpoint (официальное руководство по MCP-серверу).
Путь одного запроса
Production-путь достаточно короткий, чтобы его можно было проверить целиком:
ChatGPT
-> MCP поверх Streamable HTTP
-> проверка OAuth token и scopes
-> tool handler JourneyBay
-> данные Supabase или Edge Function
-> текстовый результат + опциональные данные для UI
Публичный MCP endpoint: https://mcp.journeybay.co/mcp. Сервер написан на Deno и использует официальный TypeScript SDK для MCP. Каждое подключение получает MCP session, а перед регистрацией инструментов сервер выбирает platform profile по OAuth client и origin запроса.
Отдельные профили платформ оказались полезнее, чем выглядело в начале. ChatGPT не нужны все внутренние поля и developer-only инструменты. Профиль OpenAI исключает health tool, нормализует описания, удаляет запрещённые входные поля и фильтрует ответ, который увидит модель. Другой клиент может получить свой набор инструментов и UI без копирования бизнес-логики.
Фраза «построено на MCP» сама по себе ничего не гарантирует. Серверу всё равно нужны однозначная авторизация, ограниченный объём данных в ответе, стабильные tool contracts и рабочий fallback для клиента без custom UI.
Почему карта не должна жить в prompt
Маршрут по дням неудобно проверять в длинном абзаце. Поэтому JourneyBay связывает отдельные инструменты с UI resources MCP Apps: картой поездки, расписанием дня, карточками мест, результатами поиска, чек-листом, progress view и короткими подтверждениями операций записи.
В tool response два канала:
contentдаёт модели достаточно текста, чтобы продолжить диалог.structuredContentпередаёт компоненту поля для отрисовки.
Resource URI связывает инструмент с компонентом. ChatGPT показывает его в iframe рядом с диалогом. Реализация использует общее поле _meta.ui.resourceUri и сохраняет alias openai/outputTemplate для совместимости с хостами, которые пока ожидают расширение OpenAI.
Такой контракт защищает от частой ошибки MCP UI: красивый виджет становится единственным местом, где есть полезный результат. Инструменты JourneyBay возвращают осмысленный текст и в хосте без компонентов. OpenAI также рекомендует строить UI поверх общего стандарта и оставлять tools пригодными для работы без него (официальное руководство по UI).
Следующий технический шаг - отделить больше data tools от render tools. Если компонент прикреплён к каждому промежуточному вызову, iframe может перезапуститься несколько раз, пока модель ещё собирает ответ. Отдельный render tool позволяет сначала получить, отфильтровать и проверить данные, а затем открыть одно финальное представление. Но это стоит внедрять по результатам измерений на многошаговом поиске, а не механически для всех инструментов.
Авторизация проверяется на уровне инструмента
Данные о поездках персональны, а изменения маршрута имеют побочные эффекты. Production-сервер не принимает анонимные MCP-вызовы. Он публикует metadata защищённого ресурса и authorization server, использует OAuth 2.1 authorization code flow с PKCE и проверяет bearer token для каждого MCP request.
В JourneyBay девять scopes:
trips:readиtrips:write;favorites:readиfavorites:write;places:read;chat:readиchat:write;profile:read;itinerary:generate.
Каждый инструмент объявляет необходимые scopes. Registry повторно проверяет их до запуска handler. Затем backend query привязывается к авторизованному пользователю JourneyBay. Это и есть defense in depth: скрыть инструмент из tools/list полезно, но это не замена авторизации.
Актуальная документация OpenAI требует от MCP-серверов с пользовательскими данными или write actions реализацию OAuth 2.1, discovery metadata и PKCE с S256 (официальное руководство по авторизации). Живые metadata JourneyBay публикуют эти endpoint и scopes на mcp.journeybay.co.
Два получателя - два набора данных
Модели и виджету нужны разные поля.
Из JSON-ответов инструментов, доступных модели, профиль OpenAI удаляет внутренние user и trip IDs, timestamps, данные подписки, deep links, точные координаты пользователя и служебные metadata.
Виджету иногда нужен record ID для следующего tool call или координаты, чтобы нарисовать карту. Поэтому structured channel сохраняет функциональные поля, но удаляет запрещённые provider IDs, commerce data и бесполезные deep links. Registry применяет фильтры к JSON после tool handler. Свободный текст нужно проверять отдельно: response filter не даёт права возвращать произвольные строки.
Это не превращает _meta или iframe в security boundary. Токенам и секретам не место в tool result. Авторизация остаётся на сервере, а вызов из виджета проходит те же проверки, что и вызов от модели. Тот же принцип действует для остальных пунктов аудита безопасности MCP.
Как приложение ломается безопасно
Ошибка должна оставлять диалогу понятный путь восстановления.
- Просроченный или отозванный token возвращает
401и metadata защищённого ресурса, чтобы хост мог переподключиться. - При нехватке scope сервер возвращает конкретную ошибку разрешений и не пытается выполнить действие.
- Rate limits считаются по OAuth client и пользователю; для AI generation действует более низкий лимит.
- Tool calls создают audit events, duration metrics и success/error counters без записи содержимого маршрута в лог.
- Ошибка компонента не уничтожает текстовый результат.
Текущий rate limiter хранится в памяти. Для нынешнего single-instance deployment этого достаточно, но перед горизонтальным масштабированием его нужно вынести в общее хранилище. Иначе две реплики будут независимо разрешать два бюджета запросов.
Как подключить JourneyBay к ChatGPT
Откройте каталог plugins или apps в ChatGPT, выберите JourneyBay и нажмите Sign in with JourneyBay. Проверьте запрашиваемые разрешения и завершите авторизацию. Для первого вызова лучше выбрать ограниченную задачу:
- «Покажи мои ближайшие поездки».
- «Открой расписание второго дня поездки в Токио».
- «Найди три музея рядом с сохранёнными местами в Париже».
- «Перенеси бронь ресторана на третий день».
Первые два запроса используют read tools. Последний требует права менять поездку. Когда операции разделены, проще понять и authorization prompt, и запись в audit trail.
Для другого MCP-совместимого клиента укажите remote server URL https://mcp.journeybay.co/mcp. Одной фразы «клиент поддерживает MCP» недостаточно. Нужно проверить remote Streamable HTTP, требуемый OAuth flow, tool annotations и, если нужны карты или карточки, MCP Apps UI.
Что изменилось после первого прототипа
Первую версию было легко описать: подключить travel API к ChatGPT. В production пришлось точнее провести границу ответственности.
Модель предлагает и связывает действия. JourneyBay отвечает за identity, permissions, data access, validation, side effects и auditability. Компоненты упрощают проверку структурированного результата, но инструменты остаются полезными и без них. MCP задаёт транспорт и contracts, однако не заменяет безопасность приложения.
В этом и состоит практический результат интеграции. Обсуждение поездки в ChatGPT больше не обязано заканчиваться одноразовым текстом. После явного разрешения оно может стать тем же структурированным маршрутом, с которым пользователь продолжит работать в JourneyBay.
Источники
- OpenAI: разработка MCP-сервера
- OpenAI: добавление UI к MCP-серверу
- OpenAI: авторизация пользователей plugin
- Спецификация Model Context Protocol
JourneyBay показывает визовый контекст, чтобы помочь с подготовкой к поездке. Перед путешествием всегда проверяйте правила въезда на сайте посольства, консульства или официального государственного портала страны назначения.