sovereign-mcp-gateway
sovereign-mcp-gateway
Прокси-шлюз для серверов Model Context Protocol. Направьте ваш MCP-клиент на шлюз вместо ваших серверов. Он подключается ко всем перечисленным вами апстримам, объединяет их каталоги инструментов в один и пропускает каждый вызов через цепочку проверок, прежде чем он достигнет сервера, который должен его выполнить.
pip install sovereign-mcp-gateway
sovereign-mcp-gateway --init # writes gateway.json from the servers you already run
sovereign-mcp-gateway --config gateway.json --check--init читает уже имеющуюся у вас конфигурацию MCP (Claude Desktop, Claude Code, Cursor, VS Code или Windsurf) и записывает gateway.json, который проксирует те же серверы, так что первый запуск даёт рабочую конфигурацию, а не ошибку конфигурации. Он не будет импортировать собственную запись шлюза, потому что это заставило бы его проксировать самого себя.
Сам шлюз является MCP-сервером, поэтому любой клиент, говорящий на MCP, работает без изменений.
Эта базовая установка — рабочий шлюз. Четыре дополнительных опции добавляют поверх него дополнительные слои — см. Установка.
Что это останавливает
Агент читает issue на GitHub, в теле которого содержится инструкция, адресованная модели, а не вам. Он поддаётся убеждению и вызывает git_commit.
коммитов после | внедрённый коммит присутствует | |
напрямую к | 2 | да |
через шлюз | 1 | нет |
Тот же инструмент, те же аргументы, тот же сервер. Разница в том, был ли кто-то в состоянии отказать.
Прочтите пошаговое руководство: Ваш агент читает issue — или запустите его:
pip install "sovereign-mcp-gateway[all]" mcp-server-git
python examples/poisoned_issue.pyRelated MCP server: Agentrim MCP
Почему прокси, а не библиотека
Библиотеку должен принять тот, кто написал сервер. Прокси защищает серверы, которые вы не можете изменить — а таких большинство, потому что полезные MCP-серверы — это опубликованные пакеты, которые поддерживает кто-то другой.
Это также даёт вам одно место для хранения политики и один журнал аудита для всех серверов, к которым может обращаться агент, вместо конфигурации на каждый сервер, которую никто не синхронизирует.
Настройка
Начните с того, что уже запущено
$ sovereign-mcp-gateway --init
Wrote gateway.json
imported 3 servers from Claude Desktop
/Users/you/Library/Application Support/Claude/claude_desktop_config.json
imported 1 server from VS Code (project)
upstreams: fetch, git, sqlite, time
skipped:
sovereign - this gateway - importing it would proxy itself
notion - no command, probably a remote/SSE server
git - already imported from another clientЧетыре вещи он не сделает: не импортирует сам себя, не импортирует удалённый сервер, который не может запустить как подпроцесс, не перезапишет существующий файл без --force и не запишет список deny_tools, который вы не выбирали. Он записывает файл, сообщает, что взял и что оставил, и останавливается.
Передайте --config PATH вместе с --init, чтобы записать в другое место, а не в ./gateway.json.
После запуска замените эти серверы в вашем клиенте одной записью для шлюза. Если оставить оба, ваш агент будет общаться с ними напрямую, а также через прокси, и журнал аудита покажет только половину трафика.
{
"servers": {
"git": {"command": "mcp-server-git", "args": ["--repository", "/repo"]},
"sqlite": {"command": "mcp-server-sqlite", "args": ["--db-path", "/data.db"]}
},
"policy": {"deny_tools": ["git__git_reset"], "pii_policy": "warn"},
"audit": {"path": "gateway-audit.jsonl"}
}Проверьте подключение, прежде чем клиент его увидит:
sovereign-mcp-gateway --config gateway.json --checkSOVEREIGN GATEWAY - configuration check
upstreams: 2
layers: policy -> intent -> text-filter -> frozen-verify -> audit
EXPOSED AS UPSTREAM TOOL
git__git_status git.git_status
git__git_reset git.git_reset [DENIED]
sqlite__read_query sqlite.read_query
...
18 tools exposed.Цепочка
policy → intent → text-filter → frozen-verify → [ call executes ] → output-verify → logic-rules → auditLayer | Package | Отказывает, когда |
policy | — | инструмент в списке запрещённых или отсутствует в списке разрешённых |
intent |
| вызов не проходит поведенческий минимум |
text-filter |
| аргумент содержит инъекцию на любом из 21 языков или в семи кодировках |
frozen-verify |
| вызов не соответствует определению инструмента, замороженному при запуске |
output-verify |
| результат не проходит проверку схемы, обмана, PII или содержимого |
logic-rules |
| результат противоречит правилам, которые вы настроили |
audit |
| — записывает каждый вызов, разрешённый или отклонённый, в журнал с хеш-цепочкой |
Установка
Базовая установка — это рабочий шлюз, а не заглушка:
pip install sovereign-mcp-gatewayЭто даёт вам policy → frozen-verify → audit, который уже отклоняет инструмент, не предоставляемый ни одним апстримом, аргумент неверного типа, незадекларированный параметр, инструмент из вашего списка запрещённых и инъекцию в аргументе. Больше ничего не нужно.
Каждая дополнительная опция добавляет слой поверх:
Extra | Добавляет | Стоит того, когда |
|
| Ваши агенты читают текст откуда угодно, где вы не контролируете. Базовая установка ловит |
|
| Вы хотите страховку, которая не зависит от правильной схемы каждого инструмента |
|
| Вы можете выразить, как выглядит правильный результат. Ничего не делает, пока вы не зададите |
|
| Вы включаете консенсус N-моделей с хостинг-провайдером |
Комбинируйте, что хотите, или берите всё:
pip install "sovereign-mcp-gateway[text]" # one extra
pip install "sovereign-mcp-gateway[text,intent]" # several
pip install "sovereign-mcp-gateway[all]" # every layerВсе четыре дополнительных пакета — небольшие чистые Python-пакеты — [all] не добавляет скомпилированных зависимостей и не требует запуска службы.
Частичная установка заметно деградирует. Шлюз выводит свои активные слои при запуске, так что вы всегда видите, что на самом деле работает:
layers: policy -> frozen-verify -> audit # base
layers: policy -> intent -> text-filter -> frozen-verify -> audit # [all]Если слоя нет в этой строке, он не работает — что бы вы ни думали, что установили.
Проверено от начала до конца
Против mcp-server-git и mcp-server-sqlite, работающих как реальные апстримы, управляемых реальным MCP-клиентом:
Call | Результат |
| разрешено |
| разрешено — строка действительно в базе данных |
| отклонено: в списке запрещённых |
| отклонено: ни один апстрим его не предоставляет |
| отклонено: неверный тип для замороженной схемы |
| отклонено: текстовый фильтр |
| отклонено: инструмент нельзя вызвать через пространство имён другого апстрима |
После этого репозиторий по-прежнему содержит один коммит, а база данных — ровно ту строку, которую должна, — проверено прямым открытием, а не доверием к отчёту шлюза. Одиннадцать записей аудита на десять вызовов; редактирование любой из них разрывает цепочку.
Эти случаи — тестовый набор, а не скриншот: pytest tests/ -v.
Слой C: консенсус N-моделей
Все остальные слои детерминированы и локальны. Слой C — исключение: он просит несколько независимых моделей извлечь один и тот же структурированный документ из результата инструмента, канонизирует каждый ответ и сравнивает SHA-256-хеши. Согласие определяется хешем, а не прозой.
Он выключен, если не настроен, потому что это единственный слой, который стоит денег и добавляет задержку на каждый вызов, и единственный, который отправляет вывод инструмента модели.
{
"servers": { "...": {} },
"consensus": {
"providers": [
{"type": "local", "model": "llama3.1:8b"},
{"type": "local", "model": "qwen2.5:7b", "base_url": "http://localhost:11434/v1"},
{"type": "openrouter", "model": "anthropic/claude-3.5-sonnet",
"api_key_env": "OPENROUTER_API_KEY"}
]
}
}Два типа провайдеров: local (любая OpenAI-совместимая конечная точка — Ollama, vLLM, LM Studio; base_url по умолчанию http://localhost:11434/v1) и openrouter (ключ читается из указанной переменной окружения и никогда не записывается в конфиг).
Три правила, которые шлюз применяет при запуске, а не обнаруживает во время выполнения:
Как минимум два провайдера. Одна модель не может не согласиться сама с собой; консенсус из одной модели сообщает о согласии на каждый вызов, что хуже, чем отсутствие слоя, потому что это выглядит как проверка.
Без дублирующихся моделей. Согласие двух экземпляров одной и той же модели — не независимая проверка.
Отсутствующий API-ключ не даёт запуститься. Он не откатывается к работе без слоя.
Все провайдеры работают с temperature = 0, это обеспечивается в конструкторе.
Проверьте, что ваши модели согласны, прежде чем доверять слою
--check выполняет один реальный консенсус-вызов к вашим настроенным моделям и сообщает, что произошло. Это важнее, чем звучит:
LAYER C - probing the configured models with one real call
--------------------------------------------------------------
OK. The configured models produced identical documents.
Layer C will pass ordinary output rather than refusing it.Консенсус сравнивает канонические хеши, поэтому две модели, которые обе семантически правы, но структурно различаются, никогда не согласятся. Более слабая модель, которая повторяет схему —
{"branch": {"type": "string", "value": "main"}} instead of {"branch": "main"}— не совпадает при каждом вызове, всегда, и шлюз отклоняет всё с причиной, которая правильно читается как «модели не согласились». Потому что они не согласились.
Проверка различает три исхода:
означает | |
OK | модели создали идентичные документы; слой пригоден к использованию |
MISMATCH | они не согласны по тривиальному документу и будут отклонять каждый вызов — замените модель или удалите секцию |
provider unreachable | ничего не проверено; неверен ключ, идентификатор модели или конечная точка |
Установите sovereign-mcp-gateway[consensus] или [all] — HTTP-провайдерам нужен requests, от которого основная библиотека намеренно не зависит.
--check также выводит список активных слоёв, так что вы можете подтвердить с одного взгляда:
layers: policy -> intent -> text-filter -> frozen-verify -> consensus -> auditЕсли consensus отсутствует в этой строке, он не работает, что бы ни говорил конфиг.
Пространства имён
При включённом namespace (по умолчанию) инструмент отображается как git__git_status. Два апстрима, предлагающие одно и то же имя инструмента, не могут конфликтовать, затенять друг друга или быть достигнуты через неправильное пространство имён. Отключайте его только при наличии одного апстрима.
Политика
"policy": {
"deny_tools": ["git__git_reset", "write_query"],
"allow_tools": null,
"pii_policy": "warn",
"fail_closed": true,
"rate_limit_interval": 0
}deny_toolsсопоставляется либо с открытым именем (git__git_reset), либо с исходным именем инструмента (git_reset, на каждом апстриме, где он есть).allow_toolsпри задании отказывает всему, что не входит в список.pii_policyпо умолчанию имеет значениеwarn, а неblock. Реальные инструменты возвращают персональные данные как обычный вывод — каждая записьgit logсодержит email автора — и блокировка таких данных делает шлюз непригодным к использованию. Установитеblock, если ваши инструменты никогда не должны выдавать PII.fail_closedопределяет, что происходит, когда сам слой завершается с ошибкой. По умолчанию: отказ.rate_limit_intervalравен0, что отключает собственную задержку между действиями поведенческого минимума. Эта задержка подходит для одного агента, делающего обдуманные шаги, и не подходит для прокси, где всплеск вызовов инструментов — обычный трафик.entropy_policyпо умолчанию имеет значениеwarn. Эвристика энтропии текстового фильтра ищет закодированные полезные нагрузки, скрытые в прозе, но аргументы инструментов обычно структурированы — пути, идентификаторы, хэши — где высокая энтропия является нормой. Одного лишь пути к временной директории было достаточно, чтобы легитимный вызов был отклонён. Установитеblock, если ваши аргументы действительно являются прозой.
Что это не делает
Он проверяет вызовы на соответствие зафиксированным определениям и инспектирует аргументы и результаты. Он не читает исходный код ваших серверов, поэтому не может увидеть проверку, которая присутствует, вызывается и молча ничего не делает. Для этого всё ещё нужно, чтобы кто-то прочитал реализацию.
Он также не может защитить от скомпрометированного апстрима, возвращающего корректно выглядящие данные — консенсус Layer C в sovereign-mcp решает эту проблему и требует провайдеров моделей, которых вы настраиваете сами.
Лицензия
Business Source License 1.1 — см. LICENSE.
Исходный код публичен. Вы можете читать его, изменять, создавать производные работы и использовать его для разработки, оценки и любых других непроизводственных целей бесплатно.
Производственное использование также бесплатно для частного лица или организации из четырёх или менее человек — это прописано в лицензии как Additional Use Grant, а не просто заявлено здесь. Крупным организациям требуется коммерческая лицензия.
Каждая версия конвертируется в Apache 2.0 по наступлении её Change Date, через четыре года после публикации.
Чтобы лицензировать её для производства или узнать, нужна ли вам лицензия для вашего использования: contact@sovereign-shield.net
This server cannot be deployed
Maintenance
Related MCP Connectors
MCP server for mandates, delegation, policy-gated execution, credential grants, and audit.
Governed MCP gateway: one endpoint for your tools, with credential custody and audit log.
Guarded MCP server for agent-readable business truth, provenance, readiness, and discovery.
Authenticated MCP server for ClearPolicy policy and compliance workflows.
Related MCP Servers
- AlicenseNot gradedqualityCmaintenanceCentralized MCP control plane that proxies multiple upstream MCP servers with tool namespacing, filtering, policy enforcement, audit logging, and health checks.13 npmMIT
- AlicenseNot gradedqualityBmaintenanceA least-privilege enforcement proxy for MCP servers. It sits between MCP clients and upstream servers, enforcing tool policies, hiding denied tools, requiring human approval for risky actions, and providing a structured audit trail.MIT
- AlicenseNot gradedqualityAmaintenanceProvides a governance proxy layer for MCP servers, enforcing per-tool allowlists, human approval for write operations, quotas, secret redaction, and a hash-chained audit log of all calls.MIT
- AlicenseNot gradedqualityCmaintenanceProvides a security and context-control layer that multiplexes multiple MCP servers behind a single endpoint, scanning tool definitions and results, enforcing authorization, rate limiting, and audit logging, and dynamically retrieving tools to manage context window usage.MIT