Содержание
Я отправил первую версию плагина Call Trace на проверку в OpenAI и получил отказ. В ответе говорилось, что назначение приложения или часть его поведения противоречит правилам использования. До публикации пришлось пересмотреть, какие возможности и данные я передаю AI-клиенту.
Call Trace — мой сервис для работы с записями звонков. Через плагин пользователь может найти запись, посмотреть её основные данные и получить расшифровку прямо в ChatGPT или Codex. За этим простым сценарием стоят взаимодействие модели с инструментами, авторизация в сервисе и проверка границ доступа.
Расскажу, что я изменил после отказа, как устроил обмен данными и как проверял интеграцию. Отдельно остановлюсь на доработках, которые понадобились уже после публикации.
Сценарий для пользователя
У пользователя уже есть записи звонков в Call Trace. Для работы с ними из чата нужны понятные действия: найти запись, посмотреть её основные данные и открыть расшифровку.
Например:
Покажи 10 последних завершённых звонков.
Затем:
Открой расшифровку звонка с этим ID.
После получения текста можно попросить ChatGPT кратко пересказать содержание или выписать договорённости с цитатами. Здесь важно различать две операции: сервер Call Trace возвращает расшифровку, а модель работает с полученным текстом. Отдельного инструмента «сделать резюме» в публичном плагине нет.
Такой сценарий позволяет начать с обычного вопроса и последовательно дойти до нужного материала. При этом доступ остаётся привязан к аккаунту и компании в Call Trace.
Для этого нужно согласовать три вещи: как пользователь формулирует задачу, какой инструмент выбирает модель и какие данные сервер вправе вернуть. Ошибка на любом из этих этапов влияет на конечный ответ.
Что пришлось изменить после отказа
После отказа по версии 1.0.0 я сузил публичную часть интеграции. Это было моё решение по доработке плагина: письмо OpenAI указывало на несоответствие правилам использования в общей форме.
В раннем варианте были инструменты подробного анализа звонка и командных показателей. Они включали оценки, сведения о сотрудниках и другие результаты внутренней аналитики. При доработке я убрал публичный доступ к идентификаторам сотрудников, оценкам, рейтингам, анализу эмоций и сравнению результатов команды.
В итоге осталось три действия: найти запись, прочитать минимальные данные и получить расшифровку конкретного разговора.
Этот опыт помог мне точнее провести границу между основным продуктом и плагином. Внутри сервиса может быть много функций, но каждую возможность, передаваемую AI-клиенту, приходится оценивать отдельно: для чего она нужна, какие данные раскрывает и какие выводы позволяет делать.
Сокращение возможностей затронуло серверный ответ. Даже если во внутренней записи есть дополнительные поля, публичный инструмент возвращает только явно разрешённый набор.
Из этого случая не следует общий запрет на аналитику звонков. Он показывает, как замечания к конкретной интеграции могут потребовать пересмотра её функций. Теперь я бы закладывал такую границу заранее: внешний контракт должен содержать данные, необходимые для заявленного сценария.
Взаимодействие AI-клиента с сервисом
Публичная интеграция Call Trace использует MCP — Model Context Protocol. Он позволяет AI-клиенту узнать, какие действия доступны на сервере, с какими аргументами их вызывать и какой результат ожидать.
MCP-сервер Call Trace работает по HTTPS через Streamable HTTP. У него есть адрес https://www.call-trace.com/mcp, а доступ к данным выдаётся через OAuth.
После авторизации запрос проходит через несколько этапов:
«Покажи последние завершённые звонки»
OAuth связывает подключение с подтверждёнными аккаунтом и компанией.
- 01AI-клиентChatGPT / Codex
Выбирает инструмент и передаёт аргументы.
- 02Проверка доступаMCP Call Trace
Проверяет токен, права и компанию.
- 03Источник данныхРабочее пространство
Возвращает записи разрешённой компании.
Call Trace отбирает разрешённые поля и маскирует поддерживаемые чувствительные данные в тексте.
- Только чтение
- В рамках компании
- Минимум данных
Я реализовал плагин без собственного виджета внутри чата: сервер предоставляет инструменты и данные, а диалог ведёт AI-клиент. Для трёх доступных действий этого оказалось достаточно.
Здесь полезно различать компоненты. MCP-сервер выполняет операции. OAuth определяет, кто и к каким данным получает доступ. Пакет плагина содержит сведения для установки и подключения. Каталог помогает пользователю найти и установить этот пакет.
Актуальная документация OpenAI описывает пакет как объединение навыков, подключений MCP и других ресурсов. Состав зависит от задачи: собственный интерфейс и набор навыков нужны не каждому плагину. Устройство пакета плагина.
Три инструмента с понятными границами
В публичной версии я оставил небольшой контракт:
| Инструмент | Назначение | Что получает клиент |
|---|---|---|
search_calls |
Найти записи по статусу, очереди, времени создания или фрагменту имени файла либо внешнего ID записи (reference) |
Список с минимальными данными |
get_call |
Получить данные одного звонка по ID | ID, статус, очередь, время создания и наличие расшифровки |
get_transcript |
Получить текст конкретного звонка | ID, расшифровку с маскированием поддерживаемых чувствительных данных и признак применения маскирования |
Поиск возвращает новые записи первыми: по умолчанию десять, максимум двадцать пять за вызов. Это ограничивает объём одной выдачи и делает результат удобнее для дальнейшей работы.
Например, запрос «покажи десять последних завершённых звонков» должен привести к вызову search_calls со статусом done и ограничением 10. После выбора записи модель использует её ID для получения расшифровки. Сервер отвечает за поиск и проверку доступа, а модель — за выбор действия и объяснение результата пользователю. Эти части взаимодействия нужно проверять отдельно.
У поиска есть существенная граница: search_calls не выполняет смысловой поиск по всем расшифровкам. Если попросить «найди все звонки, в которых обсуждали возврат денег», нельзя обещать полный результат на основании этого инструмента. Сначала нужно определить доступную выборку, затем получить необходимые тексты и обозначить, какие записи действительно просмотрены.
Описание каждого инструмента должно объяснять его назначение, входные параметры и ограничения. Модель использует эти сведения, чтобы выбрать действие. Поэтому точность описания влияет на поведение интеграции так же непосредственно, как точность схемы API. Как проектировать инструменты.
Практический приём, который я рекомендую: рядом с каждым примером успешного запроса записать похожий запрос, который инструмент выполнить не может. Это быстро обнаруживает слишком широкие обещания в описании.
Ограничения доступа к данным
Первое ограничение — доступ только к данным авторизованной компании. Идентификатор компании сервер получает из проверенного контекста авторизации. Модель не выбирает его аргументом инструмента.
Это относится и к поиску, и к запросу отдельной записи. Знание чужого callId само по себе не должно давать доступ к звонку.
Второе ограничение — небольшой состав ответа. Для списка звонков не нужны исходные метаданные провайдера, аудиофайлы или сведения о сотрудниках. Публичный контракт содержит только поля, необходимые для заявленных действий.
Третье — маскирование перед передачей текста. В расшифровках обрабатываются известные шаблоны чувствительных данных: например, обычные адреса электронной почты, телефонные номера и некоторые форматы платёжных реквизитов и секретов.
Это не полная анонимизация. Маскирование по шаблонам не гарантирует удаления любых имён, косвенных идентификаторов или необычно записанных данных. Такой механизм нужно проверять на характерных для продукта примерах и точно описывать его границы.
Все три инструмента объявлены как readOnlyHint: true, destructiveHint: false и openWorldHint: false: они читают данные внутри разрешённой компании, не изменяют записи и не обращаются к произвольным внешним ресурсам.
Эти аннотации сообщают клиенту свойства инструмента. Фактические ограничения обеспечивают проверки доступа и код сервера. Размещение MCP-сервера в интернете само по себе не означает openWorldHint: true: значение относится к области действия инструмента. Справочник аннотаций OpenAI.
Подключение аккаунта через OAuth
Для Call Trace я использовал OAuth с кодом авторизации, PKCE и динамической регистрацией клиентов. Плагин запрашивает ограниченную область доступа analysis:read.
PKCE связывает обмен кода на токен с клиентом, который начал авторизацию. Для пользователя эта деталь незаметна, но сервер должен проверять её вместе со сроком действия запроса, допустимым адресом возврата и правами доступа.
В документации OpenAI также описаны discovery — обнаружение параметров авторизации — и ответ 401 с указанием метаданных защищённого ресурса. Для PKCE требуется поддержка S256. Динамическая регистрация, которую я использовал, — один из поддерживаемых способов настройки клиента; её не следует считать единственным вариантом для любого проекта. Авторизация MCP в OpenAI.
При проектировании этого участка полезно заранее ответить на практические вопросы: что произойдёт после истечения запроса, повторного подтверждения, смены аккаунта, обновления токена или отзыва подключения? У каждого состояния должен быть понятный результат и для сервера, и для человека.
Валидация инструментов и авторизации
Я дополнял проверки по мере разработки и доработок после релиза. В итоге валидация разделилась на несколько уровней: контракт серверных инструментов, процесс авторизации и поведение интеграции в реальном AI-клиенте. Для первых двух появились отдельные автоматические проверки.
Проверка контракта фиксирует точный список инструментов, схемы ответов, аннотации, отсутствие исключённых полей и маскирование подготовленных примеров. Она помогает заметить ситуацию, когда изменение внутреннего API случайно расширяет публичную выдачу.
Для OAuth я проверял регистрацию и активацию в новой вкладке, повторную отправку письма, смену аккаунта, одновременное подтверждение, неверный PKCE, повторное использование кода, обновление токенов, отзыв доступа, истечение запроса и права администратора.
В приёмку стоит включить следующую матрицу ожидаемого поведения:
| Сценарий | Ожидаемый результат |
|---|---|
| Пользователь не вошёл в сервис | Подключение продолжается после входа |
| Письмо активации открыто в новой вкладке | Восстанавливается исходный запрос подключения |
| Аккаунт изменился перед подтверждением | Нельзя незаметно выдать доступ от другого аккаунта |
| Передан ID звонка другой компании | Данные чужой компании не возвращаются |
| Код авторизации использован повторно | Повторный обмен отклоняется |
| Пользователь отозвал подключение | Токены отозванного подключения больше не дают доступ |
| Запрос подключения истёк | Пользователь получает понятное предложение начать заново |
Проверки, создающие пользователей и компании, я вынес в отдельную тестовую базу. Дополнительно тест требует явно указать разрешённый тестовый адрес и останавливается при несовпадении конфигурации.
Ещё один урок возник при выпуске OAuth-изменений: локальная конфигурация базы отличалась от фактической production-конфигурации. Поэтому применение миграции нужно проверять через подключение, которым пользуется опубликованное приложение. Успешная команда миграции в терминале сама по себе не доказывает, что обновлена нужная база.
Отдельно нужно проверять взаимодействие с моделью: какое действие она выбрала по запросу пользователя, какие аргументы передала и насколько ответ соответствует полученным данным. Локальный тест с собственным адресом возврата не воспроизводит интерфейс и поведение ChatGPT или Codex. Установку и подключение из самого клиента нужно включать в приёмку отдельным проходом.
Материалы для проверки OpenAI
Для Call Trace я описал пять положительных и три отрицательных сценария. Положительные покрывали последние завершённые звонки, фильтры по очереди и датам, данные одной записи, её расшифровку и поиск по явному reference.
Отрицательные сценарии проверяли границы: запрос данных другой компании, ранжирование сотрудников и попытку использовать анализ эмоций для кадрового решения. Они нужны, чтобы проверить, соблюдает ли интеграция заявленные ограничения.
Для демонстрации я подготовил отдельный сценарий с синтетическими звонками. При подготовке своей заявки стоит сделать так, чтобы проверяющий мог воспроизвести каждый шаг без доступа к реальным клиентским разговорам.
По актуальной на 2 ноября 2026 года инструкции OpenAI пакет для проверки MCP включает отдельный демонстрационный аккаунт, пять положительных и три отрицательных теста, видеодемонстрацию и описание изменений. Аккаунт проверяющего должен работать без MFA, одноразовых кодов и magic links. Также нужны стабильный публичный HTTPS-сервер и проверка домена. Подготовка и отправка плагина.
Практически полезно вести небольшой комплект материалов рядом с кодом: описание возможностей, схемы инструментов, примеры запросов, ожидаемые результаты, ограничения и сценарий демонстрации. Тогда изменения контракта легче согласовать с текстом карточки и тестами.
Публикация в каталоге
После доработок я опубликовал Call Trace в общедоступном каталоге. Карточка плагина и инструкция подключения — точки входа для пользователя.
При подготовке релиза полезно различать состояния. Добавление в локальный marketplace даёт возможность установки и тестирования в соответствующей среде. Публикация внутри рабочего пространства ограничивает распространение этой организацией. Для общедоступного каталога предусмотрена отдельная процедура. Варианты распространения.
В публичном процессе OpenAI отправка на проверку, одобрение и публикация — разные шаги. После одобрения требуется действие Publish plugin. Процесс публикации.
При обновлении MCP-инструментов документация рекомендует запускать Rescan и проверять доступность изменений. Новые инструменты появляются после одобрения, а задержка проверки изменений существующего инструмента может оставить у клиента прежнюю одобренную схему. Серверу нужно сохранять совместимость с ней до обновления. Обновление MCP-сервера.
После появления плагина в каталоге начался следующий этап проверки — подключение из реального пользовательского сценария. Именно здесь обнаружилась проблема, которую не видно по одному лишь ответу MCP-сервера.
Проблемы после публикации
После публикации я столкнулся с ситуацией, которую легко пропустить во время разработки: пользователь устанавливает плагин, проходит часть подключения и не понимает, к какому аккаунту сервиса он привязан.
Установка и разрешение доступа — разные этапы. Пользователь может прийти из каталога без активной сессии Call Trace. Может зарегистрироваться впервые. Может открыть письмо подтверждения в другой вкладке. Может обнаружить, что вошёл под другим аккаунтом.
Я переделал подключение в явную последовательность:
- Войти или зарегистрироваться.
- Проверить показанные email и компанию.
- Подтвердить доступ на чтение.
- Вернуться в AI-клиент.
Запрос подключения сохраняется на сервере. Браузер получает непрозрачный идентификатор процесса, а переход после подтверждения почты восстанавливает нужный шаг. Поэтому продолжение не зависит только от состояния исходной вкладки.
Перед выдачей доступа сервер повторно проверяет, что текущие пользователь и компания соответствуют тем, которые были показаны при подтверждении. Для разрешения подключения требуются права администратора компании.
На странице интеграций пользователь видит, кто выдал доступ, к какой компании относится подключение, когда оно использовалось и как его отозвать. Если обращений ещё не было, интерфейс показывает ожидание первого запроса.
Это важное различие для диагностики: выданное разрешение и успешное обращение за данными — два отдельных события.
С чего я начал бы следующую интеграцию
Если бы я проходил этот путь заново, порядок работы был бы таким:
- Выбрать конкретный сценарий. Описать вопрос пользователя и полезный результат, который он должен получить.
- Определить минимальные инструменты. Для каждого записать аргументы, возвращаемые поля и ограничения.
- Спроектировать доступ. Связать запросы с авторизованной компанией и проверять права на каждую запись.
- Пройти подключение как новый пользователь. Начать без активной сессии, проверить регистрацию, письмо в другой вкладке и смену аккаунта.
- Подготовить демонстрационные данные. Сделать сценарии воспроизводимыми без реальных разговоров клиентов.
- Проверить границы. Запросить чужую запись, неподдерживаемую операцию и данные, которые контракт не должен возвращать.
- Согласовать код и материалы заявки. Описание, видео и ожидаемые ответы должны соответствовать фактическим возможностям.
- После публикации повторить весь путь в клиенте. Установить плагин, разрешить доступ, получить данные и отозвать подключение.
В итоге у публичного плагина осталось три инструмента с определёнными границами доступа. Отказ заставил меня пересмотреть состав выдаваемых данных, проверки — зафиксировать допустимое поведение, а опыт после публикации — сделать подключение аккаунта понятнее. Следующую интеграцию я бы с самого начала проверял целиком: запрос человека, выбор инструмента моделью, авторизацию, ответ сервера и возможность отозвать доступ.
Ссылки: сайт Call Trace · Call Trace в LinkedIn · плагин в каталоге OpenAI.