sovereign-mcp-gateway
sovereign-mcp-gateway
Un proxy de filtrado para servidores del Model Context Protocol. Apunta tu cliente MCP al gateway en lugar de a tus servidores. Se conecta a todos los upstreams que enumeres, fusiona sus catálogos de herramientas en uno solo, y somete cada llamada a una cadena de verificación antes de que llegue al servidor que la ejecutaría.
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 lee la configuración MCP que ya tienes (Claude Desktop, Claude Code, Cursor, VS Code o Windsurf) y escribe un gateway.json que hace de proxy a esos mismos servidores, de modo que la primera ejecución produce una configuración funcional en lugar de un error de configuración. No importará la propia entrada del gateway, porque eso haría que se hiciera de proxy a sí mismo.
El gateway es en sí mismo un servidor MCP, así que cualquier cliente que hable MCP funciona sin cambios.
Esa instalación base es un gateway funcional. Cuatro extras opcionales añaden más capas encima — consulta Instalación.
Lo que detiene
Un agente lee un issue de GitHub cuyo cuerpo lleva una instrucción dirigida al modelo y no a ti. Se deja persuadir y llama a git_commit.
commits después | commit inyectado presente | |
directo a | 2 | sí |
a través del gateway | 1 | no |
Misma herramienta, mismos argumentos, mismo servidor. La diferencia es si algo estaba en posición de negarse.
Lee el tutorial completo: Tu agente lee un issue — o ejecútalo:
pip install "sovereign-mcp-gateway[all]" mcp-server-git
python examples/poisoned_issue.pyRelated MCP server: Agentrim MCP
Por qué un proxy y no una librería
Una librería tiene que ser adoptada por quien escribió el servidor. Un proxy protege servidores que no puedes modificar — que son la mayoría, porque los servidores MCP útiles son paquetes publicados que mantiene otra persona.
También te da un único lugar para mantener la política y un único registro de auditoría en todos los servidores a los que un agente puede llegar, en lugar de una configuración por servidor que nadie mantiene sincronizada.
Configurar
Empieza desde lo que ya ejecutas
$ 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 clientCuatro cosas que no hará: importarse a sí mismo, importar un servidor remoto que no pueda lanzar como subproceso, sobrescribir un archivo existente sin --force, ni escribir una lista deny_tools que no hayas elegido. Escribe el archivo, te dice qué tomó y qué dejó, y se detiene.
Pasa --config PATH junto con --init para escribir en un lugar distinto de ./gateway.json.
Después de ejecutarlo, sustituye esos servidores en tu cliente por una única entrada para el gateway. Dejar ambos significa que tu agente habla con ellos directamente además de a través del proxy, y el registro de auditoría solo mostrará la mitad del tráfico.
{
"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"}
}Comprueba el cableado antes de que un cliente lo vea:
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.La cadena
policy → intent → text-filter → frozen-verify → [ call executes ] → output-verify → logic-rules → auditCapa | Paquete | Se niega cuando |
policy | — | la herramienta está en una lista de denegación, o ausente de una lista de permisos |
intent |
| la llamada no supera el mínimo conductual |
text-filter |
| un argumento lleva inyección, en cualquiera de 21 idiomas o siete codificaciones |
frozen-verify |
| la llamada discrepa de la definición de herramienta congelada al inicio |
output-verify |
| el resultado falla los controles de esquema, engaño, PII o contenido |
logic-rules |
| el resultado es inconsistente con las reglas que configuraste |
audit |
| — registra cada llamada, permitida o denegada, en un registro encadenado por hash |
Instalación
La instalación base es un gateway funcional, no un esqueleto:
pip install sovereign-mcp-gatewayEso te da policy → frozen-verify → audit, que ya se niega a una herramienta que ningún upstream expone, un argumento de tipo incorrecto, un parámetro no declarado, una herramienta en tu lista de denegación e inyección de prompt en un argumento. No se necesita nada más.
Cada extra añade una capa encima:
Extra | Añade | Merece la pena cuando |
|
| Tus agentes leen texto de cualquier lugar que no controlas. La instalación base detecta |
|
| Quieres una red de seguridad que no dependa de acertar con el esquema de cada herramienta |
|
| Puedes expresar cómo es un resultado correcto. No hace nada hasta que establezcas |
|
| Estás habilitando consenso de N modelos con un proveedor alojado |
Combina lo que quieras, o tómalo todo:
pip install "sovereign-mcp-gateway[text]" # one extra
pip install "sovereign-mcp-gateway[text,intent]" # several
pip install "sovereign-mcp-gateway[all]" # every layerLos cuatro extras son paquetes pequeños de Python puro — [all] no añade dependencias compiladas ni ningún servicio que ejecutar.
Una instalación parcial se degrada de forma visible. El gateway imprime sus capas activas al inicio, para que siempre puedas ver qué está ejecutándose realmente:
layers: policy -> frozen-verify -> audit # base
layers: policy -> intent -> text-filter -> frozen-verify -> audit # [all]Si una capa no está en esa línea, no se está ejecutando — digas lo que digas que instalaste.
Verificado de extremo a extremo
Contra mcp-server-git y mcp-server-sqlite ejecutándose como upstreams reales, manejados por un cliente MCP real:
Llamada | Resultado |
| permitidas |
| permitidas — la fila está realmente en la base de datos |
| denegada: en la lista de denegación |
| denegada: ningún upstream la expone |
| denegada: tipo incorrecto para el esquema congelado |
| denegada: filtro de texto |
| denegada: una herramienta no puede alcanzarse a través del namespace de otro upstream |
Después, el repositorio sigue teniendo un commit y la base de datos contiene exactamente la fila que debería — comprobado abriéndolos directamente, no confiando en el propio informe del gateway. Once registros de auditoría para diez llamadas; editar cualquiera de ellos rompe la cadena.
Esos casos son la suite de pruebas, no una captura de pantalla: pytest tests/ -v.
Capa C: consenso de N modelos
Todas las demás capas son deterministas y locales. La Capa C es la excepción: pide a varios modelos independientes que extraigan el mismo documento estructurado del resultado de una herramienta, canoniza cada respuesta y compara los hashes SHA-256. El acuerdo se decide por hash, no por prosa.
Está desactivada salvo que se configure, porque es la única capa que cuesta dinero y latencia por llamada, y la única que envía la salida de la herramienta a un modelo.
{
"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"}
]
}
}Dos tipos de proveedor: local (cualquier endpoint compatible con OpenAI — Ollama, vLLM, LM Studio; base_url por defecto es http://localhost:11434/v1) y openrouter (la clave se lee de la variable de entorno nombrada, nunca se escribe en la configuración).
Tres reglas que el gateway aplica al inicio en lugar de descubrir en tiempo de ejecución:
Al menos dos proveedores. Un modelo no puede discrepar de sí mismo; un consenso de uno informa acuerdo en cada llamada, lo cual es peor que no tener capa porque parece verificación.
Sin modelos duplicados. Dos instancias del mismo modelo que coinciden no son verificación independiente.
Una clave API ausente se niega a arrancar. No recurre a ejecutarse sin la capa.
Todos los proveedores se ejecutan a temperature = 0, aplicado en el constructor.
Comprueba que tus modelos coinciden antes de confiar en la capa
--check ejecuta una llamada de consenso real contra tus modelos configurados y te dice qué pasó. Esto importa más de lo que parece:
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.El consenso compara hashes canónicos, así que dos modelos que ambos son semánticamente correctos pero estructuralmente diferentes nunca coinciden. Un modelo más débil que devuelve el esquema —
{"branch": {"type": "string", "value": "main"}} instead of {"branch": "main"}— no coincide en cada llamada, para siempre, y el gateway lo deniega todo con una razón que correctamente dice "los modelos discreparon". Porque discreparon.
La sonda distingue los tres resultados:
significa | |
OK | los modelos produjeron documentos idénticos; la capa es utilizable |
MISMATCH | discrepan en un documento trivial y denegarán cada llamada — sustituye un modelo, o elimina la sección |
provider unreachable | no se verificó nada; una clave, un ID de modelo o un endpoint es incorrecto |
Instala sovereign-mcp-gateway[consensus] o [all] — los proveedores HTTP necesitan requests, del que la librería principal deliberadamente no depende.
--check también lista las capas activas, para que puedas confirmarlo de un vistazo:
layers: policy -> intent -> text-filter -> frozen-verify -> consensus -> auditSi consensus falta en esa línea, no se está ejecutando, diga lo que diga la configuración.
Namespacing
Con namespace activado (el valor por defecto), una herramienta se expone como git__git_status. Dos upstreams que ofrecen el mismo nombre de herramienta no pueden colisionar, ensombrecerse mutuamente, ni alcanzarse a través del namespace equivocado. Desactívalo solo cuando tengas un único upstream.
Policy
"policy": {
"deny_tools": ["git__git_reset", "write_query"],
"allow_tools": null,
"pii_policy": "warn",
"fail_closed": true,
"rate_limit_interval": 0
}deny_toolscoincide con el nombre expuesto (git__git_reset) o con el nombre de la herramienta upstream (git_reset, en cada upstream que la tenga).allow_tools, cuando se establece, rechaza todo lo que no esté en la lista.pii_policytiene como valor predeterminadowarn, noblock. Las herramientas reales devuelven datos personales como salida normal — cada entrada degit logincluye un correo del autor — y bloquearlas hace que el gateway sea inutilizable. Estableceblockcuando tus herramientas nunca deban emitir PII.fail_closeddecide qué ocurre cuando una capa en sí misma falla. Valor predeterminado: rechazar.rate_limit_intervales0, lo que desactiva el retardo entre acciones propio del suelo conductual. Ese retardo es adecuado para un agente que da pasos deliberados e inadecuado para un proxy, donde una ráfaga de llamadas a herramientas es tráfico normal.entropy_policytiene como valor predeterminadowarn. La heurística de entropía del filtro de texto busca cargas útiles codificadas ocultas en prosa, pero los argumentos de las herramientas suelen ser estructurados — rutas, identificadores, hashes — donde la entropía alta es normal. Una ruta de directorio temporal por sí sola bastó para que se rechazara una llamada legítima. Estableceblockcuando tus argumentos sean realmente prosa.
Lo que esto no hace
Verifica las llamadas contra definiciones congeladas e inspecciona argumentos y resultados. No lee el código fuente de tus servidores, por lo que no puede ver una comprobación que está presente, se llama y silenciosamente no hace nada. Eso todavía requiere que alguien lea la implementación.
Tampoco puede proteger contra un upstream comprometido que devuelve datos de aspecto correcto — el consenso de Layer C en sovereign-mcp aborda eso, y requiere proveedores de modelos que configures tú mismo.
Licencia
Business Source License 1.1 — consulta LICENSE.
El código fuente es público. Puedes leerlo, modificarlo, crear obras derivadas y usarlo para desarrollo, evaluación y cualquier otro propósito no productivo sin coste.
El uso en producción también es gratuito para un individuo, o una organización de cuatro o menos personas — eso está escrito en la licencia como una Additional Use Grant, no solo declarado aquí. Las organizaciones más grandes necesitan una licencia comercial.
Cada versión se convierte a Apache 2.0 en su Change Date, cuatro años después de la publicación.
Para obtener una licencia para producción, o para preguntar si tu uso necesita una: 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