mcpclerk
mcpclerk
Un proxy de gobernanza para servidores MCP: se sitúa delante de cualquier servidor MCP, aplica una lista blanca por herramienta, retiene las herramientas de clase escritura para aprobación humana, aplica cuotas por herramienta, redacta argumentos con aspecto de secreto y escribe un registro de auditoría encadenado por hash de cada llamada.
Un agente de IA en servidores MCP puede llamar a cualquier herramienta que estos expongan, tantas veces como quiera, con cualquier argumento, y nada registra lo que hizo de una forma que cualquiera pueda auditar. En una empresa, la pregunta no es "¿puede el agente hacer el trabajo?" sino ¿qué se le permite hacer, quién aprobó las partes peligrosas y qué hizo realmente?
mcpclerk responde a esas tres con código. Es en sí mismo un servidor MCP: el agente se conecta a él, él se conecta a los servidores reales y reexpone sus herramientas como upstream.tool. Cada llamada pasa por un único pipeline: lista blanca, cuota, redacción, aprobación, reenvío, registro. Una herramienta no listada es denegada. Una herramienta de clase escritura espera a que un humano responda y. Las denegaciones vuelven como errores legibles. El registro es JSON Lines de solo añadido, cada entrada con hash de la anterior, de modo que cualquier edición rompe la cadena.
La demo envuelve el servidor oficial de sistema de archivos: una lectura pasa, una escritura se retiene y se aprueba, un movimiento se deniega, la cuarta búsqueda en un minuto se deniega por cuota, y el registro lo verifica. 49 pruebas demuestran cada control contra un upstream falso, incluido que el upstream siempre recibe los argumentos sin redactar.

