Перейти к содержимому
Tuskira открыла исходный код AI Agent Gateway для MCP-инструментов и LLM
9 мин чтения

Tuskira открыла исходный код AI Agent Gateway для MCP-инструментов и LLM

ai-agentsmcpllmopen-sourceapi-gatewayai-security

Обычно никто не садится утром с намерением внедрить десяток AI-агентов. Всё нарастает исподволь: один разработчик ставит Claude Code, другой выбирает Cursor, инженер платформы пишет Python-агента для разбора тикетов, а CI начинает сам создавать pull request. В итоге у каждого агента — свои ключи к моделям, свой набор MCP-серверов и, что особенно неприятно, собственное понимание дозволенного.

Поначалу это терпимо. Но затем кто-то задаёт вполне земной вопрос: какие агенты на этой неделе обращались к production-проекту в Jira? Что попытался сделать CI-агент, хотя делать этого не должен был? На что ушли токены за прошлый месяц? И тут начинается квест: биллинг провайдеров, конфиги на ноутбуках, разрозненные логи. Картина, мягко говоря, лоскутная.

Сегодня Tuskira публикует исходный код Tuskira AI Agent Gateway — единой точки управления для ответов на эти вопросы и настройки политик. Шлюз разворачивается в вашей инфраструктуре, не требует аккаунта Tuskira, а код доступен на GitHub по лицензии Apache 2.0.

Коротко для разработчиков

Запуск: один бинарный файл Go; есть манифесты Docker Compose и Kubernetes
Порты: 8080 для MCP, 8081 для REST API и консоли, 8082 для LLM
Зависимости: PostgreSQL обязателен; ClickHouse и Redis-совместимое хранилище — по необходимости
Агенты: Claude Code, Cursor, VS Code, Codex CLI и любые клиенты с поддержкой MCP либо SDK провайдера
Провайдеры: Anthropic, AWS Bedrock, OpenAI и Gemini — с вашими ключами
Статус: v0.4.0, alpha до 1.0, лицензия Apache 2.0

Когда каждый агент подключён по-своему

Возьмём типичный агент. Ему нужны API-ключи для провайдеров моделей, записи конфигурации для MCP-серверов и, как правило, отдельные учётные данные к каждому из них. Правила доступа живут в настройках самого агента — если они вообще сформулированы и не потерялись где-то между README и личным заметником инженера.

Умножьте это на агентов, ноутбуки и CI-runner’ы — получите три знакомые беды. Секреты разъезжаются по местам, за которыми никто толком не следит. Единого реестра вызовов и расходов нет. А политика доступа может существовать на бумаге, но в момент действия агента её никто не применяет.

Именно здесь нужен не очередной конфигурационный файл, а управляемая архитектура AI-агентов: единый маршрут запросов, проверяемые права и понятные границы ответственности.

До: четыре агента подключены к четырём инструментам с разными учётными данными. После: агенты работают через единый gateway с профилями, секретами, политиками и общим журналом.
Слева — привычная для многих команд схема. Справа — те же агенты и сервисы, но все запросы проходят через один gateway.

Единый gateway на маршруте запросов

Шлюз встаёт между агентами и всем, что они вызывают: MCP-серверами с инструментами и LLM-провайдерами. Агент добавляет его как MCP-сервер; если нужно учитывать ещё и обращения к моделям, SDK направляется на gateway. Инструменты, учётные данные и правила после этого берутся из центральной точки, а не из десятков локальных конфигураций.

Поставляется он одним Go-бинарником с тремя слушателями. Их можно публиковать раздельно — без лишней магии.

:8080MCP-плоскость

Endpoint для агентов. Он показывает каждому агенту только разрешённые инструменты и проверяет каждый поддерживаемый вызов до его передачи дальше.

:8081Плоскость управления и консоль

Здесь регистрируются MCP-серверы, создаются профили, выпускаются ключи и просматриваются журналы — через REST API либо встроенную административную консоль.

:8082LLM-плоскость

Необязательный компонент. Поддерживает нативные маршруты Anthropic — напрямую или через AWS Bedrock, — OpenAI и Gemini, используя ключи вашей организации.

Единственная обязательная внешняя зависимость — PostgreSQL. ClickHouse добавляет аналитические панели и временную шкалу сессий, а Redis-совместимое хранилище помогает масштабировать MCP-плоскость на несколько реплик.

Архитектура AI Agent Gateway: агенты обращаются к MCP-плоскости на порту 8080 и при необходимости к LLM-плоскости на 8082; gateway направляет запросы в MCP-серверы, Anthropic, AWS Bedrock, OpenAI и Gemini; управление доступно на 8081; PostgreSQL обязателен, ClickHouse и Redis опциональны.
Общая схема. Агентам достаточно MCP-плоскости; LLM-плоскость нужна, когда трафик к моделям тоже должен попадать в общий журнал.

Что происходит при вызове инструмента

