# MCP server reference

> Every environment variable, tool and resource in @zanora/mcp, for both the buyer and seller profiles.

```bash
npx -y @zanora/mcp          # stdio. stdout carries the protocol; logs go to stderr
```

## Environment

| Variable | Profile | Required | Default | Meaning |
|---|---|---|---|---|
| `ZANORA_ROLE` | both | no | `buyer` | `buyer` or `seller`. Never guessed from other variables |
| `ZANORA_API_KEY` | both | yes¹ | — | workspace key (buyer) or provider key (seller) |
| `ZANORA_GATEWAY_URL` | both | no | `https://api.zanora.dev` | |
| `ZANORA_AGENT_KEY_FILE` | buyer | yes² | — | path to the wallet's ed25519 private key PEM |
| `ZANORA_AGENT_KEY` | buyer | yes² | — | the PEM inline (escaped `\n` accepted) |
| `ZANORA_WALLET_ID` | buyer | no | derived | needed only if the workspace has several agent wallets |
| `ZANORA_AGENT_ID` | buyer | no | wallet id | the agent name on payment proofs |
| `ZANORA_MAX_PRICE_MINOR` | buyer | no | none | per-call ceiling in cents. `5.00` is rejected; write `500` |
| `ZANORA_APPROVAL_ELICITATION` | buyer | no | `on` | `off` to never prompt the user about held spends |
| `ZANORA_ALLOW_LOCAL_PACKAGES` | buyer | no | none | comma-separated packages this agent may run, e.g. `@acme/ocr-mcp,@acme/tts@2.1.0` |
| `ZANORA_SELLER_HEADERS` | buyer | no | — | JSON keyed by seller origin: `{"https://seller.example":{"authorization":"Bearer …"}}` |
| `ZANORA_SALES_POLL_MS` | seller | no | `20000` | how often to check for changes while a resource is subscribed. Minimum 5000 |

¹ Required on any real deployment. Without it, every tool returns `UNAUTHORIZED`. ² One of the two. The seller profile refuses a wallet key.

Every value is checked at startup. A bad value fails immediately with the variable's name.

## Buyer tools

| Tool | Arguments | Spends |
|---|---|:-:|
| `zanora_discover` | `query?`, `category?`, `protocol?`, `maxPriceMinor?`, `maxLatencyMs?`, `limit?` | |
| `zanora_capability` | `capabilityId` | |
| `zanora_invoke` | `capabilityId`, `body` (the request body; for MCP, the tool's arguments), `method?`, `maxPriceMinor?` (can only lower the ceiling) | **✓** |
| `zanora_wallet_balance` | — | |
| `zanora_wallet_ledger` | — | |
| `zanora_purchases` | `limit?`, `after?` | |
| `zanora_receipt` | `receiptId` | |
| `zanora_rate_provider` | `providerId`, `transactionId`, `rating` (1–5) | |
| `zanora_deposit_addresses` | — | |
| `zanora_approval_status` | `approvalId` | |

Resources: `zanora://wallet`, `zanora://purchases`.

## Seller tools

| Tool | Does |
|---|---|
| `zanora_provider_status` | verification, suspension, reputation, and why nothing is selling |
| `zanora_request_verification` | asks to be verified (`note?`, `contact?`) |
| `zanora_publish_capability` | publishes one capability (`endpoint` or `runsLocally`) |
| `zanora_publish_capabilities` | publishes several at once |
| `zanora_update_capability` | edits the price, wording, tags, schema or latency |
| `zanora_list_capabilities` | your listings, including deprecated ones |
| `zanora_deprecate_capability` | withdraws a capability |
| `zanora_sales` | receipts for your sales (`limit?`, `after?`) |
| `zanora_earnings` | settlement wallet balance |
| `zanora_payout_destinations` | reads your payout destinations |
| `zanora_rail_transactions` | your payouts and their state |

Resources, all subscribable: `zanora://sales`, `zanora://earnings`, `zanora://catalogue`.

## Protocol details

- Every tool declares an `outputSchema` and returns `structuredContent`. Errors carry no structured content.
- `zanora_invoke` sends four named progress steps when the client provides a progress token.
- Long lists page with `after` and return `nextCursor`.
- Where the client supports elicitation, `zanora_invoke` can ask the user to approve a held spend, or to fund an empty wallet.

## Embedding it

```ts
import { createZanoraMcpServer, loadConfigFromEnv } from "@zanora/mcp";

const { server } = createZanoraMcpServer(await loadConfigFromEnv());
await server.connect(myTransport);
// Seller profile: createZanoraSellerMcpServer(loadSellerConfigFromEnv())
```
