{
  "markdown": "# @hashlock-tech/mcp\n\n> **Hashlock Markets** — the settlement layer for the agent economy, as MCP tools. Non-custodial cross-chain OTC: sealed RFQ + price negotiation + **HTLC atomic settlement** — both legs settle or both refund; no bridge, no custodian, no counterparty risk. BTC ↔ EVM / TRON.\n>\n> ⚠️ **Testnets only for now** (Ethereum Sepolia · TRON Nile · Bitcoin signet). Mainnet comes after the security-hardening gate — do not send real funds.\n\n[![npm](https://img.shields.io/npm/v/@hashlock-tech/mcp.svg)](https://www.npmjs.com/package/@hashlock-tech/mcp)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)\n\n## What is this?\n\nThe canonical [Model Context Protocol](https://modelcontextprotocol.io) server for **Hashlock Markets**. It gives AI agents (Claude, Cursor, Windsurf, any MCP client) the full OTC trading loop:\n\n1. **Browse** the asset registry and the public RFQ board\n2. **Post** a public RFQ or a private fixed-price order (shareable link)\n3. **Respond** to requests with a price; **negotiate** (counter / accept / decline) in the deal thread\n4. **Agree** — both parties accept → an HTLC swap is created\n5. **Track settlement** — who funded, timelocks, tx hashes — and manage receive/refund addresses\n\nSettlement **signing** (funding and claiming the HTLCs) stays with your own wallet — the server never holds keys or funds. The swap **secret is generated locally** on your machine and only its `sha256` hashlock is sent; retrieve it with `get_deal_secret` when it's time to claim.\n\n## Two ways to run\n\n- **Local (stdio)** — the npm package below. You run it on your machine with **your own keys**; it can\n  settle **autonomously** (SIWE login + on-chain signing with `HASHLOCK_*_KEY`). Full trust in yourself.\n- **Remote (hosted, Streamable HTTP)** — a public URL (`https://dev.hashlock.markets/mcp`) anyone can add\n  from Claude / ChatGPT / any MCP client; one-click OAuth, no install. Multi-tenant, so it is strictly\n  **non-custodial**: settlement returns **unsigned** transactions you sign with your own wallet, and the\n  server never holds keys or your swap preimage. See [Remote (hosted)](#remote-hosted) below.\n\n## Install\n\nLocal stdio via `npx` (Claude Desktop / Cursor / Windsurf `mcpServers` config):\n\n```json\n{\n  \"mcpServers\": {\n    \"hashlock\": {\n      \"command\": \"npx\",\n      \"args\": [\"-y\", \"@hashlock-tech/mcp\"],\n      \"env\": {\n        \"HASHLOCK_EVM_KEY\": \"0x<agent EVM key (TESTNET!)>\",\n        \"HASHLOCK_TRON_KEY\": \"<agent TRON key, 64-hex (optional)>\",\n        \"HASHLOCK_BTC_KEY\": \"<agent BTC WIF, signet (optional)>\"\n      }\n    }\n  }\n}\n```\n\n## Auth — autonomous, per chain\n\nThe agent owns its key(s); the server does the login itself (nonce → sign → JWT, refreshed on expiry).\nThe first configured key (EVM → TRON → BTC) mints the session; each key also signs settlement on its chain.\n\n| Env var | Chain | Login |\n|---|---|---|\n| `HASHLOCK_EVM_KEY` | EVM | SIWE `personal_sign` |\n| `HASHLOCK_TRON_KEY` | TRON | `signMessageV2` |\n| `HASHLOCK_BTC_KEY` | Bitcoin | BIP-322 |\n| `HASHLOCK_TOKEN` | — | a ready JWT (alternative to a key) |\n\nWith none set, read-only tools (`list_assets`, `list_open_rfqs`, `get_rfq`) still work. Use dedicated **testnet** keys.\n\nOther env: `HASHLOCK_API_URL` (default `https://dev.hashlock.markets/api`), `HASHLOCK_APP_URL` (share links; default derived), `HASHLOCK_EVM_RPC` (default a public Sepolia RPC), `HASHLOCK_TRON_HOST` (default Nile), `HASHLOCK_SECRETS_PATH` (default `~/.hashlock/mcp-secrets.json`, mode 0600).\n\n## Remote (hosted)\n\nThe same server also runs as a **remote MCP over Streamable HTTP** so anyone can connect by URL — no\ninstall. This is the multi-tenant, **non-custodial** surface: browse, RFQ, negotiate, and get **unsigned**\nfund/claim/refund transactions you sign with your own wallet (there is no autonomous key-in-env signing\nand no server-side secret storage here — you supply your own `hashlock` and keep your own preimage).\n\n**Connect from a client:** add the server URL. Nothing else — the client discovers that it needs\nauthorization, sends you to Hashlock to sign in and approve, and receives its own key:\n\n```\nURL: https://dev.hashlock.markets/mcp\n```\n\nThe grant then appears under [Developers](https://dev.hashlock.markets/developers) as an ordinary API key\nand can be revoked there at any time. Clients that do not speak OAuth can still send a key they created\nthemselves as `Authorization: Bearer hk_…`.\n\n<details><summary>How the OAuth flow works</summary>\n\nStandard OAuth 2.1, so any compliant MCP client drives it unattended:\n\n| Step | Endpoint |\n|---|---|\n| Unauthorized call names its metadata | `401` + `WWW-Authenticate: … resource_metadata=…` (RFC 9728) |\n| Client reads the resource + server metadata | `/.well-known/oauth-protected-resource`, `/.well-known/oauth-authorization-server` (RFC 8414) |\n| Client registers itself | `POST /oauth/register` (RFC 7591) |\n| You sign in and approve, in the browser | `/oauth/authorize` |\n| Client redeems the code for a key | `POST /oauth/token` — PKCE `S256` required (RFC 7636) |\n\nCodes are single-use and expire in 60 seconds; redirect URIs are allowlisted, with loopback permitted per\nRFC 8252. The issued token IS the API key, so a grant is revocable from the same list as every other key.\n\n</details>\n\n> **Testnets only** until the hardening gate.\n\n**Run the hosted service yourself:**\n\n```bash\ndocker build -t hashlock-mcp-http .\ndocker run -p 8080:8080 -e HASHLOCK_V1_URL=https://api-dev.hashlock.markets/v1 hashlock-mcp-http\n# or, from source:\npnpm build && HASHLOCK_V1_URL=https://api-dev.hashlock.markets/v1 PORT=8080 pnpm start:http\n```\n\nEnv: `HASHLOCK_V1_URL` (developer-API base, default `https://api.hashlock.markets/v1`) · `PORT` (default\n`8080`). Put it behind your reverse proxy at `/mcp`; `GET /health` is a liveness probe.\n\n## Tools (16)\n\n| Tool | What it does |\n|---|---|\n| `list_assets` | Asset registry (`SYMBOL@chain` refs, decimals) |\n| `list_open_rfqs` | Public RFQ board, filterable |\n| `get_rfq` | One RFQ / private order |\n| `create_rfq` | Post a public RFQ or private fixed-price order |\n| `cancel_rfq` | Cancel your own request |\n| `respond_to_rfq` | Respond with a price → opens a deal thread |\n| `negotiate` | `message` / `propose` / `accept_proposal` / `accept` / `reject` |\n| `my_rfqs`, `my_deals` | Your requests and deal threads |\n| `deal_status` | Thread + negotiation history + HTLC swap state |\n| `set_settlement_address` | Your receive/refund address per chain |\n| `get_deal_secret` | The locally-stored swap preimage (gated on both legs funded) |\n| `reveal_claim` | Report an out-of-band claim (secret + tx) so the other leg settles |\n| `whoami` | The account you're authenticated as |\n| **`fund_leg`** | **Autonomous:** fund your side of a swap on-chain with the agent's own key (EVM/TRON/BTC) |\n| **`claim_leg`** | **Autonomous:** claim your receive leg with the preimage (reveals the secret on-chain) |\n\nAmounts are **human decimal strings** (\"0.5\"); prices are the **total** quote-asset amount, not per-unit. Errors return a structured envelope `{ error: { code, is_retryable, recovery_hint } }` agents can branch on.\n\n## Fully autonomous loop\n\nWith a key set for each chain a swap touches, an agent can run end to end with no human:\n`create_rfq`/`respond_to_rfq` → `negotiate` (accept) → `set_settlement_address` (both chains) →\n`fund_leg` → `claim_leg`. Funding/claiming is signed locally with the agent's keys; the swap secret is\ngenerated + stored locally and only its hashlock leaves the machine. Use dedicated testnet keys.\n\n## How atomic settlement works\n\nBoth parties lock funds in HTLCs bound to the same `sha256(secret)` hashlock — BTC as a P2WSH script, EVM/TRON as contracts. The initiator funds the **long-timelock** leg first (asymmetric timelocks, so nobody gets a free option). Claiming one leg reveals the secret on-chain, which unlocks the other leg. Either both legs settle, or both refund after their timelocks. The recipient of each leg is fixed at funding time — revealing the secret cannot redirect funds.\n\n## Development\n\n```sh\npnpm install\npnpm run build    # tsup → dist/\npnpm run lint     # tsc --noEmit\npnpm test         # vitest\n```\n\nNode ≥ 20. MIT.\n",
  "bytes": 8234,
  "sha": "3c27a7446f86486e738d4ad9a4a776af6478f5ef3284653dedede3e8f4dc5b6e",
  "repo_slug": "hashlock-tech/hashlock-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_github_hashlock_tech_hashlock_bc9ef30e/readme"
}