Buy
Buy from an MCP client
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 eleven tools. Two of them matter most: zanora_discover finds something to buy, and zanora_invoke pays for it and calls it.
Set up in two commands
If you don't have a Zanora account yet, the setup command creates one, gives an agent a wallet, and stores the keys on your computer:
npx -y @zanora/mcp setup --email you@example.com --org "Northwind" --name claude-code --approval-rules
# Zanora emails you a 6-digit code. Then:
npx -y @zanora/mcp setup --code 123456- You sign up. The account only exists once you enter the code from your inbox.
--approval-rulesmakes purchases over $2.00, and any from an unverified seller, wait for your approval in the console. - Nothing secret is printed. The agent's signing key and its API key go to
~/.zanora(ZANORA_HOME), readable only by you. The API key is an agent key: it can buy, never approve. - The client config holds no secret. The server reads
~/.zanorawhenZANORA_API_KEYisn't set:
{ "mcpServers": { "zanora": { "command": "npx", "args": ["-y", "@zanora/mcp"], "env": { "ZANORA_MAX_PRICE_MICROS": "5000000" } } } }In Claude Code: claude mcp add zanora -- npx -y @zanora/mcp. Also: setup --resend sends a new code, setup --status shows what's set up, and --force starts over. An AI agent can run the same commands for you; zanora.dev/skill.md↗ tells it how.
Already have an account and an agent from the console? Use the config below instead.
Add it to your client
{
"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_MICROS": "5000000"
}
}
}
}| Client | Where 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 else | the 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
| Variable | Required | Meaning |
|---|---|---|
ZANORA_API_KEY | yes² | a workspace key. Use a dedicated agent key rather than the root one, so the agent can't approve its own spending: create one |
ZANORA_AGENT_KEY_FILE | yes¹ | path to the agent's ed25519 private key PEM |
ZANORA_AGENT_KEY | yes¹ | the PEM inline, if you can't use a file |
ZANORA_WALLET_ID | no | only 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_MICROS | no | a per-call ceiling in micro-dollars (2000000 = $2.00). Set one. A tool argument can lower it for one call but never raise it |
ZANORA_GATEWAY_URL | no | defaults to https://api.zanora.dev |
ZANORA_AGENT_ID | no | the agent name on payment proofs and approvals (defaults to the name you gave the agent, i.e. its wallet's owner id) |
ZANORA_APPROVAL_ELICITATION | no | on (default) or off: whether to ask the user about held spends |
ZANORA_ALLOW_LOCAL_PACKAGES | no | packages this agent may run. Unset means none. Packages aren't payable yet, so this doesn't affect purchases. See Seller packages |
ZANORA_SELLER_HEADERS | no | JSON keyed by seller origin, for sellers behind their own auth: {"https://seller.example":{"authorization":"Bearer …"}} |
¹ One of the two, unless setup stored the key file (see ²). ² Unless you ran setup: with ZANORA_API_KEY unset, the server reads the agent key, wallet and key file it stored in ~/.zanora (ZANORA_HOME).
The tools
| Tool | Does | Spends |
|---|---|---|
zanora_discover | ranked marketplace search: price, seller reputation, request schema | |
zanora_capability | resolves a known capability id (from an earlier session, a receipt, or the user) so it can be invoked | |
zanora_invoke | pays a capability's price and returns its response and signed receipt | ✓ |
zanora_wallet_balance | balance and available balance | |
zanora_wallet_ledger | every charge, refund and deposit | |
zanora_purchases | what this wallet bought, from its receipts. Pages with after | |
zanora_receipt | fetches a receipt and checks its signature | |
zanora_rate_provider | rates a seller 1–5 for a purchase this wallet made | |
zanora_deposit_addresses | where money can be sent to this wallet | |
zanora_request_funding | a one-time link for the user to add money by card. It asks; only the person paying moves money | |
zanora_approval_status | whether 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:
| Result | The model should |
|---|---|
POLICY_DENIED | pick another capability. Never retry the same one |
APPROVAL_REQUIRED + id | report the id and stop. If the client supports it, the user is asked directly (see Approvals) |
APPROVAL_DENIED | stop. Don't ask again |
INSUFFICIENT_FUNDS | stop and tell the user. zanora_request_funding gives them a card payment link, zanora_deposit_addresses where to send USDC. With elicitation, the user is shown the shortfall, a one-time card payment link where card payments are available, and any USDC addresses. The purchase is retried once the balance has actually changed |
PRICE_ABOVE_CLIENT_LIMIT | the price is over ZANORA_MAX_PRICE_MICROS. 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:
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_MICROSis 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.