Instalación
pip install mcpclerk # Python 3.10+ (the MCP SDK requires it); pulls in mcp and pyyaml
mcpclerk --versionDesde el código fuente: git clone https://github.com/hishamalward/mcpclerk && cd mcpclerk && pip install -e ".[dev]" && pytest.
Related MCP server: Agentrim MCP
Cinco minutos
Escribe una política. Esta es la de la demo (
examples/policy.filesystem.yaml):version: 1 defaults: unlisted: deny # a tool not named here is an unreviewed tool approval_timeout_s: 120 # a call nobody answers in time is refused, and logged as such upstreams: fs: transport: stdio command: npx args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp/mcpclerk-demo-sandbox"] tools: "read_*": allow list_directory: allow search_files: { decision: allow, quota: { per_minute: 3 } } write_file: approve edit_file: approve create_directory: approve move_file: deny # the filesystem server has no delete; move is its destructive opMira qué ofrece el upstream y qué hace tu política con ello. Las anotaciones propias del servidor se muestran junto a tu decisión, que es como te das cuenta de que permitiste una herramienta destructiva:
$ mcpclerk tools --policy examples/policy.filesystem.yaml tool decision rule read_only destructive quota fs.read_file allow glob:read_* True None -/- fs.write_file approve exact False True -/- fs.move_file deny exact False True -/- fs.search_files allow exact True None -/3Registra el proxy donde tu agente busca servidores MCP. Para Claude Code,
examples/.mcp.json:{ "mcpServers": { "fs-governed": { "command": "mcpclerk", "args": ["serve", "--policy", "examples/policy.filesystem.yaml"] } } }En una segunda terminal, espera las aprobaciones:
mcpclerk approve. Cuando el agente llame afs.write_file, verás la llamada con los secretos ya enmascarados y responderásyon.Después:
mcpclerk verify audit/mcpclerk.jsonlymcpclerk report audit/mcpclerk.jsonl.
Los cinco controles
Control | Qué hace | Qué previene | Qué no puede prevenir | Demostrado por |
Lista blanca |
| Que el agente use una herramienta que nadie revisó. | Una mala decisión en la propia política. |
|
Aprobación | Las llamadas de clase | Una escritura sin supervisión. | Un humano que aprueba sin leer. |
|
Cuotas |
| Bucles descontrolados; una herramienta barata que se vuelve cara por volumen. | Distribuir un bucle entre muchas herramientas, o entre reinicios del proxy ( |
|
Redacción | Las reglas de clave ( | Que los secretos terminen en el registro o en la pantalla de un aprobador. | Un secreto con una forma que no está en la lista. Extiende |
|
Registro de auditoría | Una entrada JSON Lines por llamada con marca de tiempo, upstream, herramienta, argumentos redactados, decisión, quién aprobó, resultado, latencia y | Edición silenciosa, borrado o reordenamiento de entradas después del hecho; truncamiento de una ejecución completada ( | Un atacante que reescribe toda la cadena desde el origen (esto es una cadena, no una firma; ver más abajo). Truncamiento de una ejecución que se mató a mitad de camino. |
|
Los resultados no se registran, solo su tamaño y tipos de contenido. El registro es una auditoría de decisiones, no una copia de los datos; almacenar resultados lo convertiría en un segundo lugar donde los secretos podrían filtrarse.
Cómo se mueve una llamada
agent ──tools/call fs.write_file──▶ mcpclerk ──▶ [namespace] ──▶ [allowlist] ──▶ [quota] ──▶ [redact for log]
│ │ │
refused-unknown refused-denied refused-quota
│
┌── decision = approve ──▶ [hold: approvals/<id>.json] ──▶ y ─┐
│ │ n / timeout │
│ refused-by-human / refused-timeout │
└── decision = allow ────────────────────────────────────────┤
▼
[forward with ORIGINAL args] ──▶ upstream ──▶ result
│
[append log entry, hash-chained]Cada camino, incluida cada denegación, termina en una entrada de registro. Las denegaciones vuelven al agente como un resultado de herramienta normal con is_error: true y una razón de una línea: mcpclerk: refused-quota fs.search_files: 3/min exhausted; retry after 60s.
Aprobación, en detalle
El proxy normalmente lo inicia el cliente MCP del agente, y el SDK de MCP inicia servidores stdio en una nueva sesión, por lo que el proxy normalmente no tiene terminal propia. Por eso el mecanismo es una cola de archivos y el prompt de terminal es un cliente de ella:
approvals/<id>.jsonse escribe para cada llamada retenida, con los argumentos redactados,requested_at,expires_aty"approved": null.mcpclerk approve(en cualquier terminal, en la misma máquina) muestra las solicitudes pendientes y escribe tu respuesta.--onceresponde una y sale; sin él, sigue vigilando.Editar el archivo a mano para poner
"approved": truetambién funciona, que es lo que hace un trabajo sin cabeza o un script.Si el proxy resulta tener una terminal de control (lo iniciaste a mano), también pregunta allí. Ambos caminos compiten; la primera respuesta gana.
No responder dentro de
approval_timeout_ses una denegación, registrada comorefused-timeout. El silencio en una escritura significa no.serve --approve-sessionautoaprueba cada llamada de clase approve para ese proceso. Imprime una advertencia al inicio, la entradarun-startlo registra, cada entrada afectada diceapproved_by: session-flag, yreportlo grita. No se puede configurar en el archivo de política; es un acto por invocación de quien inicia el proceso.
El registro de auditoría
{"kind":"call","ts":"2026-08-24T01:14:40.822Z","run_id":"20260824T011440Z-3e1c","id":"20260824T011440Z-0002",
"name":"fs.write_file","upstream":"fs","tool":"write_file","rule":"exact",
"args":{"content":"# notes\n[REDACTED:kv-secret]\n","path":"/tmp/mcpclerk-demo-sandbox/notes.md"},
"decision":"approved","approved_by":"file","held_ms":253.7,"outcome":"ok","is_error":false,
"latency_ms":7.7,"content_bytes":57,"content_types":["text"],
"seq":4,"prev_hash":"5c0e…","hash":"b41a…"}decisiones uno deallowed,approved,refused-denied,refused-unknown,refused-quota,refused-timeout,refused-by-human.latency_mses solo tiempo del upstream; el tiempo de pensamiento del humano esheld_ms, así que la latencia p95 enreportsignifica la herramienta, no la persona.Las entradas de evento (
run-startcon el SHA-256 de la política y las banderas,discovercon recuentos expuestos/ocultos,run-endcon el recuento de entradas) comparten la misma cadena.verifysale con 0 yOK n entries, chain intacto con 1 yFAIL at line N: <what>. Pruébalo:sed -i '' 's/allowed/approved/' examples/audit.demo.jsonl && mcpclerk verify examples/audit.demo.jsonl.
El registro de ejemplo en examples/audit.demo.jsonl es la salida real de la ejecución de la demo. Es seguro publicarlo por construcción: las pruebas de redacción son las que lo demuestran, y la demo escribe una clave API falsa en un archivo precisamente para que el registro pueda mostrar [REDACTED:kv-secret] donde habría estado.
CLI
mcpclerk serve --policy policy.yaml [--log audit/mcpclerk.jsonl] [--approvals approvals] [--approve-session] [--no-tty]
mcpclerk approve [--approvals approvals] [--once] [--wait 60]
mcpclerk tools --policy policy.yaml [--json]
mcpclerk verify audit/mcpclerk.jsonl
mcpclerk report audit/mcpclerk.jsonl [--json]Códigos de salida: 0 ok, 1 verificación fallida o política inválida, 2 uso. La política se valida al inicio y cualquier problema (clave desconocida, decisión incorrecta, ${ENV_VAR} sin definir, un upstream stdio sin command) detiene el proxy antes de que sirva nada.
Referencia de política
version: 1
namespace_separator: "." # "__" for clients that reject dots in tool names
defaults:
unlisted: deny # allow | deny | approve
approval_timeout_s: 120
quota: { per_run: null, per_minute: null }
redaction:
extend: ['(?i)my[-_ ]?internal[-_ ]?token\s*[:=]\s*\S+'] # value regexes, added to the built-ins
extend_keys: [client_secret] # key names, added to the built-ins
replace_builtin: false # true: only your patterns (warned about)
upstreams:
<name>: # [a-z0-9_-]+ ; becomes the prefix in <name>.<tool>
transport: stdio | http
command: ... args: [...] env: { KEY: "${FROM_PROXY_ENV}" } cwd: ... # stdio
url: https://... # http
tools:
<tool or glob>: allow | deny | approve
<tool>: { decision: approve, quota: { per_run: 10, per_minute: 3 }, approval_timeout_s: 60 }Trabajo previo, y qué es esto en su lugar
Existen pasarelas para MCP y hacen más que esto: mcp-gateway de Lasso Security, mcp-context-forge de IBM y MCP Gateway de Docker aportan registros, autenticación multiinquilino, pipelines de plugins y observabilidad. mcpclerk no reclama novedad. Reclama pequeñez y verificabilidad: un proxy local, legible y de un solo propósito, cuya superficie completa son los cinco controles anteriores y un registro que puedes comprobar. Son unas 1.000 líneas de Python que puedes leer en una tarde, con una dependencia más allá del SDK de MCP (un analizador YAML).
Lo que no hace (todavía)
Identidad y políticas por usuario. Se asume un único operador; el registro indica que un humano aprobó, no cuál humano.
Una interfaz web, o canales de aprobación remotos (Slack, correo electrónico).
mcpclerk approvees una terminal local.Herencia de políticas o plantillas entre upstreams.
Recursos y prompts. v0.1 solo proxifica herramientas;
resources/listyprompts/listestán vacíos.Upstreams HTTP que necesitan cabeceras de solicitud. El transporte HTTP del SDK no acepta ninguna en esta versión; una política que establezca
headersfalla de forma ruidosa en lugar de enviar silenciosamente nada.Windows: la cola de archivos y
mcpclerk approvefuncionan; el prompt de terminal en proceso no (no hay/dev/tty). CI ejecuta Windows como mejor esfuerzo.
Modelo de amenazas, honestamente
Lo que un atacante con el asiento del agente intentaría primero es llamar a una herramienta por su nombre que esté oculta de la lista. Eso se rechaza y se registra (refused-unknown o refused-denied). Lo que esto no detiene: una herramienta que está permitida siendo utilizada para algo dañino (la política es tu juicio, mcpclerk la hace cumplir), un aprobador que aprueba sin revisar, y cualquiera con acceso de escritura al archivo de registro reescribiendo toda la cadena desde la primera entrada. La cadena defiende contra ediciones silenciosas, que es la amenaza realista; las firmas o un ancla externa (publicar el hash de cabeza diario en algún lugar que no controles) serían el siguiente paso, y no están en v0.1.
Desarrollo
pip install -e ".[dev]"
pytest -q # 49 tests, all in-process, no network, no subprocesses
python examples/demo_driver.py --approve-via-file # the demo against the real filesystem server (needs npx)
vhs examples/demo.tape # re-record the GIFLos tests usan el transporte en memoria del SDK de MCP en ambos lados: Client(proxy) → proxy → Client(fake_upstream). El upstream falso (tests/fake_upstream.py) tiene una herramienta secret_sink que devuelve exactamente lo que recibe, que es como la suite demuestra que el upstream ve argumentos sin redactar mientras que el registro no.
Relacionado: toilscan (el mismo instinto de seguridad de escritura aplicado a una herramienta de desarrollo), agent-slots (aislamiento en tiempo de ejecución para agentes paralelos), y agentkeel (el lado del proceso: compuertas y radio de explosión para código escrito por agentes; en progreso).
Para quien sea el próximo propietario: docs/learning/how-it-works.html es el recorrido (el código en orden de llamada, los controles, las respuestas de la entrevista); docs/spec.md es el contrato.
Licencia
MIT.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- AlicenseBqualityCmaintenanceSecurity gateway that wraps any MCP server with per-tool policies, approval gates, and optional Ed25519-signed decision receipts. Shadow mode logs every tool call without blocking; enforce mode applies block, rate-limit, and minimum-tier rules. Receipts are independently verifiable offline with no accounts needed.54699MIT
- 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
- AlicenseAqualityAmaintenanceAn MCP proxy that enforces policy on every tool call, blocking or flagging actions before they reach downstream MCP servers.1249MIT
- AlicenseNot gradedqualityAmaintenanceAn authorizing reverse proxy for MCP servers that enforces per-call policy rules on tool arguments with audit logging, dry-run, and rate limiting.Apache 2.0
Related MCP Connectors
Remote MCP for A2A caller identity, scope policy, verdict receipts, and audit history.
Runtime permission, approval, and audit layer for AI agent tool execution.
A paid remote MCP for CLI tool MCP, built to return verdicts, receipts, usage logs, and audit-ready
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/hishamalward/mcpclerk'
If you have feedback or need assistance with the MCP directory API, please join our Discord server