MCP has no concept of a customer, a plan or a payment. The protocol negotiates capabilities and carries tool calls. Everything about who is allowed to do what is yours to build, and the shape you choose is visible to the user at the exact moment they are refused, which makes it a product decision rather than a plumbing one.
| Shape | Needs a server of yours | Works offline | What you learn about usage |
|---|---|---|---|
| Offline signed key | only to sell the key | yes | nothing |
| Phone-home key check | yes, on every start | no | everything |
| Hosted server with a token | yes, always | no | everything |
The trade is exact: the more you learn about usage, the less the tool can be trusted with private data and the more of it stops working when you do. For a local server that reads someone's invoices, an offline key is the only one of the three that is honest.
A key is a signed statement, not a secret. The format used across the 30 servers here is
MCPL1.<payload>.<signature>, base64url, Ed25519. The payload names the product
and an optional expiry:
{ "v": 1, "p": "invoice", "id": "<license id>", "iat": 1757000000 }
// "p": "*" covers every product in the bundle
// "exp" absent means lifetime
// "h" holds a sha256(email) prefix, so a key can be traced to an order
Verification is a signature check against a public key compiled into the server. No network request is made and no identifier leaves the machine. The private key never ships; it lives on the machine that signs orders.
node scripts/sign-license.mjs invoice buyer@example.com
MCPL1.eyJ2IjoxLCJwIjoi...
Two details worth copying. Validate the payload's shape after checking the signature, not before, and reject anything whose fields are missing or the wrong type: a valid signature over a malformed payload is still malformed. And compare the product field explicitly, so a key for one server does not silently work on another.
Lookup order here: the MCP_LICENSE_KEY environment variable, then
${XDG_CONFIG_HOME:-~/.config}/mcp-servers/license.json, then the free tier. The
environment variable first is what lets a bundle's install dialog pass a key straight through, using
the manifest's user_config substitution, with nothing for the user to save. The file is
written with mode 0600 through a per-process temporary file and a rename, so two servers activating at
once cannot clobber each other.
This is the part people get wrong, and it is the only part the customer ever sees. A refusal that says "upgrade to Pro" has told them nothing. A refusal measured from a stranger's install on 2026-09-08 said:
You have already created 3 invoices in 2026-09. The free tier allows 3 invoices per calendar month.
and then named the price, said the licence is one-time and lifetime, gave the exact next command, and stated that keys verify offline with nothing sent anywhere. Four facts, at the moment they are relevant, to someone who has already found the tool useful enough to hit the limit.
The free tier has to do real work for that to land. Here reads are never metered and writes are, which means a server someone was sent a file for always works, and only producing new documents counts.
Every upgrade link carries ?src=<product>.<tool>, so a click can be traced
to the cap message that produced it. Without that tag, "nobody read the message" and "everybody read it
and did not care" are the same number, which is zero. With it they are different numbers.
What it measured here: 65 upgrade-link clicks in the seven days to 2026-09-05, and not one through a bundle source, because no cap message carried a bundle link at all. The cheaper option was named in prose with nothing to click. That defect is invisible without the tag and obvious with it.
Pricing here is one-time and lifetime, 19 dollars for a single server and 39 for all 30. Every step of the funnel has been verified working from a stranger's position: the free tier does real work, the refusal explains itself, the link redirects to a live Stripe checkout. Sales to date: zero. The constraint was never the gate. It was that 22 people reached the project in fourteen days.
That is worth saying plainly, because most writing on monetising a developer tool is written by people with traffic, and the advice reads differently when you have none. Build the gate so it is honest and attributable, then spend the rest of your time on being found.
Yes, and there is no way to stop it without phoning home. Binding a key to a hashed email and putting a licence id in the payload gives you traceability after the fact, which is the realistic ceiling. Anything stronger costs you the offline guarantee, which is often the reason someone chose a local tool.
A permanent limit is easier to defend and easier to explain. A trial makes the tool stop working for someone who is not ready to decide, and the message they see at that moment is that it broke.
At the call site of the capability being sold, not at startup. A server that refuses to start without a key cannot demonstrate anything, and a user who never sees the tool work has no reason to buy.
No. The protocol has no billing, entitlement or identity concept, and nothing in the current revision suggests it will. Licensing sits entirely in your server's own code.
Compile the public half of a signing keypair into the server and check the signature locally. The key is a signed claim rather than a lookup token, so verifying it needs no service and works on a plane.
All MCP servers and prices · All guides · Buy the bundle $39