Usage billing for MCP servers

Your MCP server has users.
Make them customers.

Tollgate meters every tools/call, hands out API keys with 200 free credits, and answers "out of credits" with a checkout link the calling agent can follow. One wrapper around your fetch handler — your tools stay yours.

TypeScript SDK · MIT · zero runtime deps · Workers, Node 18+, Deno, Bun

src/index.ts — the whole integration
import { Tollgate, D1Store } from "@tollgate/sdk";

export default {
  async fetch(req: Request, env: Env) {
    const tollgate = new Tollgate({
      store: new D1Store(env.DB),
      signupUrl: "https://your.dev/signup",
      checkoutUrl: "https://your.dev/buy",
    });
    return tollgate.protect(
      req,
      ({ message, ctx }) =>
        yourMcpHandler(message, ctx), // unchanged
    );
  },
};
calls metered on this instance
counted live from its D1, nothing pre-seeded

The 402 MCP never had

Errors that sell.

MCP has no payment primitive, so Tollgate answers in the protocol's own language: structured JSON-RPC errors with the URL that fixes them. Agents read the message; tooling reads the data.

no key → -31401
{
  "code": -31401,
  "message": "This method requires an
    API key. Get one free at
    tollgate.dev/signup — 200
    credits included.",
  "data": {
    "signup_url": "…/signup"
  }
}
out of credits → -31402
{
  "code": -31402,
  "message": "Out of credits
    (0 remaining). Buy more at
    tollgate.dev/dashboard
    ($9 per 1,000 credits)",
  "data": {
    "checkout_url": "…/dashboard",
    "credits_remaining": 0
  }
}
too fast → -31429
{
  "code": -31429,
  "message": "Rate limit exceeded
    (120 requests/minute).
    Retry shortly.",
  "data": {
    "retry_after_seconds": 30
  }
}

Codes are HTTP-mnemonic (401 / 402 / 429) and sit outside the JSON-RPC reserved range and the codes the MCP spec uses — they can't be misread. Discovery stays free: initialize, tools/list, ping never cost a credit.

Proof, not promises

A real paid server runs on it.

This site is an MCP server: live AI-ecosystem data — LLM prices, the official MCP registry, AI tool changelogs. Every record carries source_url and collected_at. It bills through the same SDK you just read about.

toolwhat it answerscost
ai_ecosystem_overviewwhat's inside, how freshfree
llm_pricingprices & limits, 8 providers, 142 models1
llm_price_compareyour workload costed across models1
mcp_servers_searchofficial registry, 329 servers1
mcp_server_inforemotes, packages, install1
ai_changelogreleases of 6 AI tools + MCP spec1

Bulk reads via MCP resources cost 5 credits per dataset. Counts are from the snapshot collected 2026-06-11; refresh with one command.

connect — any MCP client
# streamable HTTP + bearer key
{
  "url": "https://tollgate.example.dev/mcp",
  "headers": { "Authorization": "Bearer tg_…" }
}
llm_price_compare — real output, data of 2026-06-11
{
  "workload": { "input_tokens": 50000, "output_tokens": 5000, "calls": 1000 },
  "cheapest": "deepseek-chat",
  "comparison": [
    { "model_id": "deepseek-chat",      "total_usd": 8.40  },
    { "model_id": "gpt-5-mini",         "total_usd": 22.50 },
    { "model_id": "gemini-2.5-flash",   "total_usd": 27.50 },
    { "model_id": "claude-haiku-4-5",   "total_usd": 75.00 }
  ],
  "note": "Vendor list prices per 1M tokens;
           caching/batch discounts not applied."
}

Where the numbers come from

models.dev (vendor list prices) cross-checked against the OpenRouter API — 75 agreements, 12 disagreements, both numbers kept when they differ. Registry: registry.modelcontextprotocol.io. Changelogs: GitHub Releases. If a source is down, the collector fails loudly — it never invents a row.

Built like billing, not like a demo

The boring parts, done properly.

No overdraw, ever

A charge is one conditional UPDATE — free credits first, then paid, guarded by WHERE free + paid >= cost. Concurrent calls can race; the balance can't go negative.

Keys you can't leak

Raw keys are shown once. Only SHA-256 hashes are stored; dashboards see tg_a1b2c3d8…. Rotation revokes the old key in the same transaction.

Webhooks that can't double-pay

Lemon Squeezy and Stripe signatures are verified before any state changes, and fulfillment is idempotent on the provider's reference — retries and replays are no-ops.

Pricing

Credits, not subscriptions.

Free

200 credits

On signup, no card. 1 credit = 1 tool call. Discovery and the overview tool are always free.

Start free

Pay as you go

$9 per 1,000 credits

Blocks never expire. Checkout via Lemon Squeezy or Stripe — or the built-in mock driver while you develop.

Buy credits

The SDK itself is MIT — self-host the whole thing for free. Hosted data + billing is the product.

For server authors

Ship a paid MCP server this week.

The quickstart takes a fresh project to a metered, billable MCP server in under 15 minutes — memory store first, D1 and live checkout when you're ready. We timed it.

terminal
$ npm install @tollgate/sdk
$ wrangler d1 execute DB \
    --file=node_modules/@tollgate/sdk/schema.sql
# wrap your handler, deploy, done