ZanoraBetaDocs

Sell

Run @zanora/mcp in seller mode to publish, edit, request verification, and follow sales and earnings from Claude or any MCP client. It can see money but can't move it.

The same @zanora/mcp package that buyers use has a seller profile. It takes a provider key and no wallet key, and gives the model eleven tools for running your listings.

It publishes listings; it doesn't serve them

Publishing says what's for sale and where. The endpoint or MCP server at that address still has to run the Zanora middleware (MCP or HTTP) to charge for calls.

Add it

MCP config
{
  "mcpServers": {
    "zanora-seller": {
      "command": "npx",
      "args": ["-y", "@zanora/mcp"],
      "env": {
        "ZANORA_ROLE": "seller",
        "ZANORA_API_KEY": "zk.akey_…"
      }
    }
  }
}

The key is checked against the gateway when the server starts, so a buyer key here fails immediately. A wallet key in a seller config is also refused: sellers don't sign payments, so a spending key there is a mistake.

The tools

ToolDoes
zanora_provider_statusverified? suspended? reputation? and why nothing is selling
zanora_request_verificationasks an operator to make you discoverable, with your note
zanora_publish_capabilitypublishes one capability: REST or MCP, a URL or a pinned package
zanora_publish_capabilitiespublishes a whole catalogue in one call
zanora_update_capabilityedits price, wording, tags, schema or latency, keeping the id. Refuses to move the address
zanora_list_capabilitiesyour own listings, including deprecated ones
zanora_deprecate_capabilitywithdraws a capability from sale
zanora_salessigned receipts for what you sold. Pages with after
zanora_earningsyour settlement wallet's balance
zanora_payout_destinationsreads where payouts go
zanora_rail_transactionspayouts: the amount, where each was sent, and its real state

There's no payout tool and no tool to change your payout destination. Changing where payouts go is the first thing someone does with a stolen credential. That's a person's action in the console, with a 24-hour freeze and an alert.

Being told about sales

The seller profile serves three resources that clients can subscribe to:

ResourceContents
zanora://salessigned receipts for completed calls, newest first
zanora://earningsthe settlement wallet's balance
zanora://catalogueeverything you've published

While a client is subscribed, the server checks for changes (ZANORA_SALES_POLL_MS, default 20 seconds, minimum 5) and sends notifications/resources/updated when something changes. A publish, edit or deprecate made through this server updates zanora://catalogue straight away.

Subscribing

Subscribing is something your MCP client does, not the model and not a config setting. The client sends resources/subscribe with the resource's URI, then re-reads the resource each time a notifications/resources/updated arrives for it. Whether you can do this from a chat app depends on the app. Many let you attach or read a resource, but don't keep a subscription open. Check your client's documentation for resource subscriptions.

If your client doesn't subscribe, you can still read the same information on demand. Read the resource, or ask the model to call the tool behind it: zanora_sales, zanora_earnings or zanora_list_capabilities. The resources are built from those tools, so both give the same answer.

To be told about sales from your own code, start the seller profile with the MCP SDK's client and subscribe:

watch-sales.ts
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";
import { ResourceUpdatedNotificationSchema } from "@modelcontextprotocol/sdk/types.js";

const transport = new StdioClientTransport({
  command: "npx",
  args: ["-y", "@zanora/mcp"],
  env: { ...process.env, ZANORA_ROLE: "seller", ZANORA_API_KEY: process.env.ZANORA_API_KEY! } as Record<string, string>,
});
const client = new Client({ name: "sales-watcher", version: "1.0.0" });
await client.connect(transport);

// A notification only names the resource. Read it again to see what changed.
client.setNotificationHandler(ResourceUpdatedNotificationSchema, async ({ params }) => {
  const { contents } = await client.readResource({ uri: params.uri });
  console.log(`${params.uri} changed`, contents[0]);
});

await client.subscribeResource({ uri: "zanora://sales" });
await client.subscribeResource({ uri: "zanora://earnings" });
  • The first notification is the first change. Subscribing records the current state without announcing it, so subscribing to a quiet feed is silent until a sale lands.
  • It only runs while the server runs. The seller profile is a local process your client starts. It polls only while something is subscribed, and stops when the client disconnects or calls unsubscribeResource. Nothing is delivered while it's closed; read zanora_sales afterwards to catch up.
  • Any other URI is refused. Only the three resources above can be subscribed to.

Try it

Output
Check my Zanora seller status. If I'm not verified, request verification with a note
saying we run an invoice OCR API used by ~200 companies. Then publish an MCP capability
"extract_invoice" at https://acme.example/mcp for $1.00 in category OCR.