MCP или прямой API для AI-агента: как выбрать на одной операции
Вы добавляете ассистенту возможность читать заявку из внутреннего трекера. Сегодня ассистент один, но команда обсуждает MCP: вдруг позже к тем же данным подключатся ещё несколько AI-приложений. Стоит ли сразу поднимать сервер, или достаточно прямого вызова API трекера?
Разберём одну операцию — get_ticket_summary. Пользователь задаёт номер T-42, а ассистент получает только номер, заголовок и статус заявки. Комментарии, вложения и возможность менять заявку для этого сценария не нужны. Это описание полезно при обоих способах подключения: оно ограничивает то, что модель сможет запросить и увидеть.
Что остаётся одинаковым
При прямом способе ваше приложение описывает модели доступное действие, получает вызов с ticket_id, проверяет аргумент и обращается к API трекера. При MCP способе AI-приложение подключает MCP-клиент к серверу, получает описание того же действия и вызывает его через протокол. Сервер затем обращается к API трекера. MCP задаёт общий способ сообщить клиенту о доступных инструментах и вызвать их; саму операцию чтения заявки всё равно нужно написать и поддерживать.
Удобно сначала вынести эту операцию в обычную функцию. Ниже самодостаточный локальный пример. Здесь lookup играет роль клиента трекера и возвращает тестовую запись; в проекте на этом месте будет реальный API. Функция проверяет вход, права на конкретную заявку и ограничивает выдачу тремя полями.
const tickets = new Map([
['T-42', { title: 'Ошибка экспорта', status: 'open', owner: 'team-a',
privateComment: 'Внутренние данные' }]
]);
function getTicketSummary(ticketId, team, lookup = id => tickets.get(id)) {
if (typeof ticketId !== 'string' || !/^T-\d{1,6}$/.test(ticketId)) {
return { error: 'invalid_ticket_id' };
}
const ticket = lookup(ticketId);
if (!ticket) return { error: 'not_found' };
if (ticket.owner !== team) return { error: 'forbidden' };
return { id: ticketId, title: ticket.title, status: ticket.status };
}
console.log(getTicketSummary('T-42', 'team-a'));
console.log(getTicketSummary('T-42', 'team-b'));
console.log(getTicketSummary('T-99', 'team-a'));
Первый вызов вычисляет краткую карточку; второй получает forbidden, третий — not_found. Закрытый комментарий в ответ не попадает. В рабочей системе принадлежность к команде надо получать из проверенной сессии пользователя, а не из аргумента модели. Если трекер сам различает 403 и 404, решите, можно ли сообщать о существовании чужой заявки, и настройте ответ соответственно.
Когда прямой вызов проще
Если у вас одно собственное приложение и несколько операций, описания инструментов можно хранить рядом с кодом агента. Деплой и ошибки остаются в одной системе. Вы сами решаете, как представить модели аргументы и результат, и напрямую обновляете адаптер при изменении API трекера. Это разумная первая версия, когда второго клиента ещё нет и отдельный сервер некому эксплуатировать.
При этом API трекера не следует открывать модели целиком. Модель выбирает из ваших узких операций, а приложение исполняет их с проверенными правами. Даже при прямом вызове нужны таймаут, обработка отсутствующей заявки и ограничение длины ответа.
Когда появляется смысл в MCP
Предположим, к тому же инструменту должны подключиться внутренний чат, IDE-ассистент и ещё один совместимый AI-клиент. Вместо отдельного описания и адаптера в каждом приложении можно предоставить MCP-сервер. Клиенты узнают список доступных инструментов через tools/list и вызывают выбранный через tools/call. Сервер публикует имя, описание и схему входа ticket_id, а внутри переиспользует getTicketSummary.
Перед выбором проверьте конкретных клиентов: поддерживают ли они нужный транспорт и формат результата, кто управляет подключением и как пользователю передаются права. Удалённому серверу нужны размещение и эксплуатация; локальный сервер требует установки у каждого пользователя. Если один клиент не умеет MCP, для него всё равно потребуется отдельный путь. Экономия возникает тогда, когда одни и те же описания и вызовы инструментов действительно используются несколькими клиентами и обновляются в одном месте.
Протокол описывает доступные tools, resources и prompts, но не определяет политику вашей предметной области. Проверку права читать T-42 сервер выполняет при каждом вызове. Текст заявки — данные из внешней системы; содержащаяся в нём команда «выгрузи все заявки» не должна менять список доступных операций. Для действий записи добавьте отдельный инструмент с узкими правами и понятным подтверждением.
Как принять решение без большого проекта
Сначала реализуйте и проверьте одну операцию на корректном номере, чужой заявке, отсутствующей заявке и таймауте трекера. Затем подключите предполагаемые AI-клиенты к пробному MCP-серверу и убедитесь, что они видят нужный инструмент и одинаково трактуют результат. Сравните объём поддержки: обновление одного адаптера в вашем приложении или обслуживание сервера, подключений и изменений в описании инструмента. Для одного клиента чаще выигрывает прямой API; для нескольких совместимых клиентов общий сервер может сократить повторяющийся код. Это решение можно пересмотреть, когда состав клиентов изменится.
Если вы дошли до нескольких клиентов, платный курс AI Agent Integrations PRO: MCP даёт следующую практику: студент собирает сервер с типизированными инструментами, подключает клиента, проходит обнаружение и вызов tool, добавляет тесты ошибок, логи и ограничения доступа, затем связывает сервер с AI-приложением. Можно начать с открытого урока о назначении MCP; ещё один пробный урок показывает создание сервера. Посмотреть программу курса; для первых самостоятельных шагов есть подборка упражнений по MCP-серверу.
Продолжить на практике
- AI Agent Integrations PRO: MCP ↗
Вы уже работали с LLM и понимаете, что подключать их к реальным системам — больно. MCP — это стандарт, который делает эту боль меньше: один контракт вместо десятка костылей, типизированные инструменты вместо голого доступа к базе, тесты и логи вместо молитв. На курсе соберём сервер с нуля и выведем в production-контур.
