Sell
Manage listings from an MCP client
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.
Add it
{
"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
| Tool | Does |
|---|---|
zanora_provider_status | verified? suspended? reputation? and why nothing is selling |
zanora_request_verification | asks an operator to make you discoverable, with your note |
zanora_publish_capability | publishes one capability: REST or MCP, a URL or a pinned package |
zanora_publish_capabilities | publishes a whole catalogue in one call |
zanora_update_capability | edits price, wording, tags, schema or latency, keeping the id. Refuses to move the address |
zanora_list_capabilities | your own listings, including deprecated ones |
zanora_deprecate_capability | withdraws a capability from sale |
zanora_sales | signed receipts for what you sold. Pages with after |
zanora_earnings | your settlement wallet's balance |
zanora_payout_destinations | reads where payouts go |
zanora_rail_transactions | payouts: 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:
| Resource | Contents |
|---|---|
zanora://sales | signed receipts for completed calls, newest first |
zanora://earnings | the settlement wallet's balance |
zanora://catalogue | everything 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:
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; readzanora_salesafterwards to catch up. - Any other URI is refused. Only the three resources above can be subscribed to.
Try it
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.