ZZanoraDocs

Buy

@zanora/mcp-proxy puts one paid MCP server in front of your agent. Its tools appear under their own names with their own schemas, and each call is paid for as it's made.

With @zanora/mcp, the model decides to buy. It calls zanora_invoke with a capability id. With the proxy, a paid tool is just a tool. The model calls extract_invoice(imageUrl), and payment happens during the call.

@zanora/mcp@zanora/mcp-proxy
The model callszanora_invoke(capabilityId, body)extract_invoice(imageUrl)
Finding a sellerzanora_discover searches the marketplaceyou name one seller in the config
Payinga tool the model chooses to callhappens during the tool call
Best foran agent that shops across many sellersan agent that uses a seller you've already chosen

You can use both. The model can shop, and also have your chosen seller's tools to hand.

Add it

MCP config
{
  "mcpServers": {
    "acme-ocr": {
      "command": "npx",
      "args": ["-y", "@zanora/mcp-proxy", "https://demo-seller.zanora.dev/mcp"],
      "env": {
        "ZANORA_API_KEY": "zk.akey_…",
        "ZANORA_AGENT_KEY_FILE": "/absolute/path/to/agent-key.pem",
        "ZANORA_MAX_PRICE_MINOR": "500"
      }
    }
  }
}

The model now sees the seller's tools, with the price added to each description:

Output
extract_invoice(imageUrl)   Extract text and structured line items from scanned invoices.
                            Costs $1.00 USD per call, charged to this agent's wallet.

Configuration

The same variables as @zanora/mcp, so one agent running both sets them once:

VariableRequiredMeaning
ZANORA_AGENT_KEY_FILE / ZANORA_AGENT_KEYyes (one of)the agent wallet's private key
ZANORA_API_KEYyes on any real deploymentworkspace key
ZANORA_MAX_PRICE_MINORno, but set itper-call ceiling in cents. Without it, the proxy pays whatever a tool costs, up to the wallet's balance. The seller sets its own prices, so this is the limit you control
ZANORA_WALLET_IDnoonly when the workspace has several agent wallets
ZANORA_GATEWAY_URLnodefaults to https://api.zanora.dev
ZANORA_SELLER_HEADERSnoJSON keyed by origin, for a seller behind its own auth
ZANORA_TOOLS_POLL_MSnohow often to re-read the seller's tool list. Default 60000, minimum 15000, 0 to turn off

The seller URL is the argument. Use one proxy entry per seller, so two sellers' tool names can't collide.

Behaviour to know

  • The seller's result is passed through unchanged: content blocks, structuredContent, the seller's _meta. You get exactly what you paid for.
  • It only calls URLs. It won't run a seller's package. That needs a separate opt-in in @zanora/mcp.
  • It refuses plain http:// sellers, except loopback for local development. The answer you paid for comes back over that connection.
  • It keeps the tool list current. It declares tools/listChanged, and notices price changes both from each purchase's receipt and from a slow poll. It never announces a change on a guess: a seller that's briefly unreachable hasn't changed its list.
  • Refusals come back as readable results (POLICY_DENIED, APPROVAL_REQUIRED, INSUFFICIENT_FUNDS), not protocol errors, and nothing is charged.
  • Cancelling stops the purchase only until the payment proof is sent, the same as the SDK.

Not yet in the proxy

An APPROVAL_REQUIRED here reports the approval id and stops. The proxy doesn't prompt the user through elicitation the way @zanora/mcp does yet, and doesn't prompt about funding either.