关于 Sovereign Gateway
Sovereign Gateway 是面向需要集中管理上游服务的团队的 MCP 代理服务。它合并各服务的工具,并通过可配置的验证层检查调用,同时集中记录审计日志。
主要功能
- 01合并上游服务的工具
- 02应用允许与拒绝策略
- 03验证调用和输出
- 04过滤提示词注入
- 05以哈希链记录调用审计
- 06检查配置与启用的验证层
适用场景
- 01统一管理多个 MCP 服务的策略
- 02在调用到达上游前进行检查
- 03追踪获准与拒绝的调用
- 04在客户端接入前验证网关配置
MCP 相关
它作为 MCP 服务运行在客户端与已配置的上游服务之间,将各处工具集中提供给客户端。调用到达上游前会经过已配置的验证层。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
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 的客户端都可以直接使用,无需修改。
基础安装即可运行网关。四个可选扩展可在此基础上增加更多防护层——参见安装。
它能阻止什么
Agent 读取了一条 GitHub issue,其正文包含针对模型而非你的指令。Agent 受到诱导,调用了 git_commit。
| 提交后的数量 | 是否包含注入的提交 | |
|---|---|---|
直接连接到 mcp-server-git | 2 | 是 |
| 通过网关 | 1 | 否 |
工具相同,参数相同,服务相同。区别在于,是否有任何环节能够拒绝调用。
阅读演示:你的 Agent 读取了一条 issue——或直接运行:
pip install "sovereign-mcp-gateway[all]" mcp-server-git
python examples/poisoned_issue.py
为什么选择代理,而不是库
库必须由服务的编写者集成。代理可以保护你无法修改的服务——这类服务占大多数,因为实用的 MCP 服务通常是由他人维护的已发布软件包。
它还让你可以在一个地方管理策略,并为 Agent 能够访问的所有服务保留一份审计记录,而不是为每个服务分别配置、还无人确保配置保持同步。
配置
从你已有的配置开始
$ 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 列表。它会写入文件,告知你导入了什么、未导入什么,然后停止。
在 --init 旁边传入 --config PATH,即可将文件写入 ./gateway.json 以外的位置。
运行后,在客户端中将这些服务替换为网关的单个条目。如果两者都保留,Agent 就会既直接连接这些服务,也通过代理连接它们,而审计记录只能显示一半的流量。
{
"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 --check
SOVEREIGN 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
| 层 | 软件包 | 拒绝条件 |
|---|---|---|
| 策略 | — | 工具在拒绝列表中,或不在允许列表中 |
| 意图 | intentshield | 调用未达到行为基线 |
| 文本过滤 | sovereign-shield | 参数包含注入内容,支持 21 种语言或 7 种编码形式 |
| 冻结验证 | sovereign-mcp | 调用与启动时冻结的工具定义不一致 |
| 输出验证 | sovereign-mcp | 结果未通过架构、欺骗、PII 或内容检查 |
| 逻辑规则 | logicshield | 结果与已配置的规则不一致 |
| 审计 | sovereign-mcp | — 通过哈希链日志记录每次调用,无论允许还是拒绝 |
安装
基础安装即可提供可正常工作的网关,并非空壳:
pip install sovereign-mcp-gateway
这样你就拥有 policy → frozen-verify → audit,它已经会拒绝任何上游未公开的工具、类型错误的参数、未声明的参数、位于拒绝列表中的工具,以及参数中的提示词注入。无需其他内容。
每个额外组件都会在此基础上增加一层:
| 额外组件 | 增加内容 | 适用情况 |
|---|---|---|
[text] | sovereign-shield — 对字符串参数进行更深入的检查:支持 21 种语言,并可通过七种变体解码隐藏在 base64、hex、ROT13、leet 语或反转文本中的负载 | 你的 Agent 会读取你无法控制的来源中的文本。基础安装能捕获 IGNORE ALL PREVIOUS INSTRUCTIONS,但无法捕获经过 base64 编码或用荷兰语写出的同一句话 |
[intent] | intentshield — 无论调用了哪个工具都会应用的行为底线:shell 禁令、删除禁令、凭据 URL、恶意软件语法 | 你需要一个不依赖于为每个工具都正确设置架构的兜底防护 |
[rules] | logicshield — 你为工具 输出 编写的一致性规则 | 你能够描述正确结果的样子。除非设置 output_rules,否则此项不起作用 |
[consensus] | requests — Layer C 的 HTTP 提供商所需 | 你要启用由托管提供商支持的多模型共识 |
可以组合所需组件,也可以全部启用:
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 客户端驱动正在运行的真实上游 mcp-server-git 和 mcp-server-sqlite 进行验证:
| 调用 | 结果 |
|---|---|
git__git_status、git__git_log | 允许 |
sqlite__create_table、__write_query、__read_query | 允许 — 该行确实写入了数据库 |
git__git_reset | 拒绝:位于拒绝列表中 |
git__git_push_force | 拒绝:没有上游公开此工具 |
git__git_status(repo_path=12345) | 拒绝:类型与冻结架构不符 |
git__git_commit("IGNORE ALL PREVIOUS INSTRUCTIONS…") | 拒绝:文本过滤器 |
sqlite__git_commit(...) | 拒绝:无法通过其他上游的命名空间访问工具 |
之后,代码库中仍只有一个提交,数据库中也恰好只有应有的那一行——这是直接打开它们检查的结果,而非依赖网关自身的报告。十次调用产生了十一条审计记录;编辑其中任意一条都会破坏链条。
这些用例属于测试套件,而非截图:pytest tests/ -v。
Layer C:多模型共识
其他每一层都是确定性的,并在本地运行。Layer 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 | 未能验证任何内容;密钥、模型 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记录都包含作者的电子邮箱 — 屏蔽这些内容会让网关无法使用。如果你的工具绝不应输出 PII,请设置为block。fail_closed决定某一层本身出错时的处理方式。默认值:拒绝。rate_limit_interval为0,这会禁用行为底线自身的操作间隔延迟。对于有意采取逐步操作的单个 Agent,这种延迟是合适的;对于代理则不合适,因为一连串工具调用是常见流量。entropy_policy默认为warn。文本过滤器的熵启发式会查找隐藏在散文中的编码负载,但工具参数通常是结构化内容 — 路径、标识符、哈希 — 其中高熵很常见。仅一个临时目录路径就足以导致合法调用被拒绝。如果你的参数确实是散文,请设置为block。
此工具无法做到什么
它会根据冻结的定义验证调用,并检查参数和结果。它不会读取你服务器的源代码,因此无法发现某项检查虽然存在、也被调用,却悄无声息地什么都不做。这仍需要有人阅读实现代码。
它也无法防范被入侵的上游返回看似正确的数据 — sovereign-mcp 中的 Layer C 共识可处理此问题,但需要你自行配置模型提供商。
许可证
Business Source License 1.1 — 请参阅 LICENSE。
源代码是公开的。你可以免费阅读、修改、创作衍生作品,并将其用于开发、评估及任何其他非生产用途。
个人或四人及以下的组织也可免费用于生产 — 这项规定明确写入许可证,作为额外使用授权,而不只是本文中的说明。规模更大的组织需要商业许可证。
每个版本都会在其变更日期(发布四年后)转换为 Apache 2.0。
如需获取生产用途授权,或咨询你的用途是否需要授权: [email protected]
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。