- BrainTools - https://www.braintools.ru -
Представьте диалог c вашим любимым ИИ‑инструментом:
— Найди поездку в Казань на выходные, до 20 тысяч рублей и с нормальным отелем.
— Секунду, подбираю…
«Подбираю» в этом диалоге — это некоторый чёрный ящик. Под ним могут скрываться воспоминания модели из обучения [1], попытки воспользоваться веб‑браузером, поиском в интернете. Такие обращения могут содержать различного рода погрешности.
А вот чтобы это «подбираю» означало поиск по реальным ценам и наличию агент должен уметь обращаться к базе данных с билетами. Именно для этого мы вместе с командой Туту выпустили MCP‑сервер [2].
По оценке McKinsey, к 2030 году ИИ‑агенты могут участвовать в продажах товаров на сумму от 3 до 5 трлн долларов по всему миру.
MCP (Model Context Protocol — протокол контекста модели) — открытый протокол, через который ИИ‑агент узнаёт о доступных инструментах сервиса и вызывает их сам, а не разбирает страницы сайта.
В результате: у пользователя есть гарантия поиска по реальным данным, у разработчика агентов появляется стабильный контракт обмена данными, а для сервиса — это новая точка входа для пользователей, которые приходят через ИИ‑платформы.
Меня зовут Александр Поляков, я проектирую ИИ‑продукты. Этот MCP‑сервер мы собрали вместе с командой Туту, поэтому все семь наблюдений ниже — из практики.
Первый отзыв пришёл не от ИИ‑инженеров, а от обычных пользователей. Они присылали скриншоты белого экрана с сообщением:
{"detail": "Method Not Allowed"}
И это логично [3]. Человек первым делом нажимает на то, что выглядит как ссылка. Если адрес MCP‑сервера при обычном переходе из браузера показывает техническую ошибку [4], кажется, что всё сломалось. Разбираться дальше никто не станет.
Решение простое: если сервер умеет отличить агента от браузера, браузеру стоит показывать страницу с инструкцией. Мы различаем запросы по методу и заголовку Accept:
|
Что пришло в запросе |
Что отдаём |
|
POST |
Ответ агенту в формате JSON‑RPC (JavaScript Object Notation Remote Procedure Call — формат удалённых вызовов) |
|
GET с Accept: text/event‑stream |
Поток событий агенту через SSE (Server‑Sent Events — события от сервера) |
|
GET с Accept: text/html |
Лендинг, или посадочную страницу |
Лендинг объясняет человеку, что это за сервер, как его подключить и для каких сценариев использовать.
Здесь есть тонкость. Некоторые агенты приходят с неопределённым заголовком Accept, поэтому их нельзя случайно отправить на страницу для человека. Безопасное правило по умолчанию — отвечать как агенту, а лендинг показывать, только если мы точно распознали браузер. Боты, которые создают предпросмотр ссылок в мессенджерах, тоже получат страницу — в этом случае так и задумано.
Итог. Человек видит описание сервера и способы подключения, а агент — доступные методы и инструкции для работы.
MCP позволяет передавать агенту общие инструкции, но длинный гайд быстро расходует контекст. Надёжнее, когда каждый инструмент сам сообщает, что умеет, какие параметры принимает и как с ним обращаться.
Например, описание поиска отелей может выглядеть так:
{
"name": "search_hotels",
"description": "Поиск отелей в городе на даты заезда и выезда. Возвращает отели с ценой, рейтингом и идентификатором для оформления.",
"inputSchema": {
"type": "object",
"required": ["city", "checkin", "checkout"],
"properties": {
"city": {
"type": "string",
"description": "Город или его идентификатор"
},
"checkin": {
"type": "string",
"format": "date"
},
"checkout": {
"type": "string",
"format": "date"
},
"guests": {
"type": "integer",
"default": 2
}
}
},
"annotations": {
"readOnlyHint": true,
"idempotentHint": true,
"openWorldHint": true
}
}
Здесь агенту уже сообщено всё необходимое:
readOnlyHint — инструмент только читает данные и ничего не меняет;
idempotentHint — повторный вызов безопасен;
openWorldHint — инструмент обращается во внешний сервис.
Дублировать эту информацию в общем гайде не стоит. Иначе появятся два источника инструкций, которые рано или поздно разойдутся, а поведение [5] агента станет непредсказуемым.
Подробные руководства для сложных предметных областей мы тоже не держим в каждом сеансе. Их вынесли в отдельные методы вида get_<домен>_instructions, которые агент вызывает только при необходимости.
Итог. Хорошее описание и аннотации делают инструмент понятным без дополнительных инструкций.
Первую версию сервера мы тестировали на GPT-5.4 — всё работало стабильно. Когда запустили те же сценарии на Qwen3-30B‑A3B с контекстным окном примерно в 130 тысяч токенов, начались проблемы.
Некоторые инструменты возвращали слишком объёмные ответы. Например, схемы вагонов быстро переполняли контекст, запускали компактизацию — автоматическое сокращение истории диалога — и агент терял важные детали об инструментах.
Можно было добавить инструкцию: сначала сохранять ответ на диск, а потом искать по нему с помощью grep. Или расширить MCP с помощью отдельного навыка. Но оба варианта усложняют настройку и остаются ненадёжными.
Поэтому мы добавили постраничную выдачу даже там, где раньше она не требовалась. Например, карта мест в поезде из девяти вагонов занимала около 140 КБ. Мы стали подробно показывать первые вагоны, а остальные заменили краткими блоками с пометкой «продолжение по запросу». В карточке отеля могло быть от 20 до 35 ссылок на фотографии — оставили обложку и общее количество снимков.
На типовых ответах получили такие результаты:
|
Ответ инструмента |
Было |
Стало |
Экономия |
|
Детали по поезду |
66–75 КБ |
14–17 КБ |
75% |
|
Карточка отеля |
58 КБ |
16 КБ |
72% |
|
Сценарий целиком в памяти [6] |
около 133 тыс. токенов |
около 34 тыс. токенов |
74% |
Главная оптимизация проекта: на типовом сценарии объём занятого контекста сократился на 74%.
Отсюда практический приём: проверяйте MCP на небольших моделях с коротким контекстным окном. Они быстрее проявляют пограничные сценарии, которые незаметны при оценке на более крупных моделях.
Итог. После оптимизации даже локальная Qwen3-30B‑A3B в OpenCode проходит все наши тесты при небольшом контекстном окне.
Когда мы дошли до оплаты, на архитектуру повлияли два требования:
пользователь должен явно и осознанно принять оферту;
если передавать персональные данные или билеты в интерфейс иностранного сервиса, может возникнуть трансграничная передача данных. Для неё закон предусматривает отдельную процедуру, включая предварительное уведомление Роскомнадзора.
Поэтому последний шаг покупки всегда проходит в сеансе на сайте продавца. Сейчас через MCP агент может подобрать поездку и довести пользователя до этапа, на котором нужно ввести персональные данные и оплатить заказ. Оферту принимает, данные вводит, билет оплачивает и скачивает уже сам пользователь.
Для бизнеса это означает, что агент может довести человека до решения, а критичные действия — принятие оферты, ввод персональных данных, оплату и получение билетов — безопаснее оставить в контролируемом интерфейсе продавца. Это не ограничение технологии, а осознанная модель покупки. Полную автономию можно строить через собственных управляемых агентов — Managed Agents.
Итог. Агент помогает выбрать и подготовить заказ, но юридически значимые и чувствительные действия остаются под контролем пользователя и продавца.
Если начать разбираться с авторизацией агентов через MCP, легко запутаться в противоречивых рекомендациях. Мне понравилось, как коллеги из Битрикс24 объяснили выбор токенов. Был и собственный опыт [7]: MCP Granola удобно подключается к приложениям ChatGPT и Claude через OAuth, а с агентом Hermes пришлось повозиться — отдельно запрашивать ссылку и передавать ему redirect_url.
В стандарте MCP авторизация для удалённых HTTP‑серверов (Hypertext Transfer Protocol — протокол передачи гипертекста) описана через OAuth 2.1 — протокол, который позволяет приложению получить ограниченный доступ без передачи пользовательского пароля. Поэтому облачные клиенты, включая ChatGPT и Claude, ожидают именно такой сценарий: вставить в них произвольный ключ обычно нельзя.
Локальные клиенты работают иначе. Они могут хранить секрет на устройстве пользователя и передавать его в заголовке запроса, поэтому полноценный OAuth для них бывает избыточен. Для таких клиентов мы поддерживаем статический ключ в заголовке как дополнительный способ авторизации.
Клиенты пока не одновременно внедряют новые возможности стандарта, поэтому на переходном этапе приходится поддерживать оба варианта.
Чего точно нельзя делать — передавать ключ в адресе, например:
https://site.ru/mcp?key=xxxxxx
Спецификация MCP прямо запрещает помещать токен в строку запроса: он может попасть в логи и историю браузера.
Любой способ авторизации также требует раздела в личном кабинете. Пользователь должен видеть всех подключённых агентов, уметь отозвать любой токен, ограничить расходы агента и связать доступ с принятием оферты.
Итог. Поддерживаем OAuth 2.1 и ключ в заголовке, показываем подключённых агентов в личном кабинете и никогда не передаём секрет в URL (Uniform Resource Locator — адрес ресурса).
Юнит‑тест проверит, что инструмент вернул ответ нужной формы. Но он не заметит главного сбоя в поведении [8] агента: например, если тот не вызвал нужный инструмент или после изменения сигнатуры вызова стал хуже справляться со сценарием.
Поэтому кроме юнит‑тестов мы используем эвалы — сценарные проверки качества. Запускаем живого агента на реальных запросах, а вторая модель оценивает его действия по заданным критериям.
Важно различать источник ошибки:
агент получил нужные данные, но неправильно ими распорядился;
сервер не вернул данные, без которых задачу нельзя решить.
Сейчас у нас больше 60 сценариев, по которым мы оцениваем качество работы агента. Кроме того, мы собрали небольшой бенчмарк — набор одинаковых испытаний, который показывает, какие модели лучше справляются с конкретными задачами через наш MCP.
Чтобы результаты были воспроизводимыми, мы сохранили ответы API (Application Programming Interface — программный интерфейс приложения) и запускаем MCP в режиме моков, то есть с заранее подготовленными данными. Если агент формирует правильный запрос, он получает корректный ответ. Если ошибается, сценарий не проходит.
Во время разработки мы закрепили правило: для каждой новой возможности сразу описываем набор тестовых сценариев, а после крупных обновлений запускаем полный прогон. Так мы регулярно находим неожиданные эффекты и ошибки.
Итог. MCP поддерживает гибкий набор пользовательских сценариев, поэтому и тестировать его нужно сценариями — так можно заметить поломки именно в поведении агента.
Ограничение частоты запросов, или рейт‑лимит, по привычке хочется включить для всего сервера. Но у нас на одном адресе находятся и лендинг, и инструменты, поэтому лимит действует только на вызовы инструментов.
Если сервер отвечает кодом 429 Too Many Requests — “слишком много запросов”, — агенту стоит сразу сообщить, когда лимит сбросится, сколько запросов разрешено и как лучше перестроить работу.
Если ограничить всё подряд, пострадают и люди, и боты, и агенты. Пользователь несколько раз обновил лендинг, мессенджер запросил предпросмотр ссылки — и лимит уже исчерпан, хотя вводили его для агента, который слишком активно разбирает поисковую выдачу.
Поэтому мы привязали лимит к вызовам API Туту, а не ко всему серверу.
Итог. Ограничиваем агрессивный сбор результатов поиска, но не доступ к лендингу и описаниям инструментов.
MCP отличается от привычного REST API (Representational State Transfer — архитектурный подход к программным интерфейсам) не только способом взаимодействия. Такой сервер приходится объяснять сразу двум аудиториям: людям, которые подключают агента и получают результат, и самим агентам, которым нужно правильно выбрать и вызвать инструмент.
На практике качество MCP складывается не только из корректного кода. Нужны понятный лендинг, самодостаточные описания инструментов, компактные ответы, продуманная авторизация, юридически безопасный путь к покупке, сценарные тесты и прозрачные ограничения.
Делитесь в комментариях своими приёмами: как вы проектируете MCP и на какие грабли уже наступили? Особенно интересно, если ваш агент уверенно придумывал то, чего сервис никогда не возвращал.
P. S. Пишу про ИИ, код и кейсы агентной коммерции в телеграм‑канале «Поляков считает» [9].
Автор: artwistru
Источник [10]
Сайт-источник BrainTools: https://www.braintools.ru
Путь до страницы источника: https://www.braintools.ru/article/33665
URLs in this post:
[1] обучения: http://www.braintools.ru/article/5125
[2] MCP‑сервер: https://mcp.tutu.ru/mcp
[3] логично: http://www.braintools.ru/article/7640
[4] ошибку: http://www.braintools.ru/article/4192
[5] поведение: http://www.braintools.ru/article/9372
[6] памяти: http://www.braintools.ru/article/4140
[7] опыт: http://www.braintools.ru/article/6952
[8] поведении: http://www.braintools.ru/article/5593
[9] телеграм‑канале «Поляков считает»: https://t.me/+UBnIUhIiADwyOTMy
[10] Источник: https://habr.com/ru/companies/tuturu/articles/1063414/?utm_source=habrahabr&utm_medium=rss&utm_campaign=1063414
Нажмите здесь для печати.