Проще пройти путь одного запроса. Представим, что Claude Code с профилем coding просит создать pull request в GitHub.

Агент отправляет в MCP-плоскость два заголовка: ключ gateway и имя профиля. Gateway валидирует ключ, связанный с tenant’ом и ролью, а затем применяет ограничение частоты запросов — если оно настроено. После этого проверяется право профиля на конкретный инструмент. Нет права? Вызов заканчивается здесь. Агент получает ошибку, попытка фиксируется в журнале, а GitHub вообще ничего не узнаёт.

Если вызов разрешён, gateway извлекает зашифрованные учётные данные GitHub, добавляет их в исходящий запрос и передаёт его дальше. Токен у агента не хранится. Ответ возвращается через шлюз, а в общий журнал попадает запись об агенте, инструменте, решении и времени выполнения.

Такой подход важен не только для наблюдаемости. Это практический слой защиты AI-агентов от лишних прав: доступ проверяется в точке действия, а не надеется на добросовестность локальной настройки.

Жизненный цикл вызова инструмента: агент вызывает инструмент, gateway проверяет ключ и профиль, подставляет учётные данные и перенаправляет запрос; отклонённый вызов возвращает ошибку и сохраняется в журнале.
Любой этап на стороне gateway попадает в единый журнал доступа — независимо от того, был вызов разрешён или отклонён.

Отклонённый запрос возвращается агенту как стандартная ошибка JSON-RPC. Поэтому и агент, и инженер, который разбирает инцидент, видят, какой инструмент и какой профиль участвовали в попытке.

Отклонённый ответ tools/call
{
  "jsonrpc": "2.0", "id": 1,
  "error": {
    "code": -32003,
    "message": "tool not allowed by profile",
    "data": { "tool": "github__delete_repo", "profile": "read-only-analyst" }
  }
}

Профиль проверяется повторно именно в момент вызова, а не только при формировании списка доступных инструментов. Спрятать инструмент — удобно. Отказать в запуске — это уже настоящий контроль. И он сработает даже тогда, когда агента каким-то образом уговорили вызвать то, чего он никогда не видел.

Профили задают права каждого агента

MCP-сервер регистрируется один раз — в виде connector с единым набором учётных данных. Затем профили определяют, какие именно инструменты доступны разным типам агентов. Один GitHub connector может выдать агенту разработки чтение и запись, агенту ревью — чтение и комментирование, а CI-задаче оставить один-единственный инструмент. Ровно столько, сколько ей нужно.

Профили настраиваются в плоскости управления: вручную через консоль или программно через REST API.

API плоскости управления
# выбрать инструменты, разрешённые для профиля
curl -X PUT http://localhost:8081/api/v1/profiles/$PROFILE_ID/tools \
  -H "Authorization: Bearer $GATEWAY_KEY" -H "Content-Type: application/json" \
  -d '{"tools": [
        {"connector_id": "'$CONNECTOR_ID'", "tool_name": "search"},
        {"connector_id": "'$CONNECTOR_ID'", "tool_name": "get_issue"}
      ]}'

# привязать ключ агента к профилю, чтобы агент не выбирал его самостоятельно
curl -X PATCH http://localhost:8081/api/v1/api-keys/$KEY_ID \
  -H "Authorization: Bearer $GATEWAY_KEY" -H "Content-Type: application/json" \
  -d '{"profile_id": "'$PROFILE_ID'"}'

Свяжите ключ агента с его профилем — и это ограничение будет применяться при каждом запросе. Если ключ CI утечёт, масштаб ущерба ограничится правами данного профиля, а журнал покажет все обращения. Поменять разрешения можно в одном месте: изменения подхватят все агенты, использующие профиль, при следующем вызове.

Один GitHub connector с едиными сохранёнными учётными данными обслуживает три профиля: coding видит пять инструментов, review — четыре, ci — один.
Один connector, один набор сохранённых учётных данных, три профиля. В каждом запросе профиль определяет, что именно сможет сделать агент.

И дело не ограничивается инструментами. Prompts и ресурсы всех подключённых серверов объединяются в единое пространство имён; профили также могут включать skills и команды, которые агент получает нативно через MCP.

Модели через один endpoint

В LLM-плоскости gateway сохраняет нативный API каждого провайдера. Anthropic SDK продолжает обращаться к /v1/messages, а SDK OpenAI и Gemini отправляют привычные им запросы. По сути, меняется только base URL.

Направьте SDK в LLM-плоскость
# Anthropic SDK, Claude Code и другие клиенты с поддержкой этой переменной
export ANTHROPIC_BASE_URL=http://localhost:8082
# Для OpenAI, Gemini и Bedrock применяется тот же принцип: настройте
# base_url / endpoint_url для маршрутов /openai/, /gemini/ и /model/

Gateway подставляет ключ провайдера, пересылает вызов и записывает число входных и выходных токенов вместе с ориентировочной стоимостью.

