checkout402_
Guides

Sell MCP tools#

You run an MCP server. Agents want your tools. You would rather not run accounts, keys, quotas or invoices for any of them.

An mcp checkout puts a price on a tool call. We connect to your server as a client, call the tool, and return the result to whoever paid.


Two products, not one#

This is the decision that shapes everything else, so make it first.

c402 checkouts create --title "Company search" --price 0.10 \
  --origin-url https://mcp.yourco.com/mcp \
  --mcp-tool search_companies

One price, one named tool. The buyer cannot call anything else — enforced on every call, not just the first.

c402 checkouts create --title "All my tools" --price 25.00 \
  --fulfillment mcp \
  --origin-url https://mcp.yourco.com/mcp \
  --calls 500

One price for any tool. The buyer names one per call.

Per tool Whole server
Buyer picks the tool ✗ you did ✓ per call
Price can be right only if your tools cost the same
Discovery for the buyer they know what they want they can explore

Whole-server pricing has an economics problem

If your server has a cheap ping and an expensive deep_research, one price across both is either overpriced for the cheap call or loss-making on the dear one — and a rational buyer spends the whole package on the expensive tool. Sell the whole server only when your tools cost roughly the same. Otherwise price them separately.

The whole server is the one shape that cannot be inferred

A bare origin_url is always a relay. To sell a whole MCP server you must say --fulfillment mcp explicitly, because nothing else in the request distinguishes it.


Find out what you are selling#

Before pricing a tool, ask your own server what it has:

c402 mcp tools https://mcp.yourco.com/mcp
c402 mcp tools https://mcp.yourco.com/mcp --auth-type bearer --auth-value "$KEY"

Nothing is stored. It exists so a checkout is built from a name your server actually advertises — an agent that guesses a tool name creates a checkout that takes money and then fails on a tool the origin has never heard of, which is a failure only a buyer can discover, after paying.

Your server describes itself, so you do not have to

tools/list returns each tool's description and input schema. When you pin a tool, we keep both and fill in the offer card for you. You do not retype what your own server just told us.


Why this is not just a relay#

An MCP endpoint is JSON-RPC over POST, so it looks like something a relay checkout could wrap. It cannot, for four reasons — and the last one is about money.

What a plain relay would do
initialize handshake Skip it. Spec-compliant servers then reject the call
mcp-session-id Return it on initialize and never echo it back
SSE framing Forward progress notifications to the buyer as if they were the answer
isError: true inside HTTP 200 See a 200, record "delivered", and charge for a failure

So mcp speaks the protocol properly. If we did not, your alternative would be to expose a plain HTTP endpoint and use relay — a different product.


How a buyer calls it#

Pinned to one tool — they send arguments, nothing else:

curl "https://api.checkout402.com/c/chk_abc123?q=acme" \
  -H "Authorization: Bearer pk_…"

Whole server — they name the tool:

curl "https://api.checkout402.com/c/chk_abc123?tool=search_companies&q=acme" \
  -H "Authorization: Bearer pk_…"

Everything except tool becomes an argument to it. Arguments are strings; send arguments as a JSON object when a tool needs numbers or nesting.

The result comes back as the goods:

{ "fulfillment": { "mode": "mcp", "tool": "search_companies",
                   "payload": {  the tool's result  } } }

Pinning is enforced by us, not by the signature#

Worth understanding, because it is the difference between a price and a suggestion.

On a single call, the tool name is folded into the string the buyer signs — swap it and verification fails. But a package key is a bearer token with no signature at all. Binding alone would let someone who bought 500 calls of a 1¢ tool spend them on a $5 one.

So a pinned checkout checks the tool server-side on every call. A buyer who names a different one is refused, and it costs them the call.


Selling calls in bulk#

MCP checkouts can be packages, in either shape:

c402 checkouts create --title "500 searches" --price 25.00 \
  --origin-url https://mcp.yourco.com/mcp --mcp-tool search_companies --calls 500

One settlement, then a pk_… key that spends a counter. Minimum $1.00, expires in 30 days by default, capped at 60 calls/minute per key.

Buying a whole-server package does not spend a call

Purchasing 500 calls is buying an allowance, not making one — you cannot name a tool when the thing you are buying is 500 of them. The purchase returns the key with all 500 intact. A pinned package does deliver one call at purchase, exactly like relay, because it knows its tool.


When a call fails#

Your server Buyer charged
Transport 5xx, timeout, unreachable No
Malformed reply, no result No
JSON-RPC -32601 — tool not found No (you pinned a tool your server lacks)
JSON-RPC -32602 — invalid params Yes
isError: true from the tool Yes
Wrong tool named on a pinned checkout Yes

isError is the debatable one, so here is the reasoning: MCP gives no way to tell "your arguments were wrong" from "my database is down". The tool ran and consumed your compute, and the symmetric relay case — an origin returning 400 — is charged too. Refunding it would leave MCP checkouts as the one type where a buyer can probe indefinitely for free.

The cost of that choice is that a genuinely broken server bills its buyers. So every isError is tagged on the delivery record and visible to you, and a buyer can report it.


Before you go live#

Rehearse on the test face. Your server is a live dependency at purchase time; a checkout that works in your terminal and not from our network is a failure a buyer discovers after paying. /c/chk_abc123/test runs the whole loop — including the real call to your MCP server — with simulated settlement. When it works, arm the checkout in place:

c402 checkouts go-live chk_abc123

Same id, same URL; the test face keeps rehearsing forever.

Check the credential path. If your MCP server needs auth, store it once and rotate in one place:

c402 origin-keys add --auth-type bearer --value "$MCP_KEY" --name mcp-prod

It is injected server-to-server and never reaches a buyer.


What next#