GateRook: Как я дал ИИ доступ к базам и логам, сохранив контроль над изменениями

Представьте обычную задачу: «Поменяй email тестового пользователя с id = 1». Для разработчика это одна строка SQL. Для ИИ‑агента — несколько решений: найти подключение, выбрать окружение и базу, понять схему, составить запрос и выполнить его. Ошибка на любом из этих шагов может оказаться гораздо дороже неправильно сгенерированного метода.
Мне хотелось пользоваться ИИ не только как редактором исходников. Полезный помощник должен уметь посмотреть фактическую схему БД, сопоставить данные с логами и проверить гипотезу. Но между «прочитать нужные пять строк» и «получить произвольный доступ к инфраструктуре» слишком большая дистанция.
Поэтому я сделал GateRook — локальное desktop‑приложение и MCP‑шлюз между ИИ‑клиентами и рабочими ресурсами. Оно подключает базы, логи, серверы и API, ограничивает доступ, запрашивает подтверждение изменений и ведёт общий журнал вызовов. Исходники открыты под Apache 2.0: GitHub проекта. Установщики и документация находятся на официальном сайте.
Ниже — технический разбор того, какие проблемы я решает GateRook и как это выглядит на конкретных запросах. Я автор проекта, поэтому интерес к нему у меня прямой. Вместо обещаний «безопасного ИИ вообще» покажу устройство границы доступа и её ограничения.

Концептуальная иллюстрация проекта. Дальше — снимки интерфейса и реальные записи вызовов.
Где заканчивается помощь с кодом и начинается работа с системой
Claude, Codex, Cursor и Antigravity могут быть удобны в разных рабочих процессах. Меня здесь интересует общий для таких инструментов вопрос: какой доступ получает агент, когда ему недостаточно содержимого репозитория?
В коде описана ожидаемая структура системы. В работающем окружении может быть другая миграция, другой индекс, не тот конфиг, задержавшаяся задача или запись, которой разработчик не ожидал. Без доступа к этим данным агент строит гипотезы, а человек выполняет роль транспорта: запускает SQL, копирует вывод, ищет лог, переносит фрагмент в чат, повторяет цикл.
Если просто выдать агенту терминал и credentials, ручных действий станет меньше. Одновременно станет сложнее ответить на вопросы: какой именно ресурс ему доступен, что он может изменить, где остановится перед записью и как потом восстановить последовательность действий.
Вторая проблема появляется при нескольких клиентах. Одни и те же ресурсы приходится подключать повторно, настройки расходятся, секреты размножаются по конфигурациям, история оказывается разбросана между чатами.
Третья проблема — неоднозначность разрешения. Фраза «разрешаю работать с базой» не отвечает, можно ли обновить одну строку, изменить схему или выполнить запрос в production. Даже «подтверждаю этот SQL» бесполезно, если после подтверждения агент может отправить другой запрос.
Именно эти вопросы я перенёс из промпта в отдельный исполняющий слой.
Как устроен GateRook
MCP здесь — интерфейс, через который ИИ клиент обнаруживает инструменты и вызывает их. GateRook принимает вызов, связывает его с конкретным подключением, проверяет правила и только затем передаёт работу коннектору.
Упрощённый путь запроса:
ИИ-клиент
↓ MCP
GateRook: endpoint и область доступа
↓
Классификация → политики → подтверждение при необходимости
↓
Коннектор → база / логи / API / сервер
↓
Маскирование результата → клиент и журнал
У приложения есть три понятия, которые полезно разделять:
Connector знает, как работать с типом ресурса: например, MySQL, MongoDB или SSH‑логами.
Connection описывает конкретный ресурс, его окружение и способ аутентификации.
Endpoint определяет набор подключений и инструментов, доступных клиенту через конкретную MCP‑точку входа.
За desktop‑интерфейсом на Electron и Angular работает отдельное Java‑ядро. Конфигурация и журнал хранятся локально в SQLite. Проверки выполняет ядро, поэтому нарисовать в клиенте красивую кнопку «Approved» недостаточно, чтобы разрешить операцию.
Мне важна эта независимость от оболочки ИИ. Можно сменить клиент, не пересоздавая каждое подключение и не перенося в новый чат пароли баз данных.

Overview: отдельные endpoints для dev и production, назначенные им подключения и состояние клиентов. На этом снимке Claude Desktop и Codex подключены; это ещё не свидетельство выполненных вызовов каждого клиента.
В примере на скриншоте dev‑endpoint объединяет SSH, файловые логи, Redis, MongoDB, MySQL и OpenSearch. Production вынесен отдельно. Названия вроде pb-mysql-local — алиасы подключений, которыми оперирует агент. Пароль не нужен в каждом запросе.
Подключить один раз и использовать из разных клиентов
Добавление ресурса организовано как последовательность: выбрать тип, заполнить параметры, проверить соединение, назначить endpoints. Для меня это важнее длинного списка галочек в описании: новое подключение должно становиться понятным инструментом, а не ещё одним фрагментом JSON, который нужно вручную размножать.

