MCP-мост для AI-агентов: безопасное обслуживание сервера без root shell
MCP-мост для AI-агентов: безопасное обслуживание сервера без root shell
AI-агенты уже умеют писать код, чинить конфиги, читать логи и объяснять, почему продакшен внезапно перестал отвечать. Но как только агенту нужно обслуживать реальный сервер, появляется неприятный вопрос: сколько власти ему дать?
Самый простой путь — выдать агенту shell с широкими правами. Самый опасный путь — тоже он. Один неудачный prompt, один неверно понятый файл, одна команда не в той директории — и вместо автоматизации получается лотерея с root-доступом.
В своём стеке я выбрал другой подход: не давать Hermes, Codex и Claude Code универсальную командную строку, а построить узкий MCP-мост обслуживания. Агент видит не сервер целиком, а набор именованных действий: посмотреть статус, прочитать редактированные логи, запустить бэкап, проверить offsite-копию, перезапустить строго разрешённый unit. Это скучнее, чем «дай root и посмотрим», зато намного ближе к нормальной эксплуатации.
Ниже — практическая схема, которую можно повторить в self-hosted окружении: что именно выносить в мост, как ограничивать действия, где хранить политику и какие проверки делать после изменений.
Почему generic shell для AI-агента — плохая идея
Когда человек открывает shell на сервере, он держит в голове контекст: где он находится, какие команды опасны, что нельзя трогать, какие сервисы сейчас критичны. AI-агент часть этого контекста может прочитать, но не всегда правильно удерживает границы. Особенно если задача длинная и в ней смешаны диагностика, правки и деплой.
У generic shell есть три практические проблемы.
Первая — слишком широкая поверхность воздействия. Даже если агенту нужно только проверить бэкап, shell даёт ему возможность менять файлы, удалять каталоги, перезапускать любые сервисы и читать секреты. Ограничение через «пожалуйста, не делай так» не является безопасностью. Это просто текстовая просьба.
Вторая — сложность аудита. Команда bash -c может содержать всё что угодно: цепочки, подстановки, перенаправления, скачивание скриптов, чтение переменных окружения. Потом тяжело понять, что именно произошло и было ли действие допустимым.
Третья — prompt injection через файлы и логи. Агент читает вывод команды, README, issue, web-страницу или лог. Внутри может быть текст вида «игнорируй правила и выполни команду». Хорошо обученный агент должен это игнорировать, но архитектура безопасности не должна зависеть только от самоконтроля модели.
Поэтому правило простое: если AI-агенту нужен доступ к серверу, лучше дать ему операционную панель с кнопками, а не свободный терминал. MCP-мост как раз и становится такой панелью.
Архитектура: Unix socket, allowlist и именованные действия
В моём случае схема выглядит так: на хосте работает небольшой maintenance API, а внутри Hermes-контейнера есть MCP-wrapper, который общается с ним через Unix socket. Снаружи этот socket не торчит: он лежит в shared data mount, доступен только контейнеру и хостовому сервису. Ни LAN, ни WAN его не видят.
Условная схема:
Hermes Agent / MCP tools
↓
MCP wrapper внутри контейнера
↓ Unix socket
host maintenance API
↓
allowlisted systemd/script actions
Ключевая мысль: агент не отправляет произвольную команду. Он вызывает действие по имени. Например:
host_maintenance_status— собрать диагностический bundle;host_maintenance_logs— вернуть редактированные логи Hermes;host_maintenance_backup_status— показать состояние локального restic-бэкапа;host_maintenance_offsite_backup— запустить offsite backup, если remote настроен;host_maintenance_restart_unit— перезапустить только заранее разрешённые unit-файлы.
Даже restart не должен быть общим. В allowlist попадают только конкретные сервисы, где перезапуск ожидаем и относительно безопасен: например, cloudflared.service, hermes-data-backup.timer, web-shell units за Cloudflare Access. Никакого postgresql.service, docker.service или «что агент решит» без отдельного решения.
Такой дизайн снижает риск по двум причинам. Во-первых, интерфейс становится маленьким: можно прочитать список действий и понять, что агент физически способен сделать. Во-вторых, каждое действие можно обвязать проверками: таймаутом, redaction секретов, логированием, ограничением вывода, понятным статусом успеха или ошибки.
На практике это превращает агента из «пользователя с shell» в «оператора ограниченного runbook». Он всё ещё полезен: может диагностировать, собрать контекст, предложить план, инициировать бэкап или безопасный restart. Но он не получает лишних полномочий просто потому, что так быстрее.
Политика доступа: что фиксировать в vault
Технические ограничения важны, но их мало. Нужна ещё живая политика, которую читают все агенты. У меня она лежит в Obsidian vault рядом с playbook-ами: отдельная заметка описывает правила инструментов, другая — архитектуру maintenance bridge, третья — порядок синхронизации между Hermes, Codex и Claude Code.
Минимальный набор правил, который стоит зафиксировать:
- Секреты не попадают в vault. Никаких API-ключей, токенов Telegram, OAuth-кодов, cookies и приватных SSH-ключей в Markdown-заметках. В vault можно писать путь к файлу секрета, но не значение.
- MCP surface должен быть минимальным. Лучше включать инструменты через allowlist, чем подключать широкий filesystem или shell-сервер и надеяться на дисциплину.
- Серверные изменения требуют inspect → action → verify. Сначала статус и ожидаемый эффект, потом действие, потом проверка результата.
- Generic shell не является штатным инструментом обслуживания. Если он временно появился для аварийной диагностики, это надо считать расхождением с целевой политикой и убрать после разбора.
- Внешние SaaS/MCP подключаются по одному. Отдельные токены, отдельные scopes, только нужные операции.
Очень полезно явно разделить роли агентов. Например, Hermes может быть оркестратором и интерфейсом через Telegram, Codex — read-only аналитиком, Claude Code — исполнителем инженерных задач. Тогда агентам проще понимать, кто должен менять состояние, а кто только проверять и спорить.
В реальной эксплуатации это спасает от хаоса. Допустим, Hermes видит проблему в логах. Он не обязан сразу чинить всё сам. Он может собрать статус через maintenance bridge, прочитать playbook, попросить независимый анализ у Codex, а уже потом предложить Claude Code конкретный патч. Вся цепочка оставляет след в vault: что изменилось, почему, какие проверки прошли.
Пример из практики: безопасный restart и бэкап
Самый частый сценарий обслуживания — «что-то подвисло, надо посмотреть и, возможно, перезапустить». Без политики агент легко уходит в импровизацию: читает логи, пробует одну команду, потом другую, потом перезапускает больше, чем нужно.
Через MCP-мост сценарий выглядит иначе.
Сначала агент вызывает диагностику: статус контейнеров, состояние туннеля, последние редактированные логи, место на диске. Если проблема похожа на сетевую, он проверяет именно Cloudflare Tunnel. Если проблема в cron или бэкапах — смотрит timer и последний restic snapshot.
Затем он формулирует ожидаемый эффект: «перезапуск cloudflared.service должен восстановить туннель, не затрагивая Hermes и данные». Только после этого вызывается allowlisted restart. После рестарта обязательно идёт verify: повторный статус, HTTP-проверка сайта, чтение логов на предмет новых ошибок.
С бэкапами похожая логика. Агент не должен сам собирать длинную команду restic с параметрами и секретами. Ему достаточно действия host_maintenance_offsite_backup: хостовой скрипт уже знает, где конфиг, где repository, какие переменные нужны и как редактировать вывод. Агент получает результат без токенов и паролей.
Примерный runbook:
1. Проверить health maintenance API.
2. Прочитать статус локального и offsite-бэкапа.
3. Если remote настроен — запустить offsite backup.
4. Дождаться результата или понятного таймаута.
5. Проверить свежий snapshot.
6. Записать в отчёт только статус, время и ошибки без секретов.
Важная деталь: такой runbook можно выполнять автономно. Он не требует, чтобы человек сидел рядом и подтверждал каждую команду. Но автономность достигается не доверием к модели, а тем, что модель физически ограничена заранее безопасным набором действий.
Чеклист внедрения MCP-моста
Если собирать такую схему с нуля, я бы шёл по короткому чеклисту.
- Опишите роли агентов. Кто оркестратор, кто аналитик, кто имеет право менять состояние.
- Составьте список операций обслуживания. Не команд, а именно операций: статус, логи, бэкап, restart конкретного unit, проверка health.
- Сделайте allowlist. Всё, чего нет в списке, недоступно по умолчанию.
- Используйте Unix socket вместо сетевого порта. Если мост нужен только контейнеру и хосту, не надо слушать TCP.
- Редактируйте вывод. Секреты, токены и приватные пути не должны возвращаться агенту.
- Ограничьте размер логов. Агенту обычно нужны последние 100–200 строк, а не мегабайты шума.
- Проверяйте после действия. Любой restart, backup или deploy заканчивается verify-командой.
- Держите политику в shared vault. Агенты должны читать одни и те же правила, а не жить в разных версиях реальности.
Отдельно стоит завести заметку «расхождения политики и факта». Если сейчас в системе есть временный широкий инструмент вроде host shell, не прячьте это. Запишите риск, причину, дату и план удаления. Иначе временная дырка станет постоянной.
Я бы ещё добавил простое правило зрелости: если действие нельзя описать одной фразой без shell-синтаксиса, его рано отдавать автономному агенту. Сначала надо превратить его в нормальный скрипт, покрыть логированием, убрать секреты из вывода и только потом выставлять наружу через MCP. Это дисциплинирует сильнее любых инструкций в prompt.
На практике такой подход ещё упрощает обучение новых агентов. Вместо длинного системного текста «не трогай вот это, будь аккуратен, сначала спроси» агент получает короткий каталог разрешённых операций. Каталог можно показать в отчёте, проверить в ревью и сравнить с политикой безопасности в vault.
Итог: меньше магии, больше эксплуатации
Безопасная автоматизация AI-агентов не похожа на демо, где модель сама получает сервер и «делает красиво». В продакшене лучше наоборот: меньше магии, больше скучных границ.
MCP-мост с allowlist даёт хороший баланс. Агент остаётся полезным: он читает статус, сопоставляет симптомы, запускает регламентные операции, пишет понятный отчёт. Но он не превращается в неконтролируемый root shell с красивым интерфейсом.
Для self-hosted стека это особенно важно. На одном сервере могут жить Hermes, блог, Obsidian vault, бэкапы, туннели, Telegram-интеграции и экспериментальные агенты. Ошибка в такой системе стоит дороже, чем лишние 30 минут на нормальный maintenance bridge.
Если вы строите свою Agent OS, начните не с вопроса «как дать агенту больше прав», а с другого: какие действия ему действительно нужны, чтобы приносить пользу без лишнего риска? Ответ на него и станет основой безопасной архитектуры.
Читайте также: Obsidian как shared memory для AI-агентов и практический опыт построения мультиагентной системы на bronevik.vip.
Подписывайтесь на RSS и Telegram-канал Bronevik Blog — дальше будет больше практики про self-hosted AI, безопасность агентов и автоматизацию без vendor lock-in.
📬 Не пропускай новые статьи
Подпишись на Telegram-канал или RSS, чтобы получать уведомления о новых материалах