approval-gate-mcp
approval-gate-mcp
Un servidor MCP que coloca una puerta de aprobación humana frente a un proceso autónomo de larga duración, además de las herramientas operativas que necesitas para convivir con él: estado, registros, reinicio, parámetros de recarga en caliente y un resumen de lo que ha hecho.
Construido con FastMCP. Funciona con cualquier cliente MCP.
El problema
Un proceso que actúa por sí solo es útil hasta que una de sus acciones tiene consecuencias. Las respuestas habituales son malas en ambos casos. Apágalo y pierdes todo lo que estaba haciendo bien. Déjalo correr y te enteras después.
La puerta es una tercera opción. El proceso sigue ejecutándose sin supervisión, pero cuando quiere realizar una acción que has marcado como trascendente, escribe una propuesta y continúa en lugar de actuar. Revisas las propuestas cuando puedas, en el cliente MCP que ya tengas abierto, y las apruebas o rechazas. El proceso recoge tu decisión en su siguiente ciclo.
Ninguno de los dos lados bloquea al otro. No hay ningún servicio intermedio. El contrato son dos archivos JSON.
process you
| |
|-- writes proposal ----> pending.json
| |
| list_pending_approvals
| approve(0) / reject(1)
| |
|<-- reads on next cycle -- approved.json
|
|-- acts, appends to records.jsonHerramientas
Puerta de aprobación
Herramienta | Qué hace |
| Cada propuesta pendiente de una decisión, con todos sus campos |
| Mueve una propuesta al archivo de aprobadas |
| Descarta una propuesta |
Control del proceso
Herramienta | Qué hace |
| En ejecución o no, PID, tiempo de actividad, CPU, memoria, disco, última línea de registro |
| Muestra las últimas líneas del archivo de registro |
| Reinicia mediante tu script de inicio, desacoplado para que sobreviva a la sesión SSH |
| Vía de escape para comprobaciones puntuales |
Registros
Herramienta | Qué hace |
| Totales, resueltos frente a abiertos, desglose por tipo, entradas recientes |
| Vista de tabla más amplia, además de los registros abiertos actualmente y su exposición |
Parámetros — registrados solo si PARAMS_SCHEMA apunta a tu manifiesto
Herramienta | Qué hace |
| Lo que este despliegue declara ajustable y lo que está sobrescrito en este momento |
| Escribe una sobrescritura, validada contra tu manifiesto |
| Elimina una sobrescritura, o todas ellas |
Cadena — registrados solo si EVM_RPC_URL, WALLET_ADDRESS y TOKEN_CONTRACT están todos configurados
Herramienta | Qué hace |
| Saldo ERC-20 y nativo de solo lectura para una dirección vigilada. No se firma nada. |
Instalación
git clone https://github.com/WillyV347/approval-gate-mcp
cd approval-gate-mcp
pip install -r requirements.txt
cp .env.example .env # then edit itPruébalo en el inspector antes de conectarlo a un cliente:
fastmcp dev server.pyLuego regístralo. Para un cliente que lee una configuración JSON:
{
"mcpServers": {
"approval-gate": {
"command": "python3",
"args": ["/absolute/path/to/approval-gate-mcp/server.py"],
"env": {
"VPS_HOST": "your.host.or.ip",
"VPS_USER": "your-ssh-user",
"PROCESS_DIR": "/srv/my-process",
"PROCESS_MATCH": "my_process.py",
"PARAMS_SCHEMA": "/absolute/path/to/params.schema.json"
}
}
}
}No hay valores predeterminados para VPS_HOST, VPS_USER ni PROCESS_DIR. El servidor se cierra con un mensaje claro si faltan. Una herramienta de supervisión que silenciosamente recurre a algún host fijado por su autor es un error, así que esta se niega a adivinar.
La autenticación es tu configuración SSH existente. El servidor invoca al binario ssh del sistema, por lo que los agentes, las claves de hardware y los administradores de contraseñas que exponen un agente funcionan sin cambios. Nunca lee una clave privada por sí mismo.
El contrato que implementa tu proceso
Necesitas tres cosas en el lado del proceso. Ninguna de ellas requiere una biblioteca.
1. Registros. Añade a un array JSON. Cuatro claves se interpretan si están presentes, y todo lo demás se transmite sin cambios:
[
{
"id": "job-1041",
"record_type": "reindex",
"resolved": true,
"outcome": "win",
"cost": 4.25,
"result": 11.80,
"label": "nightly reindex, shard 3"
}
]2. Propuestas. Cuando se ejecuta en modo de aprobación, escribe aquí en lugar de actuar:
{
"proposals": [
{
"id": "job-1042",
"label": "reindex shard 7",
"action": "reindex",
"cost": 6.00,
"created_at": "2026-08-18T22:14:07Z"
}
]
}Cada campo que incluyas se muestra. El servidor no tiene un esquema para las propuestas y no quiere tenerlo.
3. Consulta el archivo de aprobadas. En cada ciclo, lee approved.json, actúa sobre lo que hay y límpialo. A grandes rasgos:
approved = read_json(APPROVED_FILE) or {"proposals": []}
for proposal in approved["proposals"]:
execute(proposal)
write_json(APPROVED_FILE, {"proposals": []})El orden es deliberado en el lado del servidor. Una decisión elimina la propuesta de pending.json antes de escribir en approved.json, por lo que el modo de fallo de una decisión a medio completar es una propuesta descartada, nunca una acción duplicada.
Parámetros, y por qué no hay ninguno en este repositorio
La recarga en caliente solo es útil si el servidor sabe qué es ajustable, y codificar los parámetros de un despliegue en una herramienta compartida la hace de un solo propósito. Así que declaras los tuyos en un manifiesto y apuntas PARAMS_SCHEMA a él:
{
"poll_interval_seconds": { "type": "int", "description": "Seconds between work cycles" },
"max_concurrent_jobs": { "type": "int", "description": "Jobs in flight at once" },
"dry_run": { "type": "bool", "description": "Plan work but do not execute" },
"approval_mode": { "type": "bool", "description": "Queue proposals instead of acting" }
}Los tipos admitidos son int, float, bool, str, dict y list. set_param convierte y valida contra esto y rechaza cualquier cosa que no se pueda convertir. Sin un manifiesto, las herramientas de parámetros simplemente no se registran, lo cual es mejor que exponer una ruta de escritura sin nada contra lo que verificarla.
params.schema.json está en gitignore, porque tu ajuste es tuyo. params.schema.example.json se incluye como punto de partida.
Haz que tu proceso lea el archivo de sobrescrituras al inicio, y en cada ciclo si quieres que los cambios se apliquen sin reiniciar:
overrides = read_json(PARAMS_FILE) or {}
poll_interval = overrides.get("poll_interval_seconds", POLL_INTERVAL_DEFAULT)Sesión de ejemplo
> is it running?
Process RUNNING
PID: 31882
Uptime: 14h 22m (51720s)
CPU: 0.6%
Memory: 84.3 MB
Disk: 212M
Last log: 2026-08-18 22:03:11 cycle complete, 2 proposals queued
> anything waiting on me?
2 proposal(s) awaiting approval
--- Proposal #0 ------------------------------
id: job-1042
label: reindex shard 7
action: reindex
cost: 6.00
created_at: 2026-08-18T22:14:07Z
--- Proposal #1 ------------------------------
id: job-1043
label: reindex shard 12
action: reindex
cost: 6.00
created_at: 2026-08-18T22:14:07Z
Use approve(index) or reject(index) to decide.
> approve 0, reject 1
Approved and queued for execution: reindex shard 7
Rejected and removed: reindex shard 12La salida anterior es ilustrativa.
Notas sobre seguridad
run_commandejecuta comandos de shell arbitrarios en el host remoto. Existe porque la alternativa es abrir una terminal de todos modos, pero es la herramienta más peligrosa aquí. Limita el usuario SSH a lo que realmente necesita en lugar de ejecutar todo como root.wallet_balancees de solo lectura y nunca toca una clave. Si no lo configuras, no existe.Nada en este repositorio almacena una credencial. Las URL RPC llevan claves de proveedor en la ruta, así que mantén
EVM_RPC_URLen el entorno y fuera de tus archivos de configuración.StrictHostKeyCheckingestá configurado enaccept-new: los hosts desconocidos se consideran de confianza en la primera conexión, las claves de host cambiadas aún fallan. Configúralo enyesy rellena previamenteknown_hostssi quieres el comportamiento más estricto.
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 Connectors
Control plane for autonomous software labor. Agents claim objectives over MCP with audit trail.
A paid remote MCP for CLI tool MCP, built to return verdicts, receipts, usage logs, and audit-ready
A paid remote MCP for hosted MCP server, built to return verdicts, receipts, usage logs, and audit-r
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/WillyV347/approval-gate-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server