HashLock OTC
Comercio de criptomonedas OTC con liquidación atómica HTLC en Ethereum y Bitcoin: crea intercambios, bloquea activos y liquida sin confianza a través de agentes de IA
Documentación
@hashlock-tech/mcp
Hashlock Markets — la capa de liquidación para la economía de agentes, como herramientas MCP. OTC entre cadenas sin custodia: RFQ sellado + negociación de precios + liquidación atómica HTLC — ambas patas se liquidan o ambas se reembolsan; sin puente, sin custodio, sin riesgo de contraparte. BTC ↔ EVM / TRON.
⚠️ Solo testnets por ahora (Ethereum Sepolia · TRON Nile · Bitcoin signet). La mainnet llega después de la puerta de endurecimiento de seguridad — no envíes fondos reales.
¿Qué es esto?
El servidor canónico de Model Context Protocol para Hashlock Markets. Da a los agentes de IA (Claude, Cursor, Windsurf, cualquier cliente MCP) el ciclo completo de trading OTC:
- Explorar el registro de activos y el tablero público de RFQ
- Publicar un RFQ público o una orden privada a precio fijo (enlace compartible)
- Responder a las solicitudes con un precio; negociar (contraoferta / aceptar / rechazar) en el hilo de la operación
- Acordar — ambas partes aceptan → se crea un swap HTLC
- Seguir la liquidación — quién financió, bloqueos de tiempo, hashes de transacción — y gestionar direcciones de recepción/reembolso
La firma de la liquidación (financiar y reclamar los HTLC) permanece en tu propia billetera — el servidor nunca tiene claves ni fondos. El secreto del swap se genera localmente en tu máquina y solo se envía su hashlock sha256; recupéralo con get_deal_secret cuando sea el momento de reclamar.
Dos formas de ejecutar
- Local (stdio) — el paquete npm a continuación. Lo ejecutas en tu máquina con tus propias claves; puede
liquidar autónomamente (inicio de sesión SIWE + firma en cadena con
HASHLOCK_*_KEY). Confianza total en ti mismo. - Remoto (alojado, Streamable HTTP) — una URL pública (
https://dev.hashlock.markets/mcp) que cualquiera puede añadir desde Claude / ChatGPT / cualquier cliente MCP; OAuth con un clic, sin instalación. Multi-tenant, por lo que es estrictamente sin custodia: la liquidación devuelve transacciones sin firmar que firmas con tu propia billetera, y el servidor nunca tiene claves ni tu preimagen del swap. Ver Remoto (alojado) a continuación.
Instalación
Stdio local vía npx (config de Claude Desktop / Cursor / Windsurf mcpServers):
{
"mcpServers": {
"hashlock": {
"command": "npx",
"args": ["-y", "@hashlock-tech/mcp"],
"env": {
"HASHLOCK_EVM_KEY": "0x<agent EVM key (TESTNET!)>",
"HASHLOCK_TRON_KEY": "<agent TRON key, 64-hex (optional)>",
"HASHLOCK_BTC_KEY": "<agent BTC WIF, signet (optional)>"
}
}
}
}
Autenticación — autónoma, por cadena
El agente posee sus claves; el servidor hace el inicio de sesión por sí mismo (nonce → firmar → JWT, renovado al expirar). La primera clave configurada (EVM → TRON → BTC) acuña la sesión; cada clave también firma la liquidación en su cadena.
| Variable de entorno | Cadena | Inicio de sesión |
|---|---|---|
HASHLOCK_EVM_KEY | EVM | SIWE personal_sign |
HASHLOCK_TRON_KEY | TRON | signMessageV2 |
HASHLOCK_BTC_KEY | Bitcoin | BIP-322 |
HASHLOCK_TOKEN | — | un JWT listo (alternativa a una clave) |
Sin ninguna configurada, las herramientas de solo lectura (list_assets, list_open_rfqs, get_rfq) siguen funcionando. Usa claves dedicadas de testnet.
Otras env: HASHLOCK_API_URL (por defecto https://dev.hashlock.markets/api), HASHLOCK_APP_URL (enlaces compartidos; por defecto derivado), HASHLOCK_EVM_RPC (por defecto un RPC público de Sepolia), HASHLOCK_TRON_HOST (por defecto Nile), HASHLOCK_SECRETS_PATH (por defecto ~/.hashlock/mcp-secrets.json, modo 0600).
Remoto (alojado)
El mismo servidor también se ejecuta como MCP remoto sobre Streamable HTTP para que cualquiera pueda conectarse por URL — sin
instalación. Esta es la superficie multi-tenant, sin custodia: explorar, RFQ, negociar, y obtener transacciones sin firmar
de financiar/reclamar/reembolsar que firmas con tu propia billetera (no hay firma autónoma con clave en env
ni almacenamiento de secretos en el servidor aquí — tú proporcionas tu propio hashlock y guardas tu propia preimagen).
Conectar desde un cliente: añade la URL del servidor. Nada más — el cliente descubre que necesita autorización, te envía a Hashlock para iniciar sesión y aprobar, y recibe su propia clave:
URL: https://dev.hashlock.markets/mcp
La concesión aparece entonces en Developers como una clave API ordinaria
y se puede revocar allí en cualquier momento. Los clientes que no hablan OAuth aún pueden enviar una clave que ellos mismos
crearon como Authorization: Bearer hk_….
Cómo funciona el flujo OAuth
OAuth 2.1 estándar, por lo que cualquier cliente MCP compatible lo maneja sin supervisión:
| Paso | Endpoint |
|---|---|
| La llamada no autorizada nombra sus metadatos | 401 + WWW-Authenticate: … resource_metadata=… (RFC 9728) |
| El cliente lee los metadatos del recurso y del servidor | /.well-known/oauth-protected-resource, /.well-known/oauth-authorization-server (RFC 8414) |
| El cliente se registra a sí mismo | POST /oauth/register (RFC 7591) |
| Tú inicias sesión y apruebas, en el navegador | /oauth/authorize |
| El cliente canjea el código por una clave | POST /oauth/token — PKCE S256 requerido (RFC 7636) |
Los códigos son de un solo uso y expiran en 60 segundos; las URI de redirección están en la lista blanca, con loopback permitido según RFC 8252. El token emitido ES la clave API, por lo que una concesión es revocable desde la misma lista que cualquier otra clave.
Solo testnets hasta la puerta de endurecimiento.
Ejecuta el servicio alojado tú mismo:
docker build -t hashlock-mcp-http .
docker run -p 8080:8080 -e HASHLOCK_V1_URL=https://api-dev.hashlock.markets/v1 hashlock-mcp-http
# or, from source:
pnpm build && HASHLOCK_V1_URL=https://api-dev.hashlock.markets/v1 PORT=8080 pnpm start:http
Env: HASHLOCK_V1_URL (base de API de desarrollador, por defecto https://api.hashlock.markets/v1) · PORT (por defecto
8080). Ponlo detrás de tu proxy inverso en /mcp; GET /health es una sonda de actividad.
Herramientas (16)
| Herramienta | Qué hace |
|---|---|
list_assets | Registro de activos (refs SYMBOL@chain, decimales) |
list_open_rfqs | Tablero público de RFQ, filtrable |
get_rfq | Un RFQ / orden privada |
create_rfq | Publicar un RFQ público o una orden privada a precio fijo |
cancel_rfq | Cancelar tu propia solicitud |
respond_to_rfq | Responder con un precio → abre un hilo de operación |
negotiate | message / propose / accept_proposal / accept / reject |
my_rfqs, my_deals | Tus solicitudes y hilos de operación |
deal_status | Hilo + historial de negociación + estado del swap HTLC |
set_settlement_address | Tu dirección de recepción/reembolso por cadena |
get_deal_secret | La preimagen del swap almacenada localmente (condicionada a que ambas patas estén financiadas) |
reveal_claim | Reportar un reclamo fuera de banda (secreto + tx) para que la otra pata se liquide |
whoami | La cuenta con la que estás autenticado |
fund_leg | Autónomo: financiar tu lado de un swap en cadena con la clave propia del agente (EVM/TRON/BTC) |
claim_leg | Autónomo: reclamar tu pata de recepción con la preimagen (revela el secreto en cadena) |
Los montos son cadenas decimales humanas ("0.5"); los precios son el total del activo cotizado, no por unidad. Los errores devuelven un sobre estructurado { error: { code, is_retryable, recovery_hint } } en el que los agentes pueden ramificar.
Bucle totalmente autónomo
Con una clave configurada para cada cadena que toca un swap, un agente puede ejecutarse de principio a fin sin humanos:
create_rfq/respond_to_rfq → negotiate (aceptar) → set_settlement_address (ambas cadenas) →
fund_leg → claim_leg. El financiamiento/reclamo se firma localmente con las claves del agente; el secreto del swap se
genera + almacena localmente y solo su hashlock sale de la máquina. Usa claves dedicadas de testnet.
Cómo funciona la liquidación atómica
Ambas partes bloquean fondos en HTLC vinculados al mismo hashlock sha256(secret) — BTC como script P2WSH, EVM/TRON como contratos. El iniciador financia la pata de bloqueo de tiempo largo primero (bloqueos de tiempo asimétricos, para que nadie obtenga una opción gratuita). Reclamar una pata revela el secreto en cadena, lo que desbloquea la otra pata. O ambas patas se liquidan, o ambas se reembolsan después de sus bloqueos de tiempo. El destinatario de cada pata se fija en el momento del financiamiento — revelar el secreto no puede redirigir fondos.
Desarrollo
pnpm install
pnpm run build # tsup → dist/
pnpm run lint # tsc --noEmit
pnpm test # vitest
Node ≥ 20. MIT.