Часть доступных коннекторов в мастере: SQL‑базы, MongoDB, Redis, OpenSearch, Elasticsearch и SSH.
В проекте есть коннекторы для PostgreSQL, MySQL, Oracle Database, SQL Server, MongoDB, Redis, поисковых систем, логов, облачных ресурсов и Kubernetes. HTTP/OpenAPI и подключение внешних MCP‑серверов позволяют расширять набор интеграций. При этом расширение списка инструментов не отменяет необходимости понимать полномочия нового коннектора.
Для Claude Desktop, Codex, Cursor и Antigravity предусмотрены способы подключения в разделе AI apps. Конкретный путь зависит от возможностей клиента: транспорт, авторизация и поддержка встроенных MCP Apps могут различаться. Поддержка интеграции не означает одинаковый интерфейс во всех клиентах.
На снимках ниже есть фактические вызовы Claude Desktop и Cursor. По этим материалам нельзя утверждать, что все четыре клиента прошли один и тот же сценарий: на экране Insights у Codex нет вызовов в выбранном интервале, а Antigravity обнаружен, но не подключён. Я специально сохраняю это различие между возможностью подключения и свидетельством конкретного запуска.
Сценарий 1. Агент читает логи через ограниченный инструмент
Допустим, нужно проверить, когда запускался сервис импорта. В ручном процессе я бы открыл SSH, нашёл нужный файл, сформулировал поиск и перенёс результат в чат. Здесь агент вызывает специализированный инструмент ssh_logs_search.
На скриншоте виден такой запрос:
{
"connection": "pb-log-dev",
"file": "pb-data-import-service.log",
"offset": 0,
"tail": true,
"maxLines": 5,
"from": "-2d",
"scanBytes": 67108864,
"query": "Started DataImportApplication",
"matchMode": "literal",
"caseSensitive": true
}
Параметры задают не абстрактное «посмотри сервер», а конкретный файл, буквальную строку поиска, временное окно, направление чтения и ограничения. scanBytes = 67108864 — бюджет сканирования 64 MiB, maxLines = 5 — ограничение числа возвращаемых строк. Эти числа описывают запрос, а не доказывают, что весь лог содержит только пять подходящих событий.

Карточка вызова: Claude Desktop, dev‑подключение, точные аргументы и длительность 29,9 секунды. На снимке нет тела результата, поэтому я не делаю по нему вывод о найденных строках.
Практический выигрыш — в управляемом способе получения контекста. Агент может уточнять гипотезу через тот же интерфейс, а мне видно, какой запрос он действительно выполнил. Пароль SSH не нужно вставлять в промпт, а доступ к поиску в логах не требует выдачи произвольного shell.

Фильтр по подключению показывает три операции: получение списка логов и два поиска. Время 4,9, 3,4 и 29,9 секунды — наблюдения одного сеанса, не бенчмарк скорости шлюза.
Для действий через SSH предусмотрены также runbooks с типизированными параметрами. Это позволяет предложить агенту заранее определённую операцию вместо неограниченной командной строки. Но безопасность такого инструмента зависит и от содержания самого runbook: обёртка не делает опасную команду безопасной автоматически.
Сценарий 2. Правильный SELECT ещё не означает правильный запрос
Один из самых показательных отказов в моей истории — не попытка удалить таблицу. Агент отправил обычный SELECT к MySQL, но не указал базу, с которой должен работать вызов.
Подключение допускало выбор из двух баз. В SQL было выражение SELECT DATABASE(), однако оно спрашивает СУБД о текущем контексте, а не задаёт явный выбор базы для шлюза. GateRook остановил запрос до выполнения.

