sovereign-mcp-gateway
Шлюз-посредник для Model Context Protocol серверов
Шлюз-посредник для серверов Model Context Protocol. Подключайте ваш MCP-клиент к шлюзу, а не к вашим серверам. Он соединяется с каждым указанным вышестоящим сервером, объединяет их каталоги инструментов в один и пропускает каждый вызов через цепочку проверок, прежде чем тот достигнет сервера, который его выполнит.
pip install sovereign-mcp-gateway
sovereign-mcp-gateway --config gateway.jsonСам шлюз является MCP-сервером, поэтому любой клиент, говорящий на MCP, работает без изменений.
Базовая установка — это рабочий шлюз. Четыре дополнительных расширения добавляют дальнейшие уровни — см. Installing.
Что он останавливает
Агент читает GitHub-issue, в теле которого содержится инструкция, адресованная модели, модель, а не вам. Модель убеждается и вызывает git_commit.
коммитит после | внедрённый коммит присутствует | |
напрямую к | 2 | да |
через шлюз | 1 | нет |
Тот же инструмент, те же аргументы, тот же сервер. Разница лишь в том, было ли что-то в состоянии отказать.
Прочитайте описание: Ваш агент читает issue — или запустите:
pip install "sovereign-mcp-gateway[all]" mcp-server-git
python examples/poisoned_issue.pyRelated MCP server: Mavryn
Зачем прокси, а не библиотека
Библиотеку должен внедрить тот, кто написал сервер. Прокси защищает серверы, которые вы не можете изменить и которые вы не можете изменить — а это большинство из них, потому что полезные MCP-серверы — это опубликованные пакеты, которые поддерживает кто-то другой.
Также у вас есть одно место для хранения политик и одного журнала аудита для каждого сервера, до которого может дотянуться агент, а не отдельная конфигурация, которую никто не синхронизирует.
Конфигурация
{
"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 → auditСлой | Пакет | Отказ, когда |
политика | — | инструмент в списке запрещённых или отсутствует в списке разрешённых |
интент |
| вызов не проходит поведенческий этаж |
текстовый фильтр |
| аргумент содержит инъекцию на любом из 22 языков или семи кодировок |
замороженная проверка |
| вызов не согласуется с определением инструмента, замороженным при запуске |
проверка вывода |
| результат не проходит схему, проверку на обман, PII или содержимое |
правила логики |
| результат противоречит настроенным вами правилам |
аудит |
| — каждый вызов, разрешённый или запрещённый, записывается в хэш-цепочку |
Установка
Базовая установка — рабочий шлюз, а не заглушка:
pip install sovereign-mcp-gatewayЭто даёт вам политика → замороженная проверка → аудит, которая уже отказывает инструменту, который не предоставляет вышестоящий сервер, аргументу неверного типа, необъявленному параметру, инструменту из вашего списка запрещённых и инъекции, инъекции в аргумент. Больше ничего не нужно.
Каждое дополнительное расширение добавляет уровень:
Расширение | Добавляет | Стоит, когда |
|
| Ваш агент читает текст из любого места, которое вы не контролируете. Базовая установка отловит |
|
| Вам нужен барьер, который не зависит от правильной схемы каждого инструмента |
|
| Вы можете описать, как выглядит правильный результат. Ничего не делает, пока не установите |
|
| Вы включаете 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-клиентом:
Вызов | Результат |
| разрешено |
| разрешено — строка действительно в базе данных |
| отказано: в списке запрещённых |
| отказано: ни один вышестоящий сервер его не предоставляет |
| отказано: неверный тип для замороженной схемы |
| отказано: текстовый фильтр |
| отказано: инструмент не может быть достигнут через пространство имён другого вышестоящего сервера |
После этого в репозитории остаётся один коммит, а база данных содержит ровно ту строку, которую и должна — проверяется открытием напрямую, а не доверием отчёту самого шлюза. Одиннадцать записей аудита на десять вызовов; редактирование любой из них нарушает всю цепочку.
Это набор тестов, а не скриншот: 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) и 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 | ничего не проверено; неверный ключ, ID модели или конечная точка |
Установите 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, что отключает поведенческий пол собственного взаимодействия-задержки. Эта задержка верна для одного агента, который совершает продуманные шаги, и wrong для прокси, где burst обычных запросов — обычный трафик.entropy_policyпо умолчаниюwarn. Энтропийная эвристика текстового фильтра ищет закодированные полезные нагрузки, скрытые в прозе, но аргументы инструментов имеют стандартную структуру — пути, идентификаторы, хэши, где высокая энтропия является нормой. Временная директория может быть путь к файлу, что приводит к отклонению легитимного вызова. Устанавливайтеblock, когда ваши аргументы действительно являются прозой.
Что это не делает
Он проверяет вызовы по замороженным определениям и проверяет аргументы и результаты. Он не читает исходный код ваших серверов, поэтому не может видеть проверку, которая присутствует, называется и молча или тихо ничего не делает. Для этого всё равно нужно, чтобы кто-то читал реализацию.
Need final. Ensure output only Russian.# Шлюз-посредник для серверов Model Context Protocol
Направьте ваш MCP-клиент на шлюз, а не на ваши серверы. Он подключается к каждому указанному вами вышестоящему серверу, объединяет их каталоги инструментов в один и пропускает каждый вызов через цепочку проверок, прежде чем он достигнет сервера, который его выполнит.
pip install sovereign-mcp-gateway
sovereign-mcp-gateway --config gateway.jsonСам шлюз является MCP-сервером, поэтому любой клиент, говорящий на MCP, работает без изменений.
Эта базовая установка — рабочий шлюз. Четыре дополнительных расширения добавляют новые слои поверх — см. Installing.
Что это позволяет предотвратить
Агент читает GitHub issue, в теле которого содержится инструкция, направленная на модель, а не на человека. Убеждает её и вызывает git_commit.
коммитит после | внедрённый коммит присутствует | |
напрямую к | 2 | да |
через шлюз | 1 | нет |
Тот же инструмент, те же аргументы, тот же сервер. Разница в том, что было в состоянии отказать.
Прочитайте описание: Ваш агент читает issue — или запустите:
pip install "sovereign-mcp-gateway[all]" mcp-server-git
python examples/poisoned_issue.pyПочему прокси, а не библиотека
Библиотеку должен внедрить тот, кто написал сервер. Прокси защищает серверы, которые вы не можете изменить, — а это большинство из них, потому что полезные MCP-серверы — это опубликованные пакеты, поддерживаемые кем-то другим.
Это также даёт вам одно место для хранения политики и единый журнал аудита для каждого сервера, к которому может достать агент, а не отдельная конфигурация, которую никто не может держать в синхронизированном состоянии.
Конфигурация
{
"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 → auditСлой | Пакет | Отказ когда |
политика | любые | инструмент находится в списке запрещённых или отсутствует в списке разрешённых |
намерение |
| вызов не соответствует поведенческому полу |
текстовый фильтр |
| аргумент содержит инъекцию на любом из 22 языков или семи кодировок |
замороженная проверка |
| вызов не соответствует определению инструмента, замороженному при старте |
проверка вывода |
| результат не соответствует схеме, обману, PII или содержимому |
правила логики |
| результат не соответствует настроенным вами правилам |
аудит |
| — каждый вызов, разрешённый или запрещённый, записывается в хэш-цепочку |
Установка
Базовая установка — рабочий шлюз, а не заглушка:
pip install sovereign-mcp-gatewayЭто даёт вам политика → замороженный → аудит, который уже отклоняет инструмент, который не предоставляет вышестоящий сервер, аргумент неправильного типа, необъявленный параметр, инструмент из вашего списка запрещённых, и инъекцию в аргумент. Больше ничего не нужно.
Каждый дополнительный уровень добавляет поверх:
Дополнение | Добавляет | Стоит, когда |
|
| Вы читаете текст из любого места, которое вы не контролируете. Базовая установка ловит |
|
| Вам нужен барьер, который не зависит от того, чтобы схема каждого инструмента была правильной |
|
| Вы можете выразить, как выглядит правильный результат. Ничего не делает, пока вы не установите |
|
| Вы включаете 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-клиентом:
Вызов | Результат |
| разрешено |
| разрешено — строка действительно есть в базе данных |
| отказано: в списке запрещённых |
| отказано: нет вышестоящего, который его отдаёт |
| отказано: неправильный тип для замороженной схемы |
| отказано: текстовый фильтр |
| отказано: инструмент не может быть достигнут через пространство имён другого вышестоящего |
В итоге в репозитории остаётся один коммит, а база данных содержит ровно ту строку, которая должна быть — проверяется открытием напрямую, а не доверием к отчёту самого шлюза. Одиннадцать записей аудита на десять вызовов; изменение одной из них разрывает цепочку.
Это и есть набор тестов, а не скриншот: pytest tests/ -v.
Уровень C: межмодельный консенсус
Каждый другой уровень детерминирован и локален. Уровень 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) и 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"}— не совпадает на каждом вызове, и шлюз отказывает на каждой причине, которая правильно гласит, что "модели не согласились". Потому что они не согласились.
Зонд различает три исхода:
объяснение | |
ОК | модели создали идентичные документы; слой юзабилити |
MISMATCH | они расходятся на тривиальном документе и будут отклонять каждую просьбу — замените модель или удалите секцию |
provider unreachable | ничего не проверено; ключ, ID модели или конечная точка неверны |
Установите sovereign-mcp-gateway[consensus] или [all] — HTTP-провайдерам нужен requests, от которого основная библиотека намеренно не зависит.
--check также перечисляет активные слои, чтобы вы могли подтвердить с первого взгляда:
layers: policy -> intent -> text-filter -> frozen-verify -> consensus -> auditЕсли consensus отсутствует в этой строке, он не выполняется, независимо от того, что говорит конфигурация.
Пространство имён
При включенном namespace (по умолчанию) инструмент выглядит как git__git_status. Два вышестоящих, предлагающие одно и тоже имя инструмента, не могут столкнуться, затмить друг друга, или быть доступными через неправильное пространство имён. Выключайте только тогда, когда у вас один вышестоящий.
ПолитикаОтправочные
GXP14 Translate "Once installed as allow_tools..." etc.
deny_tools— соответствует закрытому имени (git__git_reset) или имени исконного инструмента (git_reset, на каждом вышестоящем, где он есть).allow_tools— когда установлено, отказывает всё, что не перечислено.pii_policyпо умолчанию установлено вwarn, расширениеblock. Реальные инструменты возвращают персональные данные как обычный вывод — каждая записьgit logсодержит email автора, и блокировка их делает шлюз непригодным. Установитеblock, когда ваши инструменты не должны никогда излучать PII.fail_closed— что происходит, когда сам слой ошибается. По умолчанию: отказывать.rate_limit_interval—0, что отключает поведенческое тавство в этаж. Эта задержка подходит для агента, предпринимающего намеренные шаги, и wrong для прокси, где внезапная серия инструментов — обычный трафик.entropy_policyпо умолчаниюwarn. Энтропическая эвристика текстового фильтра ищет закодировочные нагрузки в прозе, но аргументы инструментов регулярно структурированы — пути, идентификаторы, hashi — где высокая энтропия — норма. Времени директория может быть только временным путём, и это может быть реальным вызовом. Установите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 installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseNot gradedqualityBmaintenanceCentralized MCP control plane that proxies multiple upstream MCP servers with tool namespacing, filtering, policy enforcement, audit logging, and health checks.7MIT
- AlicenseNot gradedqualityCmaintenanceAuthenticating reverse proxy for MCP servers providing credential isolation, OAuth2 token management, and composite tool aggregation.BSD Zero Clause
- 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
Related MCP Connectors
A paid remote MCP for hosted MCP server, built to return verdicts, receipts, usage logs, and audit-r
Hosted AgentLux MCP server for marketplace, identity, creator, services, and social flows.
Remote MCP for A2A caller identity, scope policy, verdict receipts, and audit history.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/mattijsmoens/sovereign-mcp-gateway'
If you have feedback or need assistance with the MCP directory API, please join our Discord server