Skip to main content
Glama
mattijsmoens

sovereign-mcp-gateway

by mattijsmoens

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.

Built on patent-pending components

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 mcp-server-git

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.py

Related 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 client

Cuatro 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 --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.

La cadena

policy → intent → text-filter → frozen-verify → [ call executes ] → output-verify → logic-rules → audit

Capa

Paquete

Se niega cuando

policy

—

la herramienta está en una lista de denegación, o ausente de una lista de permisos

intent

intentshield

la llamada no supera el mínimo conductual

text-filter

sovereign-shield

un argumento lleva inyección, en cualquiera de 21 idiomas o siete codificaciones

frozen-verify

sovereign-mcp

la llamada discrepa de la definición de herramienta congelada al inicio

output-verify

sovereign-mcp

el resultado falla los controles de esquema, engaño, PII o contenido

logic-rules

logicshield

el resultado es inconsistente con las reglas que configuraste

audit

sovereign-mcp

— 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-gateway

Eso 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

[text]

sovereign-shield — una pasada más profunda sobre argumentos de cadena: 21 idiomas, y decodificación de siete variantes para payloads ocultos en base64, hex, ROT13, leetspeak o texto invertido

Tus agentes leen texto de cualquier lugar que no controlas. La instalación base detecta IGNORE ALL PREVIOUS INSTRUCTIONS; no detectará la misma frase codificada en base64, ni escrita en neerlandés

[intent]

intentshield — un mínimo conductual aplicado independientemente de qué herramienta se llamó: prohibiciones de shell, prohibiciones de borrado, URLs con credenciales, sintaxis de malware

Quieres una red de seguridad que no dependa de acertar con el esquema de cada herramienta

[rules]

logicshield — reglas de consistencia que escribes para la salida de las herramientas

Puedes expresar cómo es un resultado correcto. No hace nada hasta que establezcas output_rules

[consensus]

requests — necesario para los proveedores HTTP de la Capa C

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 layer

Los 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

git__git_status, git__git_log

permitidas

sqlite__create_table, __write_query, __read_query

permitidas — la fila está realmente en la base de datos

git__git_reset

denegada: en la lista de denegación

git__git_push_force

denegada: ningún upstream la expone

git__git_status(repo_path=12345)

denegada: tipo incorrecto para el esquema congelado

git__git_commit("IGNORE ALL PREVIOUS INSTRUCTIONS…")

denegada: filtro de texto

sqlite__git_commit(...)

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 -> audit

Si 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_tools coincide 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_policy tiene como valor predeterminado warn, no block. Las herramientas reales devuelven datos personales como salida normal — cada entrada de git log incluye un correo del autor — y bloquearlas hace que el gateway sea inutilizable. Establece block cuando tus herramientas nunca deban emitir PII.

  • fail_closed decide qué ocurre cuando una capa en sí misma falla. Valor predeterminado: rechazar.

  • rate_limit_interval es 0, 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_policy tiene como valor predeterminado warn. 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. Establece block cuando 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

Maintenance

ActivitySlowing
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Centralized MCP control plane that proxies multiple upstream MCP servers with tool namespacing, filtering, policy enforcement, audit logging, and health checks.
    13 npm
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    A 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
  • A
    license
    Not graded
    quality
    A
    maintenance
    Provides 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
  • A
    license
    Not graded
    quality
    C
    maintenance
    Provides 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