Статус Denied by policy и пояснение Not run: denied in the gateway. Причина — правило dev.sql.database-not-selected: требуется выбрать базу для этого вызова.
Здесь мне важны сразу три свойства.
Первое: отказ случился до обращения с этим запросом к базе. Журнал показывает не просто красную строку после ошибки драйвера, а решение шлюза.
Второе: причина пригодна для исправления. Агенту не нужно угадывать, упал ли SSH‑туннель или закончились права. Нужно явно выбрать базу и сформировать корректный вызов.
Третье: такой отказ нельзя отменить произвольным пользовательским «одобряю». Условия допуска и подтверждение допустимой операции — разные механизмы. Если запрос нарушает обязательное ограничение, кнопка approval не должна превращаться в универсальный обход.
Это небольшой пример, но именно подобные неоднозначности встречаются в ежедневной работе. Полезная защита не обязана каждый раз выглядеть как остановка катастрофического DROP TABLE. Иногда она просто не даёт работать в неявно выбранном контексте.
Сценарий 3. Изменение email доходит до подтверждения, а не сразу до UPDATE
Теперь вернёмся к задаче из начала статьи. В чате я прошу поменять email пользователя с id = 1 в локальной MySQL. Агент готовит изменение через sql_execute. GateRook классифицирует его как запись, а выбранная политика требует решения человека.
В поддерживающем MCP Apps клиенте появляется карточка:

Waiting for approval: операция ещё не выполнена. Видны инструмент, подключение, идентификатор запроса и оставшееся время. Адреса в примере относятся к домену example.com.
Фраза агента «я отправил запрос на подтверждение» отличается от «я обновил запись». Карточка делает эту разницу явной: Not executed.
В самом GateRook я вижу точное действие:
UPDATE user SET email = 'text@example.com' WHERE id = 1;
Там же указаны окружение, endpoint, клиент, причина подтверждения и дополнительные сведения. В приведённой фотографии интерфейс показывает оценку одной затрагиваемой строки по EXPLAIN и timeout 5 секунд. Оценка планировщика — подсказка для проверки, а не гарантия фактического числа изменений.

Панель Approvals: точный SQL, причина остановки, оценка воздействия и кнопки решения. Иллюстрация на основе фотографии: Dock скрыт при обработке.
Почему я не ограничился кнопкой «разрешить инструмент»? Потому что подтверждать нужно конкретный payload. В GateRook сохраняются каноническое представление запроса и связанные с ним условия. Перед запуском ядро повторно проверяет актуальность разрешения и конфигурации, затем исполняет сохранённое действие. Клиент не получает право заменить одобренный SQL на другой.
Последовательность выглядит так:
Агент предлагает операцию и аргументы.
Шлюз проверяет область доступа, классификацию и политики.
Если нужно решение человека, создаётся ожидающий запрос с ограниченным временем жизни.
Человек изучает точное действие и выбирает разрешение или отказ.
Ядро повторно валидирует условия и выполняет сохранённый запрос либо отказывает.
Результат и решение отражаются в журнале.
Кнопка Approve in GateRook внутри карточки открывает проверку в GateRook. Само наличие виджета в чате не даёт ему полномочий подтверждать запись. Для клиентов без такого виджета остаётся текстовый путь со статусом запроса.
Если я не отвечу до истечения времени, запрос не получает разрешение. Если операция завершилась неоднозначно, нельзя бездумно повторять запись: тайм‑аут клиента не доказывает, что база ничего не сделала. Поэтому автоматический повтор мутации не должен быть способом «исправить» неизвестный исход.
Два изображения этого раздела показывают механизм ожидания и проверки на примере изменения email. Они сделаны в разные моменты и не изображают один непрерывный запуск до успешного COMMIT. Утверждать по ним, что запись уже обновлена, было бы неверно.
Политики: меньше доверия тексту, больше явных условий
Инструкция агенту «никогда не трогай production» полезна как описание намерения. Но исполняющее ограничение должно существовать независимо от того, как модель поняла эту фразу и какой текст встретила в логах или документации.
В GateRook решение связано с endpoint, подключением, инструментом, окружением и содержанием операции. Классификатор различает чтение, изменение и запрещённый запрос. Неопределённый или неподдерживаемый вариант не должен автоматически попадать в категорию чтения.
Режимы позволяют задать разные рабочие процессы:
Off убирает инструмент из доступного набора.
Read‑only позволяет чтение; попытка изменения обрабатывается согласно правилам подтверждения и ограничениям.
Approval требует решения человека для вызовов, к которым применяется этот режим.
Bypass позволяет выполнять допустимые операции без диалога подтверждения, сохраняя остальные проверки.
У отдельного read‑only endpoint запрет на изменения жёстче: его не следует путать с названием режима отдельного инструмента. Точно так же Bypass не отменяет ограничения, маскирование и аудит и не превращает запрещённый классификатором запрос в разрешённый.
Для повторяющейся работы на dev и stage есть временный bypass в узкой области: endpoint × connection × tool. Он ограничен по времени и не распространяется на production. Уже ожидающие запросы всё равно требуют своего решения.
Это компромисс с усталостью от подтверждений. Если спрашивать разрешение на каждое безобидное чтение, человек начнёт нажимать автоматически. Я предпочитаю заранее настроить область обычной работы и оставлять остановку там, где она помогает проверить последствия.
При этом права в самой инфраструктуре остаются обязательным слоем. Для чтения production разумно использовать отдельного пользователя БД с минимальными grants. Шлюз дополняет эти права проверкой контекста и процесса, а не заменяет ими настройку СУБД.
Секреты, результаты и журнал — три разных потока данных
Фраза «credentials остаются локально» легко создаёт неверное впечатление, будто за пределы компьютера вообще ничего не уходит. Поэтому я разделяю три вещи.
Секреты подключения. Пароли и другие сохранённые значения находятся в локальном зашифрованном хранилище. Мастер‑ключ отделён от SQLite; предусмотрена дополнительная защита средствами ОС. В интерфейсе секрет можно заменить или ротировать, но не раскрыть кнопкой просмотра. Есть ссылки на внешние хранилища, включая Vault/OpenBao, GCP Secret Manager и AWS Secrets Manager.
Доступ клиента к GateRook. Это отдельная авторизация. Например, короткоживущий токен шлюза не является паролем MySQL. Отзыв доступа клиента и ротация пароля ресурса — разные операции, и их не стоит смешивать в один общий API key.
Результаты инструментов. Разрешённые строки SQL, документы и фрагменты логов возвращаются ИИ‑клиенту. Если клиент отправляет контекст облачной модели, эти данные могут попасть к её провайдеру. Локальный шлюз сам по себе не делает облачный ИИ офлайн‑системой.
Перед выдачей и сохранением применяются механизмы маскирования: известные секреты и настроенные чувствительные поля заменяются. Смысл в том, чтобы не сохранять оригинал в аудит и лишь затем прятать его интерфейсом.
Однако маскирование не понимает автоматически всю бизнес‑семантику данных. Нельзя обещать, что любое персональное значение, произвольное преобразование секрета или конфиденциальный смысл текста будет распознан. Для конкретного ресурса нужно настроить доступные поля, правила и объём выдачи.
На снимках Activity есть уведомление Masked before storage. Это описание механизма. Надпись No values masked в конкретной карточке означает, что в этой записи значения не были заменены; сама по себе она не доказывает отсутствие чувствительных данных.
После работы остаётся журнал, а не только рассказ агента
Когда агент пишет «проверил базу и логи», хочется иметь возможность проверить, что именно он сделал. Activity собирает вызовы разных клиентов в одном месте: инструмент, подключение, окружение, endpoint, решение, аргументы и длительность.

