Everyone writing about paid MCP servers right now is charging per call. It makes sense: the x402 handshake inside tools/call is the obvious pattern, and the exact setup is well documented by now.
I went the other way: a one-time license, no per-call fees. This post is what I learned building and selling an MCP server that way.
What the tool does
Cierre de turno reads your public GitHub activity and writes one sentence that closes your workday: what you finished, what is still open, why it is stuck, and where to start tomorrow. The web version is free. The MCP version, which works from Cursor, Claude Code, OpenCode, or any MCP client, is a one-time 5 USDC payment on Base mainnet.
It is a tool people would use two or three times a day. That is exactly why per-call billing felt wrong: at that cadence, micropayments become a subscription with extra steps. One payment, one license, done.
The payment flow (the standard part)
The buy endpoint answers with the standard 402 and a PAYMENT-REQUIRED header, so any x402-capable client or agent can pay without reading instructions:
// GET /api/comprar returns 402 with:
// { x402Version: 1, accepts: [{
// scheme: "exact", network: "base",
// maxAmountRequired: "5000000", // 5 USDC in atoms
// asset: "0x8335...2913", // USDC on Base
// payTo: "0x...",
// extra: { name: "USDC", version: "2" }
// }]}
The client pays and retries with an X-PAYMENT header. On the server, verify and settle go through a facilitator, and only then a license token is minted:
const wallet = await verificarPago(env, request.headers.get("X-PAYMENT"));
if (!wallet) return json({ error: "Payment not verified." }, 402, { "PAYMENT-REQUIRED": reto });
const token = await crearLicencia(env, wallet); // ct_...
return json({ licencia: token, como_usar: { "x-license": token } });
The license travels as a plain header on every MCP call: x-license: ct_.... No accounts, no OAuth, no dashboard.
Three things that were not obvious
1. Store only the hash. The KV namespace never sees the license token, only sha256(token). If the store leaks, the leak is useless: you cannot reconstruct a working license from it. Cheap to do, and it makes the "no trust, verify" claim real.
2. Cap heavy buyers in the product, not in the contract. A one-time payment plus unlimited calls is a small risk I chose to bound: 200 calls per month per license, tracked in KV with a month key. If someone runs it in a loop, the service stays alive instead of bleeding model tokens. It is approximate on purpose (KV is eventually consistent, a handful of extra calls under extreme concurrency), and that is fine for what it protects.
3. Test the 402 before you can afford to test it. My full payment path was verifiable before anyone paid a cent: a fake X-PAYMENT must produce a clean 402 with a proper challenge, and a valid license must unlock tools/call while initialize and tools/list stay open. The moment of truth (a real wallet paying 5 USDC) is just the last line of a script that already ran a hundred times on fakes.
Facilitators: the detail I almost got wrong
The public x402.org facilitator is convenient for development but is not meant for production mainnet routes. For real USDC on Base there are free public options that need no account (Dexter is the one I use) and Coinbase's CDP facilitator if you want KYT/OFAC checks on every transaction and can live with an account. Making the facilitator URL configurable from day one saved the migration to a two-line change.
What I would tell the per-call crowd
Per-call billing is right when each call is a unit of value: inference, generation, data the buyer resells. When the value is a daily habit, the fee that matches it is a license, and x402 already supports that shape: one 402, one settlement, one token, then a plain header forever. The build patterns everyone is sharing apply either way.
The code is public and auditable, license included: github.com/Luis-Cwk/cierre-de-turno. If you try the MCP and something breaks, the repo issues are open, and I want to hear which part of "close your day in one sentence" is wrong for your workflow.
Top comments (0)