Как я подключил ИИ-агентов к своей инфраструктуре через MCP
Из 8+ MCP-серверов, которые в итоге прижились в моей инфраструктуре, один сначала наотрез отказывался работать: TLS-терминатор перед базой не анонсировал нужное расширение согласования протокола, и клиент с прямым SSL не мог завершить хендшейк. Это оказалась самая частая история во всей затее: почти каждый MCP-сервер из коробки рассчитан на облачный продукт вендора, а трекер задач, платформа деплоя, аналитика, observability и биллинг у меня свои, self-hosted. Почти всё пришлось перепрошивать вручную, сервер за сервером, прежде чем агенты смогли реально что-то через них делать.
#Заточено под чужое облако
Схема повторялась почти везде: MCP-сервер зашит под OAuth с облачным эндпоинтом вендора. Логика понятна: у вендора один OAuth-провайдер на всех клиентов, и клиент собран под него. В self-hosted инстансе регистрировать OAuth-приложение просто не у кого. Трекеру задач в итоге хватило трёх вещей: URL моего API, идентификатор workspace и обычный API-ключ в заголовке. Поля оказались очевидными — неочевидным был путь к ним через документацию, которая описывает только облачный сценарий.
#Поднять чужой MCP-сервер самому
Аналитика оказалась самым долгим квестом. Официальный MCP вендора отвалился сразу: в конфиге нет поля под свой хост. Второй кандидат — npm-пакет с заявленной поддержкой self-hosted — встал гладко, но внутри не оказалось ни одного исполняемого файла: библиотека без сервера.
Сработал третий заход: тот же вендор публикует собранный Docker-образ своего MCP-сервера. Первый запуск закончился циклом «поднялся — остановился», в логах — попытка достучаться до Redis. Зависимость жёсткая: без Redis сервер не стартует ни в каком урезанном режиме. Указал на уже существующий в инфраструктуре — поднялся с первой попытки. Аутентификация оказалась самой простой частью: персональный ключ bearer-токеном в заголовке.
#Мелочи, что съели время
Две истории помельче, съевшие времени непропорционально размеру. У платформы деплоя CLI на первом запуске иногда рапортует, что не может подключиться, и первый порыв — перепроверять ключ и права. Причина скучнее: холодный старт не укладывается в таймаут health-check. Правильная реакция — повторить через несколько секунд.
Со стороны observability-платформы сюрприз был другого рода. Почти все MCP-серверы в этой подборке приходят npm-пакетом — npx и готово. Этот пришёл Go-бинарником, единственный во всей подборке: файл под свою архитектуру, права на выполнение, путь в конфиге агента — процедура на порядок отличается от привычного npx имя-пакета. Аутентификация держится на заголовке, чьё имя легко набрать неточно: ошибиться в регистре символов или в формате самого имени — и сервер просто не аутентифицирует запрос, без ошибки, которая указывала бы, в чём именно дело.
#Дашборд и API на разных хостах
С биллингом ошибка напрашивалась сама: в MCP-конфиг хотелось вписать тот же хост, что открыт в браузере для входа в панель биллинга. Хост оказался неподходящим. Настоящий API биллинга живёт на отдельном домене — похожем по названию, но другом, — и именно туда MCP-серверу нужен URL вместе со своим API-ключом в заголовке; хост дашборда, за которым стоит логин, для этого не годится, потому что MCP обращается к API напрямую, минуя браузерную сессию.
Это самая обычная форма self-hosted UI в этой подборке: отдельный SSO-шлюз закрывает вход во фронтенд логином и сессией, а API под тем же продуктом стоит у себя, на другом хосте, вообще без отношения к SSO-шлюзу. Из одной вкладки браузера эта граница не видна: дашборд открывается, всё работает, и только когда MCP-сервер пытается достучаться до API напрямую, выясняется, что нужный хост — не тот, что в адресной строке.
#Базы напрямую
К остальным базам MCP-серверы подключены без посредников: колоночная аналитическая база, кэш и векторная база, у каждой свой способ аутентификации и свой клиент. Набор переменных подключения на каждую — и всё работает сразу, без сюрпризов.
Postgres — тот самый случай из начала — единственное место, где чинить пришлось уровнем ниже: TLS-прокси перед базой, который об MCP ничего не знает. Хендшейк обрывался на согласовании протокола, то есть раньше, чем Postgres увидел бы запрос: такая ошибка не говорит ни о правах, ни о базе, только о том, что стороны не договорились. В конфиге прокси не хватало ровно одного имени протокола в списке согласуемых. Добавил, перезапустил — прошло.
#Один шлюз на всё
Ещё один слой стоит ниже всего перечисленного. Self-hosted кластерный LLM-шлюз, поднятый поверх open-source LLM-роутера, задеплоен на той же платформе, что и всё остальное здесь — просто ещё один сервис в общей инфраструктуре, без отдельного облака под него. Смысл в том, чтобы каждый внутренний сервис и каждый агент ходил к языковым моделям через одну и ту же точку входа, вместо того чтобы каждый держал свой набор ключей от своего провайдера.
Роль этого слоя проще всего понять через то, что стоит рядом с ним. MCP-серверы — это то, как агенты дотягиваются до моих систем: трекера задач, деплоя, баз. Шлюз — то, как те же агенты дотягиваются до самих языковых моделей. Один слой отвечает за то, куда агент может пойти внутри инфраструктуры, второй — за то, к каким моделям он может обратиться снаружи неё.
#Короткий поводок для агентов
На последнем шаге под ограничение попали сами агентские CLI-инструменты. Два форкнутых open-source CLI для ИИ-кодинга, которыми я пользуюсь, собраны так, что каждый физически может достучаться ровно до одного эндпоинта и одного креда, зашитых на этапе сборки, — до того самого внутреннего LLM-шлюза, и больше никуда. Любой другой исходящий путь блокируется на уровне сети: правило стоит в файрволе, снаружи процесса, и сам инструмент до него не дотягивается, а значит и обойти его не может.
Разница на практике большая. Агент, который физически способен достучаться только до инфраструктуры под моим контролем, — это на порядок меньшая поверхность атаки, чем агент со свободным исходящим доступом куда угодно, куда его случайно направит инъекция промпта или обычный баг. Все MCP-серверы из предыдущих разделов остаются на месте: агент по-прежнему видит трекер задач, деплой, базы и аналитику. Путь наружу, в открытый интернет, для него закрыт заранее — на уровне, до которого сам агент дотянуться не может в принципе.