Снимок от 2 ноября: 34 вызова, из них 28 разрешены, 2 отклонены политикой, 2 истекли и 2 завершились ошибкой. Это статистика конкретного выбранного периода.
Здесь видна работа с MySQL, MongoDB и GCP Cloud Logging в рамках одного журнала. Можно отфильтровать события по подключению, клиенту, инструменту и решению, затем перейти в карточку с аргументами и объяснением отказа.
Отдельный экран Insights помогает увидеть распределение вызовов:

Другой сеанс, 31 октября: 63 вызова; 58 от Claude Desktop и 5 от Cursor. Красная группа объединяет отказы и ошибки, поэтому её нельзя называть числом предотвращённых опасных действий.
Именно поэтому мне важно разносить результаты по смыслу. Denied by policy — сработало правило допуска. Error — ошибка выполнения. Expired — истекло ожидание. Эти состояния требуют разных действий от разработчика. Единая красная цифра без возможности открыть подробности только создаёт иллюзию наблюдаемости.
В ядре предусмотрены проверки целостности аудита. Но локальный журнал не стоит выдавать за независимое WORM‑хранилище или внешнюю сертификацию безопасности. Его основная польза в этом рабочем процессе — сделать взаимодействие агента с ресурсами проверяемым и объяснимым.
Скриншоты статьи сделаны на версиях 0.5.0 и 0.6.0; версия видна в нижней части окна. Это история развития одного приложения, а не набор кадров одного тестового прогона. Описание архитектуры версии 0.6.0 доступно в репозитории.
Что ещё помогает в повседневной работе
Ограничения объёма и времени. Даже чтение может быть дорогим: агент способен запросить слишком много строк, просканировать большой лог или запустить тяжёлую агрегацию. GateRook предусматривает лимиты выдачи, времени, частоты и параллелизма. Конкретные ограничения зависят от инструмента и конфигурации. Это помогает удерживать запросы в заданных рамках, но не заменяет анализ плана SQL и ресурсные ограничения самой базы.
Проверка соединений. Состояние ресурса видно отдельно от успешности рассуждений модели. Если соединение недоступно или работает медленно, можно начать с сети, VPN, credentials или самого сервиса, а не переформулировать промпт в надежде на другой результат.
Проверка вызова в Playground. Возможность воспроизвести запрос вне диалога помогает локализовать проблему: ошибка в аргументах, политика, коннектор или поведение клиента. Это особенно удобно при отладке интеграции.
Разделение окружений. Dev, stage и prod — часть модели доступа. Я могу дать агенту полезный набор ресурсов для исследования, не добавляя туда всё, что доступно моей рабочей станции. Один и тот же коннектор при этом обслуживает разные подключения с разными правилами.
Локальная точка управления. Для обычного desktop‑сценария не нужен отдельный постоянно работающий сервер управления. Приложение использует доступность ресурсов с моей машины. Обратная сторона очевидна: если компьютер спит, шлюз остановлен или VPN отключён, рассчитывать на продолжение этого доступа нельзя.
Почему недостаточно обычного MCP‑сервера или прав read‑only
Узкий MCP‑сервер для одной задачи может быть полностью достаточным. Если нужен только поиск по одному набору документов, добавлять ещё один слой необязательно. Аналогично, в проекте с одной базой и хорошо ограниченным read‑only пользователем значительная часть рисков уже решается на стороне СУБД.
GateRook становится полезнее, когда одновременно появляются несколько типов ресурсов, несколько клиентов, разные окружения и необходимость иногда разрешать изменения.
Подход | Что решает | Что нужно организовать дополнительно |
|---|---|---|
Копировать вывод в чат вручную | Человек выбирает каждый фрагмент контекста | Повторяемость, актуальность и время на перенос данных |
Дать агенту CLI и credentials | Гибкий доступ к инфраструктуре | Разделение полномочий, хранение секретов, ограничения команд и аудит |
Подключить отдельные MCP‑серверы | Инструменты для конкретных ресурсов | Согласованные правила и наблюдаемость между интеграциями |
Использовать GateRook | Общая точка подключения, правил, подтверждений и журнала | Настройка минимальных прав ресурсов и доверия к самому шлюзу |
Это не утверждение, что другие инструменты не имеют собственных ограничений или журналов. Мой выбор — вынести общую политику доступа в слой, который сохраняется при смене ИИ‑клиента.
Что GateRook не обещает
Я не считаю честным заканчивать такой обзор формулой «теперь можно без опасений подключить всё».
Шлюз контролирует вызовы, проходящие через него. Если агенту отдельно доступен терминал с теми же credentials, альтернативный MCP‑сервер или прямой сетевой путь, эти действия не становятся подконтрольными GateRook автоматически.
Он не делает модель безошибочной. Агент может выбрать неверную гипотезу, неправильно истолковать результат или предложить бессмысленный UPDATE. Поэтому в approval показывается точное действие, а пояснение агента не должно восприниматься как независимая экспертиза.
Он не гарантирует устранение prompt injection. Текст из логов и внешних источников остаётся недоверенным вводом. Ограничения инструментов сокращают доступные последствия, но не доказывают, что модель никогда не последует чужой инструкции.
Он не заменяет защиту рабочей станции. Процесс, которому уже доступен ваш пользовательский сеанс и локальные файлы, находится внутри другой границы доверия. Шифрование хранилища полезно, но не превращает скомпрометированную ОС в надёжную среду.
Наконец, он добавляет собственную сложность: коннекторы, политики, обновления и зависимости. Именно поэтому я публикую исходники и архитектуру. Слой, через который проходит доступ к инфраструктуре, должен быть доступен для технического разбора.
Что я хочу получить в итоге
Для меня главная польза GateRook — возможность дать агенту достаточно контекста для реальной инженерной работы, сохранив понятную границу исполнения. Прочитать схему, найти события в логах и сопоставить данные он может через инструменты. Изменение должно пройти ту процедуру, которую я заранее выбрал для этого ресурса.
Мне не хочется заново решать эту задачу при каждой смене клиента. Сегодня это Claude или Cursor, завтра другой интерфейс, а базы, окружения и требования к доступу остаются. Поэтому GateRook построен вокруг ресурсов и операций.
Проект можно посмотреть и проверить:
Официальный сайт GateRook — загрузка приложения и описание возможностей.
GitHub: msrv‑ai/gaterook — исходники под Apache 2.0, сборка и обсуждение проблем.
Мне особенно интересен опыт тех, кто уже подключает агентов к рабочим данным: какие операции вы готовы разрешать без остановки, где требуете подтверждение и какого свидетельства вам достаточно, чтобы поверить фразе «агент действительно это сделал»?
Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.
KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.