Реестр моделей позволяет каждому tenant’у задавать внутренние имена моделей. Агент запрашивает зарегистрированное имя, а команда решает, какому провайдеру и какой модели оно соответствует. Перевести агентов на другую модель можно одной правкой в реестре, а не обходом всех конфигураций. Маленькая деталь, которая на практике экономит немало нервов.

SDK провайдеров направляют base URL на LLM-плоскость порта 8082, которая подставляет ключи, разрешает имена моделей, учитывает токены и примерную стоимость, а затем пересылает запрос провайдеру.
Код по-прежнему использует SDK провайдера. Gateway берёт на себя ключи, имена моделей, расчёт стоимости и журналирование.

Какие данные доступны команде

Каждый вызов через gateway сохраняется. Административная консоль показывает журналы доступа к инструментам, LLM-журналы с токенами и оценкой затрат, аналитику и временную шкалу сессий. Эти же события можно передавать в OpenTelemetry или ClickHouse, чтобы анализировать их привычными корпоративными средствами.

В демо-стеке по умолчанию сохраняются тела запросов и ответов, чтобы их можно было увидеть в консоли; размер каждого ограничен 1 MiB. Если внутренние правила запрещают хранить такие данные, функция отключается одной настройкой. В реальной среде это часто не мелочь, а обязательное условие соответствия требованиям к хранению данных при работе с AI.

Для работы внутри вашего периметра

Gateway не отправляет данные во внешние сервисы. Нет аккаунта Tuskira, нет облачной control plane и нет телеметрии использования. Конфигурация, политики и журналы остаются там, где их развернула ваша команда.

Из этого следуют и защитные настройки по умолчанию. Учётные данные backend-сервисов шифруются при хранении и подставляются отдельно для каждого запроса. API-ключи привязаны к tenant’у и роли, а пользователи консоли отделены от программных ключей. Исходящие обращения к loopback-, приватным и link-local-адресам блокируются, если их явно не разрешить; адрес метаданных облака заблокирован всегда. Поэтому ошибочно настроенный connector не должен стать лазейкой к другим workload’ам во внутренней сети.

Почему проект опубликован как open source

Tuskira создавала gateway для собственной платформы, работающей с агентами в клиентских средах, где контроль доступа — не декоративная опция. Довольно быстро стало понятно: проблема не уникальна. Любой команде, которая всерьёз внедряет агентов, нужна базовая инфраструктура контроля, а программное обеспечение, стоящее на пути каждого агентного вызова, должно быть доступно для построчного аудита.

AI-агенты появляются в production быстрее, чем организации успевают выстроить управление ими. Команды независимо подключают агентов к моделям и инструментам, не видя целой картины. Наблюдаемость и контроль должны быть частью базовой инфраструктуры — поэтому Tuskira открывает исходный код проекта.

Piyush Sharma, CEO и сооснователь Tuskira

Проект распространяется по лицензии Apache 2.0. Команда приветствует issues и pull request; в CONTRIBUTING.md описано, как добавить backend хранилища, sink для логов или нового провайдера.

Текущий статус

Это alpha-версия на пути к 1.0. Текущий релиз — v0.4.0; API и конфигурация ещё могут меняться между минорными версиями. Шероховатости вполне возможны — бывает, и это честно обозначено. Если вы их нашли, лучше завести issue. Проект работает на macOS и Linux; Windows через WSL2 пока не тестировалась. В поставку входят манифесты Docker Compose и Kubernetes, Helm chart запланирован. Точный состав текущего релиза приведён в docs/architecture.md.

Запуск за несколько минут

Понадобятся Docker с плагином Compose, curl и свободные порты с 8080 по 8082.

Терминал
git clone https://github.com/Tuskira/ai-agent-gateway.git
cd ai-agent-gateway
docker compose -f deploy/docker-compose.yml up --build -d

# дождитесь готовности плоскости управления и проверьте её
curl localhost:8081/api/v1/health

# создайте tenant и первый административный API-ключ — он выводится лишь однажды
docker compose -f deploy/docker-compose.yml exec gateway /gateway bootstrap-key

Дальше укажите gateway в качестве MCP-сервера агента. Для Claude Code достаточно одной записи в .mcp.json.

.mcp.json
{
  "mcpServers": {
    "gateway": {
      "type": "http",
      "url": "http://localhost:8080/mcp",
      "headers": {
        "X-Gateway-Key": "gk_...",
        "X-Agent-Profile-Name": "coding"
      }
    }
  }
}

В репозитории есть 13 подробных примеров для Claude Code, Cursor, VS Code, Codex CLI, Python-агента, профилей, учётных данных, наблюдаемости и Kubernetes. Начать проще всего с examples/01-quickstart.

Если агенты в вашей команде уже подключены «каждый по-своему», опишем для каждого агента правила доступа, подтверждения и журналирования — с любым шлюзом или без него.

Источник: tuskira.ai