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 的客户端都无需修改即可使用。
这个基础安装就是一个可用的网关。四个可选扩展在其上添加了更多层——参见安装。
它能阻止什么
一个代理读取了一个 GitHub issue,其正文携带了一条针对模型而非针对你的指令。它被说服了,并调用了 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 列表。它会写入文件,告诉你它采用了什么、留下了什么,然后停止。
在 --init 旁边传入 --config PATH 可以写入 ./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 → audit层 | 包 | 拒绝条件 |
policy | — | 工具在拒绝列表中,或不在允许列表中 |
intent |
| 调用未通过行为底线 |
text-filter |
| 参数携带注入内容,涵盖 21 种语言或七种编码 |
frozen-verify |
| 调用与启动时冻结的工具定义不一致 |
output-verify |
| 结果未通过 schema、欺骗、PII 或内容检查 |
logic-rules |
| 结果与你配置的规则不一致 |
audit |
| — 在哈希链日志中记录每个调用,无论允许还是拒绝 |
安装
基础安装是一个可用的网关,而不是一个空壳:
pip install sovereign-mcp-gateway这为你提供了 policy → frozen-verify → audit,它已经能够拒绝上游未暴露的工具、类型错误的参数、未声明的参数、拒绝列表中的工具,以及参数中的提示注入。无需其他任何东西。
每个扩展都会在其上添加一层:
扩展 | 添加内容 | 何时值得使用 |
|
| 你的代理会从你无法控制的任何地方读取文本。基础安装能捕获 |
|
| 你想要一个不依赖于把每个工具的 schema 都搞对的后备防线 |
|
| 你能表达出正确结果应该是什么样子。在你设置 |
|
| 你正在使用托管提供程序启用 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 客户端驱动:
调用 | 结果 |
| 允许 |
| 允许——该行确实在数据库中 |
| 拒绝:在拒绝列表中 |
| 拒绝:没有上游暴露它 |
| 拒绝:对于冻结的 schema 来说类型错误 |
| 拒绝:文本过滤器 |
| 拒绝:工具不能通过另一个上游的命名空间被访问 |
之后,仓库仍然只包含一个提交,数据库恰好包含它应有的那一行——通过直接打开它们来检查,而不是相信网关自己的报告。十次调用对应十一条审计记录;修改其中任何一条都会破坏链。
这些案例就是测试套件,而不是截图:pytest tests/ -v。
Layer C:N 模型共识
其他每一层都是确定性的且在本地的。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.共识比较的是规范化哈希,因此两个在语义上正确但结构不同的模型永远不会达成一致。一个较弱的模型只是回显 schema——
{"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,这会禁用行为下限自身的操作间延迟。该延迟适合一个代理采取审慎步骤的场景,但对代理服务器而言是错误的,因为工具调用的突发流量属于正常流量。entropy_policy默认为warn。文本过滤器的熵启发式算法用于寻找隐藏在散文中的编码载荷,但工具参数通常是结构化的——路径、标识符、哈希——在这些场景下高熵是正常的。仅一个临时目录路径就足以让合法调用被拒绝。当你的参数确实是散文时,请设置为block。
这不做什么
它根据冻结的定义验证调用,并检查参数和结果。它不读取你服务器的源代码,因此无法发现一个存在、被调用却静默无效的检查。这仍然需要有人阅读实现代码。
它也无法防止被攻破的上游返回看似正确的数据——sovereign-mcp 中的 Layer C 共识机制解决了这一问题,并且需要你自行配置模型提供商。
许可证
Business Source License 1.1——参见 LICENSE。
源代码是公开的。你可以阅读、修改、创建衍生作品,并免费将其用于开发、评估及任何其他非生产目的。
个人或不超过四人的组织也可免费用于生产——这一点已作为附加使用授权写入许可证,而不仅仅是在此处声明。规模更大的组织需要商业许可证。
每个版本在其变更日期(发布四年后)转换为 Apache 2.0。
如需获得生产使用许可,或询问你的使用是否需要许可: 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