ZZanoraDocs

Buy

Add @zanora/mcp to Claude, Cursor or any MCP client, and the model can discover, pay for and verify capabilities from its own wallet with no integration code.

@zanora/mcp is an MCP server that runs locally over stdio. It gives the model ten tools. Two of them matter most: zanora_discover finds something to buy, and zanora_invoke pays for it and calls it.

Add it to your client

MCP config
{
  "mcpServers": {
    "zanora": {
      "command": "npx",
      "args": ["-y", "@zanora/mcp"],
      "env": {
        "ZANORA_API_KEY": "zk.akey_…",
        "ZANORA_AGENT_KEY_FILE": "/absolute/path/to/agent-key.pem",
        "ZANORA_MAX_PRICE_MINOR": "500"
      }
    }
  }
}
ClientWhere the config goes
Claude Desktop~/Library/Application Support/Claude/claude_desktop_config.json (macOS), %APPDATA%\Claude\claude_desktop_config.json (Windows)
Claude Code.mcp.json in the project, or claude mcp add zanora -- npx -y @zanora/mcp
Cursor.cursor/mcp.json
Anything elsethe client's MCP server config: command npx, args ["-y", "@zanora/mcp"]

Restart the client. The server checks the configuration at startup and prints a banner to stderr. A misconfiguration fails immediately with the name of the variable at fault.

You need a wallet first

The config uses a workspace API key and the private key of an agent wallet. If you don't have them, follow Create a workspace and Wallets and agent keys, then fund the wallet.

Configuration

VariableRequiredMeaning
ZANORA_API_KEYyesa workspace key. Use a dedicated agent key rather than the root one (see Approvals)
ZANORA_AGENT_KEY_FILEyes¹path to the agent's ed25519 private key PEM
ZANORA_AGENT_KEYyes¹the PEM inline, if you can't use a file
ZANORA_WALLET_IDnoonly needed when the workspace has more than one agent wallet. With several and none named, it refuses to start and lists them
ZANORA_MAX_PRICE_MINORnoa per-call ceiling in cents. Set one. A tool argument can lower it for one call but never raise it
ZANORA_GATEWAY_URLnodefaults to https://api.zanora.dev
ZANORA_AGENT_IDnothe agent name on payment proofs (defaults to the wallet id)
ZANORA_APPROVAL_ELICITATIONnoon (default) or off: whether to ask the user about held spends
ZANORA_ALLOW_LOCAL_PACKAGESnopackages this agent may run to buy them. Unset means none. See Running seller packages
ZANORA_SELLER_HEADERSnoJSON keyed by seller origin, for sellers behind their own auth: {"https://seller.example":{"authorization":"Bearer …"}}

¹ One of the two.

The tools

ToolDoesSpends
zanora_discoverranked marketplace search: price, seller reputation, request schema
zanora_capabilityresolves a known capability id (from an earlier session, a receipt, or the user) so it can be invoked
zanora_invokepays a capability's price and returns its response and signed receipt
zanora_wallet_balancebalance and available balance
zanora_wallet_ledgerevery charge, refund and deposit
zanora_purchaseswhat this wallet bought, from its receipts. Pages with after
zanora_receiptfetches a receipt and checks its signature
zanora_rate_providerrates a seller 1–5 for a purchase this wallet made
zanora_deposit_addresseswhere money can be sent to this wallet
zanora_approval_statuswhether a person approved a held spend

The loop is discover → invoke with the capabilityId from a result. The server remembers endpoints from discovery, so the model never types a URL. An id it hasn't seen is an error, not a guess, and zanora_capability resolves it properly. REST and MCP capabilities are both bought with zanora_invoke.

Every tool returns typed structuredContent along with text. zanora_invoke reports four named progress steps if the client sends a progress token.

When the answer is "no"

Refusals come back as readable tool results, and nothing is charged:

ResultThe model should
POLICY_DENIEDpick another capability. Never retry the same one
APPROVAL_REQUIRED + idreport the id and stop. If the client supports it, the user is asked directly (see Approvals)
APPROVAL_DENIEDstop. Don't ask again
INSUFFICIENT_FUNDSstop and tell the user where to send money (zanora_deposit_addresses). With elicitation, the user is shown the shortfall and the addresses, and the purchase is retried once the balance has actually changed
PRICE_ABOVE_CLIENT_LIMITthe price is over ZANORA_MAX_PRICE_MINOR. Choose something cheaper

Resources

The server also offers resources a person can browse without asking the model: zanora://wallet (balance) and zanora://purchases (recent receipts). They return the same data as the matching tools.

Try it

Ask the model:

Output
Search Zanora for invoice OCR under $2, buy the cheapest one on
https://example.com/invoice.png, verify the receipt, and rate the seller.

Safety model

  • The key file is the spending authority. Give each agent its own wallet, funded with what you'd accept losing to it.
  • The limits are on the server. Budgets and policies are checked by the platform. ZANORA_MAX_PRICE_MINOR is an extra limit on your side, not a replacement.
  • Buying and reading only. The server can't create wallets, move money between them, change policies or read another tenant's data.
  • Running code is off by default. A search result can never cause a seller's code to run on your machine.