hydra-ops-mcp
hydra-ops-mcp
Opera una cabeza Hydra hablándole. Un servidor MCP que expone una cabeza en ejecución (ciclo de vida, libro mayor, monederos L1, registros de nodos y códigos de error en cadena) como herramientas que un cliente LLM puede invocar, para que puedas manejar y depurar una cabeza en lenguaje natural en vez de saltar entre una TUI, curl, cardano-cli y docker logs.
Cubre toda la superficie operativa: init, depósitos, transacciones dentro de la cabeza, decommit, close, fanout, fanout parcial y recuperación de depósitos, además de vistas de solo lectura del estado de la cabeza y de la L1. Cada operación que cambia el estado describe lo que haría y espera tu confirmación explícita antes de ejecutarse.
Contenido
Por qué
Operar una cabeza implica manejar varias herramientas a la vez. La TUI te muestra el estado de la cabeza pero no por qué se rechazó una transacción. La API WebSocket te da eventos pero tienes que parsear JSON a mano. Cuando algo sale mal, la respuesta suele estar en docker compose logs, correlacionada con el estado de la cabeza y decodificada contra códigos de error que viven en el código fuente de Plutus.
Este servidor pone todo eso detrás de una única interfaz conversacional:
"La cabeza no hace fanout. ¿Qué está mal?"
Claude puede verificar el estado de la cabeza, extraer la transacción fallida de los registros del nodo, decodificar el código de aborto H39 a FanoutUTxOHashMismatch y decirte las dos cosas que realmente lo causan — en un solo turno, porque tiene la API de la cabeza, los registros del contenedor y las tablas de errores al alcance.
También es útil para las partes rutinarias: abrir y financiar una cabeza, mover fondos y liquidar, con cada paso explicado y confirmado antes de ejecutarse. Y a diferencia de una sesión TUI vinculada a un solo nodo, cada herramienta acepta un argumento node, por lo que puedes comparar lo que alice, bob y carol creen sobre la misma cabeza.
Actualmente apunta a la demo devnet de hydra (tres nodos, tres partes). La capa de API no es específica de devnet; los ayudantes de L1 y el manejo de claves sí lo son (ver Limitaciones).
Inicio rápido
Requisitos previos — Docker, Python 3.10+ y un clon de cardano-scaling/hydra (para la demo devnet y las tablas de errores de Plutus).
git clone https://github.com/skoniog/hydra-ops-mcp && cd hydra-ops-mcp
python3 -m venv .venv # or: uv venv .venv
.venv/bin/pip install -r requirements.txt
./reset_devnet.sh # cardano-node + 3 hydra-nodes, seededRegistra el servidor con tu cliente MCP. Claude Code:
claude mcp add hydra-ops -- /absolute/path/to/hydra-ops-mcp/.venv/bin/python \
/absolute/path/to/hydra-ops-mcp/server.pyClaude Desktop — añade a claude_desktop_config.json:
{
"mcpServers": {
"hydra-ops": {
"command": "/absolute/path/to/hydra-ops-mcp/.venv/bin/python",
"args": ["/absolute/path/to/hydra-ops-mcp/server.py"]
}
}
}Los lanzadores MCP inician el servidor con un entorno reducido, así que pasa cualquier anulación (HYDRA_DEMO_DIR, HYDRA_REPO) en un bloque "env" en lugar de exportarlas en tu shell.
Luego pregunta:
"¿En qué estado está la cabeza y qué tiene alice en L1?" "Abre una cabeza y compromete los fondos de alice." "Envía 5 ADA de alice a bob, luego muéstrame el conjunto UTXO de la cabeza."
¿Nuevo en operar una cabeza de esta manera? RUNBOOK.md recorre todo el ciclo de vida — abrir, financiar, transaccionar, decommit, cerrar, liquidar y romperlo a propósito — como una serie de sesiones guiadas.
Arquitectura
MCP client (Claude Code / Claude Desktop / anything speaking MCP)
│ stdio
▼
server.py FastMCP registration; thin wrappers only
│
tools/ one module per domain, plain functions
├── observe.py head state, UTXOs, L1 funds, params, events
├── lifecycle.py init, commit, decommit, close, fanout, recover
├── transact.py in-head transfers
├── diagnose.py node logs, error-code decoding
└── types.py ok() / err() / needs_confirmation()
│
├──▶ hydra_client.py WebSocket + HTTP to hydra-node
│ async core, sync facade, event buffer
├──▶ tx_builder.py PyCardano: build + sign in-head txs
├──▶ cardano.py cardano-cli in the node container (L1)
└──▶ errors.py parses hydra-plutus for abort codeshydra_client.py mantiene una conexión WebSocket por nodo, ejecutando un bucle de eventos asíncrono en un hilo demonio detrás de una fachada síncrona — así las funciones herramienta siguen siendo simples mientras esperan eventos del protocolo. Almacena en búfer cada salida del servidor para recent_events, rastrea el estado de la cabeza y correlaciona transacciones confirmadas. Los comandos esperan su evento de resultado específico (Decommit → DecommitFinalized, Fanout → HeadIsFinalized) en lugar de devolver optimistamente, por lo que una llamada a herramienta que tiene éxito significa que el paso del protocolo realmente se completó.
tx_builder.py construye y firma transacciones con PyCardano — sin ida y vuelta a cardano-cli por transacción. cardano.py maneja el lado L1 (derivación de direcciones, consultas UTXO, firma y envío de transacciones de depósito) ejecutando cardano-cli dentro del contenedor cardano-node en ejecución, que es también donde residen las claves.
errors.py analiza HeadError.hs, DepositError.hs, HeadTokensError.hs y otros archivos de tu clon local de hydra en el momento de la llamada, por lo que los códigos decodificados siempre coinciden con la versión que estás ejecutando, en lugar de una tabla que se desactualiza.
El modelo de confirmación
Toda herramienta que cambia el estado acepta confirm: bool = False. Si se llama sin él, la herramienta valida todo lo que puede, resuelve lo que realmente haría y devuelve una descripción — sin haber cambiado nada:
{
"status": "requires_confirmation",
"action": "deposit alice's UTXO 4a3f…#0 (100,000,000,000 lovelace) into the head via node 1",
"message": "This would deposit… Nothing has been done. Retry with confirm=True to execute.",
"party": "alice", "utxo_ref": "4a3f…#0", "lovelace": 100000000000
}En la práctica, esto significa que Claude propone, tú apruebas, y solo entonces ocurre algo en la cadena. Es más importante para las operaciones que son unilaterales e irreversibles: close_head afecta a todos los participantes de la cabeza, y fanout liquida el estado final de la cabeza.
La vista previa está resuelta, no es hipotética — commit_funds nombra el UTXO exacto que seleccionó, decommit nombra el propietario y la cantidad que derivó del conjunto UTXO de la cabeza, send_tx informa el id de transacción que construyó. La validación se ejecuta antes de la puerta, por lo que nunca se te pide confirmar algo que de todos modos habría fallado. Las herramientas de solo lectura no tienen puerta y se ejecutan inmediatamente.
Referencia de herramientas
Todas las herramientas devuelven {status, error, ...}; los fallos son
{"status": "error", "error": "<mensaje>", ...} en lugar de excepciones. Cada herramienta acepta
node: int = 1 (1 = alice, 2 = bob, 3 = carol) excepto
l1_funds y explain_error.
Observabilidad (solo lectura)
Herramienta | Firma | Devuelve |
|
| Etiqueta de cabeza, estado observado por WS, número de UTXOs, total de lovelaces, número de instantánea, versión de cabeza, plazo de impugnación |
|
| El conjunto UTxO de la cabeza agrupado por dirección, cada uno con referencia y valor |
|
| Dirección L1 de una parte, número de UTXOs, total de lovelaces y valores por UTXO |
|
| Parámetros del libro mayor de la cabeza — conjunto completo más un resumen de los que suelen causar problemas (tarifas, min-UTXO, tamaños) |
|
| Depósitos observados pero aún no absorbidos — los candidatos a recuperación |
|
| Salidas del servidor vistas en esta conexión, opcionalmente filtradas por etiqueta |
recent_events cubre eventos desde que el servidor se conectó — la conexión WS no solicita historial, por lo que es una cola en vivo más que un registro completo. Para cualquier cosa más antigua, usa node_logs.
Ciclo de vida (con confirmación)
Herramienta | Firma | Notas |
|
| Rechaza a menos que la cabeza esté en |
|
| Redacta el depósito mediante |
|
| Retira un UTXO de la cabeza a L1 con la cabeza aún abierta. Deriva el propietario de la dirección del UTXO y construye una autotransferencia por el valor completo como la transacción de decommit |
|
| Publica la última instantánea confirmada e inicia el período de impugnación. Afecta a todos los participantes |
|
| Espera a |
|
| Liquida un subconjunto elegido; informa qué se distribuyó y qué queda. Ver Limitaciones — necesita un nodo más reciente que 2.3.0 |
|
|
|
commit_funds deliberadamente deposita un solo UTXO por llamada: los depósitos multi-UTXO son lo que atasca el fanout con H39 en 2.3.0 (ver Notas operativas).
Transacciones (con confirmación)
Herramienta | Firma | Notas |
|
| Transferencia dentro de la cabeza. |
Se rechazan cantidades inferiores a 1 ADA. La cabeza pone a cero el min-UTXO, por lo que tal salida es válida en L2 pero luego imposible de recrear en L1 — atascaría el fanout permanentemente. La transacción se reconstruye contra el conjunto UTxO actual en el momento de la confirmación, por lo que una vista previa que se quedó no gasta entradas obsoletas. La llamada retorna una vez que la transacción aparece en una instantánea confirmada, no meramente cuando es aceptada.
Diagnóstico (solo lectura)
Herramienta | Firma | Notas |
|
| Registros del contenedor, opcionalmente filtrados por expresión regular. Devuelve cuántas líneas coincidieron y las últimas |
|
| Decodifica un código de aborto ( |
Comparación con hydra-tui
La superficie de herramientas coincide deliberadamente con lo que expone hydra-tui, por lo que cualquier cosa que puedas hacer en la TUI la puedes hacer aquí:
hydra-tui | aquí |
|
|
diálogo de commit |
|
|
|
|
|
|
|
|
|
|
|
|
|
pestaña principal |
|
pestaña de fondos |
|
pestaña de historial |
|
— |
|
Al igual que el TUI, esto no expone Contest, SafeClose o
SideLoadSnapshot. Esas son respuestas del protocolo a condiciones
específicas en la cadena donde una acción es correcta y el tiempo es crítico;
pertenecen a herramientas deterministas con alertas, no detrás de un aviso.
Donde esto va más allá:
Diagnóstico.
node_logsyexplain_errorno tienen equivalente en el TUI. Esta es la ganancia práctica más grande — un cabezal atascado pasa de "el TUI dice que falló" a un código de aborto descifrado y las líneas de registro correspondientes.Entre nodos. Una sesión del TUI se conecta a un solo nodo. Aquí cada herramienta toma
node, para que puedas preguntar qué cree Alice, Bob y Carol sobre el mismo cabezal — la forma más rápida de detectar un nodo que se ha quedado atrás.L1 y L2 juntos.
l1_fundsconsulta la cadena directamente, por lo que "¿ese decommit realmente llegó?" es una sola pregunta en lugar de un cambio de contexto acardano-cli.Barandillas. Las salidas por debajo del mínimo UTXO y los depósitos multi-UTXO son rechazados por construcción, porque ambos atascan silenciosamente el fanout más tarde.
Composición. Las operaciones de varios pasos ocurren en una sola solicitud: "cierra el cabezal, espera a que pase la impugnación, haz fanout y muéstrame los saldos L1 finales de todos" es una sola petición.
Donde el TUI sigue ganando: es un panel en vivo. MCP es solicitud/respuesta, por lo que obtienes instantáneas en lugar de una vista que se actualiza continuamente — para observar un cabezal a lo largo del tiempo, mantén abierto el TUI. Las pulsaciones de teclas también superan un viaje de ida y vuelta del modelo para trabajo repetitivo, y los selectores de UTxO del TUI son visuales, mientras que aquí listas y luego seleccionas.
Configuración
Todo está en config.py, con anulaciones de entorno:
Configuración | Valor por defecto | Significado |
|
| Índice de nodo → puntos finales WS/HTTP y nombre de parte |
|
| Devnet de demostración: proyecto docker compose y credenciales |
|
| Repositorio de Hydra, para descifrar códigos de aborto |
|
| Magia de la devnet |
|
| Umbral de rechazo para salidas en el cabezal |
Las claves de firma son los pares {alice,bob,carol}-funds de la demostración. Las rutas
del lado del contenedor se usan para cardano-cli (firma y envío en L1); copias
en el lado del host de las mismas claves son leídas por PyCardano para transacciones dentro del cabezal.
Apuntar a una implementación diferente con el mismo diseño es un cambio de configuración;
apuntar a una topología diferente no lo es (consulte Limitaciones).
Pruebas
.venv/bin/python test_ops.py # offline — no devnet needed
.venv/bin/python test_ops_devnet.py # live — needs a devnet with the head Idletest_ops.py asegura que cada herramienta que cambia de estado devuelve
requires_confirmation y no llega a ningún cliente sin confirm=True (el
cliente ficticio lanza una excepción si un comando sale de la puerta), que las cargas útiles de las solicitudes coinciden con la
API, que se activan el rechazo mínimo de UTXO y la validación de UTxO, que la
tabla de errores se analiza y descifra, y que las 16 herramientas se registran con el servidor.
test_ops_devnet.py maneja un cabezal real a través de todo el ciclo de vida y
asegura la observabilidad en cada etapa: verificación de puerta → init → commit →
seis herramientas de lectura → dos pagos en el cabezal → decommit, verificado por los fondos
que aparecen en L1 mientras el cabezal permanece abierto → close → fanout → de vuelta a
Idle → registros y descifrado de errores. Se salta con un mensaje claro si la devnet
no está activa o el cabezal no está en Idle.
Notas operativas
Cosas que vale la pena saber antes de que te cuesten un cabezal.
H39 / FanoutUTxOHashMismatch atasca un cabezal permanentemente. El fanout no puede
reproducir lo que el cabezal cerrado se comprometió a hacer, por lo que el cabezal no puede liquidarse y sus
fondos quedan atrapados. Dos causas, ambas prevenibles y ambas protegidas aquí:
depósitos multi-UTXO en 2.3.0, y cualquier salida del cabezal por debajo del mínimo UTXO de L1. Pregunta
explain_error("H39") para los detalles.
El cabezal pone a cero el mínimo UTXO; L1 no lo hace. Una salida de 0.5 ADA se transacciona felizmente
en L2 y luego no se puede recrear en L1. send_tx rechaza por debajo de 1 ADA por
esta razón.
Los depósitos se absorben después de un período de depósito, no al instante.
commit_funds espera e informa si la absorción no ocurre; un depósito que nunca
llega aparece en pending_deposits y regresa con
recover_deposit.
El cierre es unilateral y afecta a todos. Cualquier participante puede cerrar, y todo el cabezal debe entonces liquidarse. La puerta existe principalmente para esto.
Un cabezal necesita que todos los participantes estén en línea. Si un pago se cuelga, verifica
docker compose ps antes de sospechar de las herramientas.
El productor de bloques de la devnet de demostración puede atascarse después de largos períodos de inactividad —
cardano-cli query tip devuelve el mismo slot dos veces y todo se cuelga.
./reset_devnet.sh lo arregla; la devnet es desechable por diseño.
La entrada WebSocket no analizable no devuelve tag. Un comando que un nodo no
reconoce regresa como un objeto simple {"input", "reason"} en lugar de un evento
etiquetado — vale la pena saberlo si escribes scripts directamente contra la API, ya que un
cliente que espera eventos etiquetados se colgará. El cliente aquí lo maneja.
Limitaciones
partial_fanout necesita un nodo más nuevo que 2.3.0. El comando es posterior a la
versión (hydra PR #2750, commit a271cced2), y la imagen de demostración fijada lo
rechaza — el nodo lista los comandos que conoce y PartialFanout no está
entre ellos. La herramienta detecta esto con precisión e informa la brecha de versión. La
ruta de código está lista para un nodo construido desde master pero solo se ha ejercitado hasta
ese rechazo.
Las tarifas son cero. tx_builder.py codifica fee=0, lo cual es correcto para los
parámetros de protocolo de la demostración y está mal en cualquier otro lugar. Se necesita
estimación de tarifas real y selección de monedas antes de que esto apunte a preview/preprod o mainnet.
Suposiciones con forma de devnet. Tres partes con nombres de clave conocidos, claves
legibles dentro del contenedor cardano-node, docker compose disponible para consultas y registros de L1.
La capa de API del cabezal es general; los ayudantes de L1 no lo son.
Solo ADA. La construcción de transacciones maneja UTXOs de solo lovelace — sin tokens nativos, scripts, datums o acuñación.
recover_deposit no está probado contra un depósito realmente atascado. Sigue
la API, pero la devnet de demostración absorbe depósitos demasiado confiablemente como para producir
uno bajo demanda.
Sin autenticación. Cualquiera que pueda alcanzar el servidor puede operar el cabezal. Eso es apropiado para una herramienta de operador local y no lo sería para cualquier cosa expuesta.
Extensión
Agregar una herramienta: escribe una función simple en el módulo tools/ relevante
que devuelva ok() / err() / needs_confirmation(), luego registra un envoltorio
delgado en server.py. Los módulos de herramientas no importan FastMCP, por lo que son
llamables directamente desde las pruebas — que es como ambas suites los manejan.
Agregar un comando de protocolo: agrega un método a HydraClient usando
_command_and_wait(command, ok_tags), que envía y espera el evento de resultado
mientras trata tanto CommandFailed como los rechazos de análisis no etiquetados como
errores.
Apuntar a otra implementación: apunta NODES a los puntos finales y
HYDRA_DEMO_DIR / HYDRA_REPO a las rutas correctas. Cualquier cosa más allá del diseño de tres partes
de la demostración significa revisar el manejo de claves en cardano.py y
tx_builder.py, y las tarifas.
Lectura adicional
La documentación de Hydra para el protocolo en sí, y RUNBOOK.md para la visita guiada de la operación de un cabezal con estas herramientas.
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
MCP server exposing the Backtest360 engine API as tools for AI agents.
Hosted MCP server for live Bittensor chain reads and self-custodial on-chain writes.
MCP server providing access to the Scorecard API to evaluate and optimize LLM systems.
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/skoniog/hydra-ops-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server