
scopeblind-gateway v0.13.1
Recibos firmados con Ed25519 + políticas Cedar para agentes de IA. Puerta de mandato financiero (Legate), paquetes de prueba, 3 borradores de Internet del IETF. npx protect-mcp
protect-mcp
Puerta de política Cedar fail-closed más recibos firmados para llamadas a herramientas de agentes de IA.
protect-mcp es una puerta que se sitúa delante de las llamadas a herramientas de un agente de IA. Evalúa
cada llamada contra una política Cedar (el mismo lenguaje
que AWS usa para IAM), bloquea lo que infringe las reglas antes de que se ejecute, y firma un
recibo Ed25519 verificable sin conexión de cada decisión. Se ejecuta localmente, no envía
telemetría de tus decisiones a ningún sitio, y tiene licencia MIT.
Por qué es diferente
- Fail-closed por defecto. Ante cualquier error de política, un motor ausente, o un
fallo de evaluación, la decisión es DENY. La puerta nunca permite de forma silenciosa. Existe un
modo de observación para despliegue en sombra, pero incluso ahí una llamada que sería
bloqueada se marca como
would_deny: true, de modo que un fallo nunca es silencioso. - Demuestra su propia contención.
serve --enforceydoctorejecutan una autoprueba de arranque y se niegan a armar la puerta a menos que puedan demostrar que una acción conocida como prohibida es realmente denegada. Una puerta que no puede probar que deniega no arranca. - Cada decisión es un recibo que cualquiera puede verificar. Las decisiones están firmadas con Ed25519
y son verificables sin conexión con
@veritasacta/verify. No se requiere confiar en un proveedor: las matemáticas no se preocupan de quién las ejecuta.
Inicio rápido: de la instalación a la primera prueba útil```bash
1. Generate an Ed25519 keypair, config template, and sample policy.
npx protect-mcp init
2. Wrap any MCP server in shadow mode. Nothing is blocked yet; calls are logged.
npx protect-mcp wrap -- node your-mcp-server.js
3. Inspect the local-only dashboard: tool inventory, risk, approvals, receipts.
npx protect-mcp dashboard --open
4. Draft a reviewable policy from observed calls.
npx protect-mcp recommend --write
5. When reviewed, restart the wrapper in enforce mode with that policy.
npx protect-mcp --policy protect-mcp.recommended.json --enforce -- node your-mcp-server.js
Para Claude Desktop, ejecuta primero un parche de configuración en modo dry-run y luego aplícalo:```bash
npx protect-mcp wrap --claude-desktop
npx protect-mcp wrap --claude-desktop --write
npx protect-mcp dashboard --open
El panel de control se enlaza a 127.0.0.1, solo lee archivos locales de registro/recibos y no
sube nada. Usa npx protect-mcp connect solo si quieres explícitamente un
panel de control ScopeBlind alojado.
La puerta como servidor MCP
Si prefieres llamar a la puerta como herramientas en lugar de configurar los hooks de Claude Code, ejecútala como un servidor MCP:```bash npx protect-mcp mcp
Habla MCP sobre stdio y expone cuatro herramientas de solo lectura, todo el bucle:
- **`evaluate_action`**: decide una llamada a herramienta propuesta contra una política Cedar en línea, fail-closed (cualquier error de política es DENY). Devuelve `{ allowed, decision, reason, policy_digest }`.
- **`sign_decision`**: convierte una decisión en un recibo firmado con Ed25519 (una denegación firma un `gateway_restraint`, un permiso un `decision_receipt`). Devuelve el recibo y su clave pública; genera una clave efímera si no proporcionas una.
- **`verify_receipt`**: verifica un recibo firmado sin conexión contra una clave pública. Devuelve `{ valid, error, type, kid, issuer }`.
- **`self_test`**: lo demuestra, sin entradas. Una acción conocida como prohibida es denegada, luego un recibo firmado realiza un round-trip y una copia manipulada falla.
Apunta cualquier host MCP hacia él, por ejemplo Claude Desktop:```json
{
"mcpServers": {
"protect-mcp": { "command": "npx", "args": ["-y", "protect-mcp", "mcp"] }
}
}
Los recibos son compatibles a nivel de bytes con los que el gate firma en tiempo de ejecución, por lo que un recibo generado aquí se verifica con @veritasacta/verify y el verificador del navegador de la misma manera.
Panel de acciones locales
protect-mcp dashboard es la vista del operador para pasar de la visibilidad a la aplicación:
- Inventario de herramientas: cada herramienta observada, recuento de llamadas, riesgo alto/medio/bajo, y si la política activa tiene una regla exacta, un respaldo con comodín o ninguna regla.
- Cobertura de políticas: ediciones de políticas locales con un clic para
Require approval,BlockuObserve. Reinicia el wrapper después de revisar los cambios. - Cola de aprobación de acciones exactas: la herramienta exacta, la acción, el destino, la vista previa del payload redactado, el hash del payload, la base de la política y la captura del motivo antes de que un humano apruebe, deniegue, edite o tome el control.
- Cadena de recibos: ids de solicitud correlacionados con hashes de recibos firmados, para que un revisor de auditoría pueda ver qué decisiones tienen prueba criptográfica.
- Exportación de auditoría: descarga el paquete de auditoría verificable sin conexión cuando existen recibos firmados. Si solo existen registros locales sin firmar, el panel explica que primero debe habilitarse la firma.
Para aprobaciones de respaldo en escritorio en vivo, inicia el panel con el endpoint de aprobación del gateway local y el nonce impresos por el wrapper:```bash
npx protect-mcp dashboard --open
--approval-endpoint http://127.0.0.1:9876
--approval-nonce "$PROTECT_MCP_APPROVAL_NONCE"
`Approve` reenvía a la puerta de enlace local activa cuando esos indicadores están presentes.
`Deny`, `Edit` y `Take over` se registran localmente como registros de resolución de aprobación; úsalos como la instrucción del operador y vuelve a ejecutar la herramienta cuando sea necesario.
### MVP de límite de pago: anclaje de digest, no carga de datos
Los recibos autofirmados locales siguen siendo gratuitos y verificables sin conexión. El límite de pago es
evidencia independiente de que ScopeBlind vio un digest de recibo en un momento dado, bajo una identidad de organización,
sin recibir el prompt sin procesar, la carga útil de la herramienta, la salida, la clave privada ni el
recibo sin procesar.```bash
# Create or refresh a local org identity and public-key directory.
npx protect-mcp registry init --org "Meridian Global Macro" --billing-account acct_meridian
# Local preview: writes a digest registry and shareable static verifier page.
npx protect-mcp registry anchor
# Hosted mode: uploads receipt digests only for independent anchoring.
SCOPEBLIND_TOKEN=... npx protect-mcp registry anchor \
--hosted \
--endpoint https://api.scopeblind.com \
--verifier-base https://legate.scopeblind.com
La vista previa local está etiquetada deliberadamente como local-preview-not-independent.
El modo alojado solo ancla hashes de recibos, ids de solicitud, claves públicas de la organización y
metadatos de facturación. No sube recibos sin procesar ni contexto sensible.
Killer Demo: de shadow a policy a proof
protect-mcp killer-demo genera un paquete completo de venta/demo de tres minutos:```bash
npx protect-mcp killer-demo --dir ./scopeblind-demo
Crea un sistema de archivos simulado, actividad simulada de GitHub, correo electrónico y PMS; muestra llamadas riesgosas en
modo shadow; aplica un paquete de políticas; requiere aprobación para una reserva sensible en el PMS;
se ejecuta a través del gateway; escribe un recibo firmado; demuestra que el recibo
original se verifica; demuestra que un recibo alterado falla; y crea un paquete de divulgación
selectiva que oculta el contexto sensible mientras muestra la prueba mínima.
Abre primero el `DEMO-RUNBOOK.md` generado. Luego ejecuta el comando de panel
impreso para guiar a un cliente a través de la secuencia exacta.
### Divulgación selectiva v0
Los recibos en modo compromiso pueden llevar un `committed_fields_root` en lugar de exponer
cada campo en texto claro. Posteriormente, el titular puede divulgar únicamente los campos seleccionados:```bash
npx protect-mcp verify-disclosure \
--receipt ./receipts/selective-disclosure.receipt.json \
--disclosure ./receipts/selective-disclosure.tool-only.json
El verificador comprueba el hash del recibo padre, la firma Ed25519, la raíz de compromiso y la prueba de Merkle de cada campo divulgado. Luego explica qué campos fueron divulgados y qué campos comprometidos permanecen ocultos. Esto es divulgación de compromiso con sal, no zero-knowledge completo, pero hace concreta la afirmación de privacidad: los auditores pueden verificar hechos seleccionados sin recibir la carga útil completa de la herramienta ni el contexto sensible del escritorio.
Probar una afirmación sobre el registro (atestaciones ciegas a la posición)
Puedes probar una AFIRMACIÓN sobre tu registro sin revelarlo. Acuña una atestación firmada y ciega a la posición sobre todo el registro que divulgue solo categorías por decisión (un resumen del recibo, el veredicto, etiquetas de capacidad), nunca tus entradas, salidas o datos de la herramienta:```bash
"No action reached the network across the record":
npx protect-mcp claim --no net.egress
other predicates:
--only fs.read,fs.write all actions were confined to these capabilities
--no-verdict blocked no action was blocked
--count blocked how many were blocked
Cualquiera lo verifica sin conexión, viendo solo las categorías, nunca el contenido:```bash
npx protect-mcp verify-claim claim-<id>.json
El verificador recalcula una raíz de Merkle sobre el conjunto divulgado y recalcula el predicado de forma independiente, por lo que el emisor no puede mentir sobre la afirmación dada la divulgación. Añade --anchor para registrar el digest de la afirmación en el registro de transparencia público y de solo anexado ScopeBlind, de modo que una contraparte que no confíe en ti pueda confirmar que el conjunto divulgado está completo y no fue recortado silenciosamente (solo se envía el hash; el registro permanece local):```bash
npx protect-mcp claim --no net.egress --anchor
Esta es una atestación responsable y ciega a la posición, no es zero-knowledge completo: revela la forma, no el contenido.
## Pruébalo en 60 segundos (no se requiere agente)
[](https://legate.scopeblind.com/record)
Mira el vídeo de dos minutos en [legate.scopeblind.com/record](https://legate.scopeblind.com/record), luego reprodúcelo contra tu propia copia:```bash
npx protect-mcp sample # seed a labeled sample record (8 decisions: 1 blocked, 2 payments)
npx protect-mcp record # open it: signatures verified in your browser
npx protect-mcp claim --payment-under 100 --anchor --output payments-under-100.json
npx protect-mcp verify-claim payments-under-100.json
npx protect-mcp anchor-record
Coloca el demo-tampered.jsonl generado en la página de registro para ver cómo se detecta una edición posterior a la firma. sample se niega a tocar un registro existente, así que ejecútalo en una carpeta vacía. Cuando estés listo para lo real, conecta el gate de abajo y los mismos comandos se ejecutarán contra el registro de tu propio agente.
Inicio rápido del hook de Claude Code```bash
Generate hook config and a sample Cedar policy.
npx protect-mcp init-hooks
Serve the Claude Code hook gate in enforce mode. It runs a restraint self-test
first and refuses to start if it cannot prove it denies a forbidden vector.
npx protect-mcp serve --enforce --cedar ./cedar
Evaluación de un solo disparo, tal como la invoca un hook PreToolUse. El código de salida 2 significa denegar
(la herramienta está bloqueada); el código de salida 0 significa permitir:```bash
npx protect-mcp evaluate --cedar ./cedar --tool Bash --input '{"command":"rm"}'
echo $? # 2 -> denied, fail-closed
npx protect-mcp evaluate --cedar ./cedar --tool Read --input '{"path":"README.md"}'
echo $? # 0 -> allowed
Una política ausente o que no se puede cargar deniega (salida 2) a menos que pases explícitamente
--fail-on-missing-policy false.
Hooks de Claude Code
protect-mcp init-hooks escribe un .claude/settings.json por ti. Para conectar la
compuerta manualmente, los dos verbos que necesitas son evaluate (PreToolUse, bloquea con salida 2)
y sign (PostToolUse, registra un recibo). Fija la versión para que una sesión de Claude Code
siempre ejecute la compuerta que probaste:```json
{
"hooks": {
"PreToolUse": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "npx [email protected] evaluate --cedar ./cedar --tool "$TOOL_NAME" --input "$TOOL_INPUT""
}
]
}
],
"PostToolUse": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "npx [email protected] sign --tool "$TOOL_NAME" --receipts ./receipts --key ./keys/gateway.json"
}
]
}
]
}
}
### Firmar la propia decisión de política
Desde la versión 0.13.0, `sign` puede evaluar la política y registrar la decisión real en el
recibo en lugar de una autorización incondicional. Pasa el directorio de la política y la
misma entrada y contexto que el hook pasaría a `evaluate`:```bash
npx [email protected] sign --cedar ./cedar --tool Bash \
--input '{"command":"rm -rf /"}' --context '{"command_pattern":"rm -rf"}' \
--receipts ./receipts --key ./keys/gateway.json
El payload del recibo luego lleva decision (permitir o denegar), reason
(cedar_allow o cedar_deny), y policy_digest (el digest acta-policy-digest-v1
del conjunto de políticas), y cita draft-farley-acta-signed-receipts-03. El
comando imprime la decisión y el digest en stdout. Una denegación también se firma: el
recibo es el registro de la decisión, no el permiso para proceder.
Se admiten dos modelos de acción de Cedar. La puerta de ejecución evalúa
Action::"MCP::Tool::call" con la herramienta como recurso, que es lo que las
políticas en cedar/ esperan y lo que sign --cedar usa por defecto. Las políticas
que nombran la herramienta como la acción (action == Action::"Bash"), como la
política de conformidad publicada en agent-governance-testvectors, necesitan
--action-model tool. evaluate acepta el mismo flag.
evaluate sale con 2 en caso de denegación para que Claude Code bloquee la llamada a la herramienta, y 0 en caso de permitir.
sign es de mejor esfuerzo: añade un recibo firmado con Ed25519 cuando hay una clave
configurada, y si no hay ningún firmante disponible registra una línea sin firmar honesta
("signed": false) en lugar de fallar la herramienta.
Úsalo en otros agentes (Codex, Cursor, Gemini, Hermes)
La misma puerta de cierre ante fallos se ejecuta como un hook de herramienta en cualquier agente que los soporte. Añade
--format <host> para que el verbo lea el payload del hook de ese host desde stdin y deniegue
en su contrato:```bash
the PreToolUse / before-tool command for each host
npx -y protect-mcp@latest evaluate --format codex --cedar ./cedar # OpenAI Codex npx -y protect-mcp@latest evaluate --format gemini --cedar ./cedar # Gemini CLI BeforeTool npx -y protect-mcp@latest evaluate --format cursor --cedar ./cedar # Cursor beforeShellExecution npx -y protect-mcp@latest evaluate --format hermes --cedar ./cedar # Hermes pre_tool_call
Empareja cada uno con `sign --format <host>` en el evento post-tool para obtener recibos. El caso importante es **Hermes**, que ignora los códigos de salida de los hooks y lee el veredicto desde stdout, por lo que `--format hermes` deniega mediante `{"decision":"block"}` en lugar de exit 2 (un exit-2 sin procesar fallaría silenciosamente abriendo el paso allí). Sin `--format`, los verbos leen los flags `--tool`/`--input` exactamente como en la sección de Claude Code anterior.
## Escribir una política
Las políticas de Cedar viven en un directorio al que apuntas con `--cedar`. Una regla `forbid` deniega, una regla `permit` permite. Para coincidir con un valor en la entrada de la herramienta, usa el idioma `.contains()`:```cedar
// Allow read-only tools.
permit(
principal,
action == Action::"MCP::Tool::call",
resource == Tool::"Read"
);
// Deny dangerous shell commands by matching the command against a list.
forbid(
principal,
action == Action::"MCP::Tool::call",
resource == Tool::"Bash"
) when {
["rm", "dd", "mkfs"].contains(context.command)
};
// Block destructive tools outright.
forbid(
principal,
action == Action::"MCP::Tool::call",
resource == Tool::"delete_file"
);
Peligro: NO escriba
context.command in ["rm", "dd"]para comparar una cadena contra una lista.ines para jerarquías de entidades, no para pertenencia de cadenas. Cedar trata la expresión como un error de tipo y descarta silenciosamente toda la reglaforbid, lo que (bajo una puerta fail-open) deja en pie unpermitresidual. Este es el defecto exacto detrás del aviso a continuación. Use[...].contains(context.command)en su lugar. A partir de 0.7.0 la puerta deniega ante ese error en lugar de permitir, y una prueba de alambre trampa de CI falla la compilación si el patrón se reintroduce en una política enviada. Consulte GHSA-hm46-7j72-rpv9.
Paquetes de políticas iniciales
La mayoría de los equipos no debería escribir Cedar desde cero el primer día. Instale un paquete inicial, ejecútelo en modo sombra, inspeccione los recibos y luego restrinja o aplique:```bash npx protect-mcp policy-packs list npx protect-mcp policy-packs show secrets-safe npx protect-mcp policy-packs install filesystem-safe --dir ./cedar npx protect-mcp policy-packs install all --dir ./cedar npx protect-mcp serve --cedar ./cedar
Packs integrados:
- `filesystem-safe`: acciones destructivas sobre archivos y lecturas de rutas similares a secretos.
- `git-safe`: force pushes, hard resets, limpiezas destructivas, eliminación de repositorios.
- `email-safe`: permite redactar borradores, bloquea envíos desatendidos.
- `database-safe`: postura de BD orientada a lectura, bloquea SQL de escritura/administración.
- `cloud-spend-safe`: creación evidente de gasto en la nube y destrucción de infraestructura.
- `secrets-safe`: exfiltración común de secretos en archivos, env, shell y nube.
- `finance-mandate-safe`: incumplimientos de listas restringidas y de concentración en flujos de reserva.
## Verificar un recibo
Los recibos están firmados y son verificables sin conexión por cualquiera que tenga la clave pública. Sin
red, sin proveedor, sin confiar en ScopeBlind:```bash
npx @veritasacta/verify ./receipts/receipts.jsonl --format jsonl
# Exit 0 = valid, non-zero = tampered or malformed
npx protect-mcp bundle --output audit.json exporta un paquete de auditoría autocontenido y verificable sin conexión de tus recibos más la clave pública de firma.
Seguridad
protect-mcp 0.7.0 falla cerrado por diseño. Ante cualquier error de evaluación de política, un motor ausente o una política que falló en la evaluación, la decisión es DENY, no allow. serve --enforce y doctor ejecutan una autoprueba de arranque que demuestra que la puerta deniega un vector conocido como prohibido antes de confiar en ella, y se niegan a armarse si no puede.
Versiones afectadas: 0.5.x y 0.6.x. Esas líneas fallan abierto (devuelven ALLOW ante un error de evaluación) y no evalúan Cedar correctamente contra el motor fijado, por lo que una regla forbid podría no bloquear. Actualiza a >= 0.7.0.
Detalles y remediación: GHSA-hm46-7j72-rpv9. Para reportar una vulnerabilidad, consulta SECURITY.md.
Comandos
| Comando | Descripción |
|---|---|
serve | Inicia el servidor de hooks HTTP para Claude Code (puerto 9377). --enforce ejecuta primero la autoprueba de restricción; --cedar <dir> y --policy <path> seleccionan la política. |
init | Genera un par de claves Ed25519 (keys/gateway.json), una plantilla de configuración y una política de ejemplo. |
sample | Siembra un registro de ejemplo claramente etiquetado (8 decisiones: una llamada bloqueada, dos pagos; kid sample-demo) más una copia manipulada, para que record, claim, verify-claim y anchor-record sean reproducibles desde cero antes de conectar un agente. Se niega a tocar un registro existente; --force lo anula. |
policy | Consulta y cambia la política Cedar desde la terminal: policy list (permit / forbid / default-deny por herramienta, con la frecuencia con que la puerta la permitió o denegó), policy show, policy allow <tool>, policy deny <tool>, policy path. Un serve en ejecución recarga en caliente al producirse el cambio. |
wrap | Imprime un comando MCP protegido o parchea los servidores MCP de Claude Desktop. Dry-run por defecto; usa --write para actualizar la configuración de Claude Desktop. |
dashboard | Inicia un panel solo local en 127.0.0.1 que muestra el inventario de herramientas, el riesgo, la cobertura de políticas, las aprobaciones de acción exacta, las cadenas de recibos y la exportación de auditoría. |
recommend | Redacta una política JSON revisable a partir de las llamadas locales observadas. Dry-run por defecto; usa --write para crear protect-mcp.recommended.json. |
registry | Crea una identidad de organización, ancla los digests de los recibos y escribe una página verificadora estática. El modo alojado sube solo los digests. |
record | Abre un visor local y consultable sobre tus recibos (--live transmite mientras el agente se ejecuta): firmas Ed25519 verificadas en tu navegador contra tu clave de puerta de enlace, etiquetas de capacidad, un árbol de procedencia y exportación firmada con un clic. Todo local, nada se sube. |
claim | Acuña una atestación firmada y ciega a la posición de un predicado sobre el registro (--no <cap> incl. --no payment, --only <c1,c2>, --no-verdict <verdict>, --count <verdict>, --payment-under <cap>), revelando solo categorías de decisión. Añade --anchor para registrar el digest de la reclamación en el registro público de transparencia; las claves inscritas se anclan como una organización con nombre. |
anchor-record | Registra un punto de control de la raíz de Merkle del registro + recuento + rango temporal en el registro público (compatible con heartbeat: se omite cuando no hay cambios). Una reclamación posterior cuyo compromiso coincida con un punto de control anclado es demostrablemente sobre el registro completo a partir de ese punto de control. |
verify-claim | Verifica un paquete de reclamación sin conexión: firma, raíz de Merkle recalculada, predicado recalculado de forma independiente y el sidecar de anclaje cuando está presente (vincula el sobre anclado a esta reclamación exacta y luego confirma que el registro público lo contiene). --check-anchor exige el anclaje; --offline omite el salto al registro. |
killer-demo | Genera un paquete de demostración completo de modo sombra a política a aprobación a recibo firmado. |
verify-disclosure | Verifica un paquete scopeblind.selective_disclosure.v0 y explica los campos revelados frente a los ocultos. |
policy-packs | Lista, inspecciona e instala paquetes de políticas Cedar de inicio. |
evaluate | Evalúa una llamada de herramienta contra una política Cedar (puerta PreToolUse). Salida 2 = denegar (fail-closed), salida 0 = permitir. |
sign | Firma una llamada de herramienta en un recibo (PostToolUse). Best-effort: registra una línea sin firma honesta si no hay clave. |
simulate | Ejecuta en seco una política contra un registro de decisiones grabado para ver qué habría bloqueado. |
demo | Inicia un servidor de demostración integrado envuelto con la puerta, para ver recibos al instante. |
doctor | Comprueba tu configuración (claves, políticas, motor Cedar, verificador) y ejecuta la autoprueba de restricción. |
bundle | Exporta un paquete de auditoría verificable sin conexión de recibos más la clave pública. |
report | Genera un informe de cumplimiento (Markdown o JSON) a partir del registro de decisiones y los recibos. |
Ejecuta npx protect-mcp --help para la referencia completa de flags.
Enlaces
- Protocolo (IETF): draft-farley-acta-signed-receipts
- CHANGELOG
- npm
- scopeblind.com
Licencia MIT. Creado por ScopeBlind.