MCP server

Install @hodle/mcp — a stdio MCP server that exposes the Hodle Platform API as tools for Claude Code, Cursor, Codex, and Hermes.

@hodle/mcp is a self-hosted Model Context Protocol server. It runs on your machine over stdio, wraps the public Hodle REST API in typed tools, and never sends your API key anywhere except Authorization: Bearer headers on requests it makes to the Hodle API itself.

Environment variables

VariableRequiredDefaultNotes
HODLE_API_KEYYesMissing key fails at startup with a clear message. Never accepted as a tool argument.
HODLE_API_URLNohttps://sandbox-api.hodle.com.brSandbox-first: set it explicitly to point at https://api.hodle.com.br.
HODLE_MCP_ALLOW_WRITESNofalse (unset)Set to true to register the write tools. Off by default.
HODLE_WALLET_PINOnly for payout/transferThe end user's wallet PIN. Read from the environment on purpose, never a tool argument — see below.
HODLE_PROTECTED_SYMMETRIC_KEYOnly for payout/transferFrom POST /api/wallet/keys. Same handling as the PIN.

Add the MCP server

Add it with the CLI:

claude mcp add hodle \
  -e HODLE_API_KEY=YOUR_API_KEY \
  -e HODLE_API_URL=https://sandbox-api.hodle.com.br \
  -e HODLE_MCP_ALLOW_WRITES=false \
  -- npx -y @hodle/mcp

Or drop this into your project's .mcp.json:

.mcp.json
{
  "mcpServers": {
    "hodle": {
      "command": "npx",
      "args": ["-y", "@hodle/mcp"],
      "env": {
        "HODLE_API_KEY": "YOUR_API_KEY",
        "HODLE_API_URL": "https://sandbox-api.hodle.com.br",
        "HODLE_MCP_ALLOW_WRITES": "false"
      }
    }
  }
}

Add this to ~/.cursor/mcp.json (or your project's .cursor/mcp.json):

~/.cursor/mcp.json
{
  "mcpServers": {
    "hodle": {
      "command": "npx",
      "args": ["-y", "@hodle/mcp"],
      "env": {
        "HODLE_API_KEY": "YOUR_API_KEY",
        "HODLE_API_URL": "https://sandbox-api.hodle.com.br",
        "HODLE_MCP_ALLOW_WRITES": "false"
      }
    }
  }
}

Reload Cursor's MCP settings from Settings → MCP after saving.

Add this to ~/.codex/config.toml:

~/.codex/config.toml
[mcp_servers.hodle]
command = "npx"
args = ["-y", "@hodle/mcp"]

[mcp_servers.hodle.env]
HODLE_API_KEY = "YOUR_API_KEY"
HODLE_API_URL = "https://sandbox-api.hodle.com.br"
HODLE_MCP_ALLOW_WRITES = "false"

Restart Codex CLI to pick up the new server.

Add this to ~/.hermes/config.yaml:

~/.hermes/config.yaml
mcpServers:
  hodle:
    command: npx
    args: ["-y", "@hodle/mcp"]
    env:
      HODLE_API_KEY: YOUR_API_KEY
      HODLE_API_URL: https://sandbox-api.hodle.com.br
      HODLE_MCP_ALLOW_WRITES: "false"

Then run /reload-mcp in a Hermes chat to pick it up without restarting.

Tools

Every tool call talks to the same host as HODLE_API_URL — sandbox by default. Read tools are always registered. Write tools are registered only when HODLE_MCP_ALLOW_WRITES=true, and every write tool requires confirm: true on the call itself — a call without it is refused before any HTTP request is made, and it tells you exactly what it would have done.

ToolGatedWraps
hodle_quoteReadPOST /api/quoteQuote
hodle_kyc_getReadGET /api/kycKYC
hodle_account_statementReadGET /api/account/statementAccount statement
hodle_wallet_getReadGET /api/walletWallet get
hodle_payout_statusReadGET /api/wallet/payout/{transactionId}Wallet payout
hodle_subaccount_listReadGET /api/subaccount
hodle_subaccount_getReadGET /api/subaccount/{subAccountId}
hodle_wallet_payoutWritePOST /api/wallet/payoutWallet payout
hodle_wallet_transferWritePOST /api/wallet/transferWallet transfer
hodle_deposit_assetWritePOST /api/deposit/assetDeposit asset
hodle_lightning_invoiceWritePOST /api/lightning/invoiceLightning invoice
hodle_subaccount_createWritePOST /api/subaccount
hodle_kyc_createWritePOST /api/kyc (hosted flow) — KYC

Use it

Once the server is wired in, ask your agent to use it directly — no extra prompting needed beyond naming what you want:

Get a quote for converting R$500 (PIX) into USDC on Base.

The agent calls hodle_quote and reads back the priced amount and fees.

What the gates do and do not do

Be precise about what protects you here, because the two gates protect different things and neither one is a human approving a payment:

  • HODLE_MCP_ALLOW_WRITES is the real boundary. Leave it unset and the write tools are never registered — the agent cannot see them, cannot call them, and no prompt can talk it into using a tool that does not exist.
  • confirm: true is a deliberateness check, not human approval. The agent sets that field, not you. It stops a value-moving call from happening by accident or as a half-formed guess, and the refusal tells you exactly what would have run — but an agent that has decided to pay can set confirm: true on its own.

The human-in-the-loop step is your MCP client's own tool-approval prompt (Claude Code, Cursor, and Codex each ask before running a tool). Keep that approval on for the write tools. If you are running an agent unattended, leave HODLE_MCP_ALLOW_WRITES unset and give the server a sandbox key.

walletPin and protectedSymmetricKey are not tool arguments. A tool argument is text the model writes, so a PIN passed that way would travel through the model's context and land in your agent's transcript and the provider's logs. The server reads both from HODLE_WALLET_PIN and HODLE_PROTECTED_SYMMETRIC_KEY instead, exactly like the API key, and both money tools refuse with a clear message when they are not set. Anything the API echoes back is scrubbed of those values before it reaches the agent. Never paste an end user's PIN into a chat session.

One consequence worth knowing up front: the server holds one credential pair, so hodle_wallet_payout refuses a call that sets subAccountId. A subaccount payout needs that subaccount's own PIN and key, and quietly sending the main account's would be wrong. Run per-subaccount payouts from your own integration code, where you can hold the right credentials per user — see Wallet payout.

When a write call times out

Write calls get a 60s timeout; reads get 15s. If a write times out or the connection drops, the tool returns outcomeUnknown: true and says so in plain words, because the operation may already have been accepted on the server. A repeated POST is not deduplicated by the API, so a blind retry can pay the same Pix twice. Check state first — hodle_payout_status for a payout, hodle_account_statement otherwise — and only then decide whether to call again.

Next steps

  • Turn on HODLE_MCP_ALLOW_WRITES=true only once you've tested the read path in sandbox.
  • Install the hodle-api agent skill alongside the MCP server so the agent also has the two end-to-end flows, KYC gating, and webhook verification in its context — the MCP server is the hands, the skill is the map.
  • Read the full API reference for every field the tools accept.