Skip to content

Viraltbh/toolmint

Repository files navigation

ToolMint

A drop-in monetization layer for MCP servers. Keep your own endpoint — wrap it, get API keys, per-call metering, and a usage/billing dashboard in minutes.

The gap it closes

There are 20,000+ MCP servers in the wild. Fewer than 5% have ever earned a dollar, and ~40% ship with no auth at all — not because nobody wants to charge, but because building an MCP tool takes a weekend; monetizing it takes weeks of billing plumbing: keys, hashing, rate limits, metering, quota enforcement, a dashboard, a payment rail.

ToolMint is the thin dev-first layer that collapses that to a config change. You point it at your MCP/HTTP endpoint (UPSTREAM_URL); it fronts your traffic and adds the parts you didn't want to build. It runs on the same primitives a working paid MCP already needs — a Cloudflare Worker, D1, and the x402 micropayment rail — just productized so you don't re-derive them.

What you get (MVP)

  1. Reverse proxy — a Worker that faithfully forwards every request (method, path, query, body, headers; response streamed back, so SSE/JSON-RPC pass through) to your configured upstream.
  2. API-key auth — issue keys (POST /admin/keys), validate them on every call via X-API-Key or Authorization: Bearer. Unauthed → 401. Only a SHA-256 hash is stored, never the raw key.
  3. Per-call metering — every authed call logs {key_id, path, ts, status, units} to D1. A free-tier monthly quota is enforced per key → 402 when exceeded (the hook for paid upgrades).
  4. Usage dashboard — a minimal HTML page (/dashboard) showing calls per key, this-month usage vs quota, and totals — read straight from D1.
  5. Billing hook — a documented seam (/billing/upgrade) where a settled x402 (or Stripe) payment raises a key's quota. Manual admin top-ups work today; the x402 settlement layer is pre-wired and flips on with one config change.

5-minute quickstart

cd toolmint
npm install

# 1. point ToolMint at YOUR MCP server (edit wrangler.jsonc -> vars.UPSTREAM_URL)
#    e.g. "UPSTREAM_URL": "https://my-mcp-server.example.com"
#    (leave the default to demo against the built-in echo upstream)

# 2. set a local admin secret
cp .dev.vars.example .dev.vars        # then edit ADMIN_SECRET

# 3. create the metering tables in a LOCAL D1
npx wrangler d1 execute toolmint --local --file=./schema.sql

# 4. run it
npx wrangler dev

Then, in another terminal:

# issue a key (returns api_key ONCE — store it)
curl -s -X POST http://127.0.0.1:8787/admin/keys \
  -H "Authorization: Bearer dev-admin-secret-change-me" \
  -H "content-type: application/json" \
  -d '{"name":"my-first-key"}'

# call your API through ToolMint with that key — metered + quota-gated
curl -s http://127.0.0.1:8787/anything?foo=bar -H "X-API-Key: tm_live_..."

# see the metered call(s)
open http://127.0.0.1:8787/dashboard?key=dev-admin-secret-change-me

A call with no key returns 401. Once a key passes its monthly quota, calls return 402 pointing at the upgrade endpoint.

Going to production

npm run db:create                       # creates the D1, prints a database_id
# paste that id into wrangler.jsonc -> d1_databases[0].database_id
npm run db:apply:remote                 # apply schema to the production D1
npx wrangler secret put ADMIN_SECRET    # set the real admin secret
npm run deploy

Configuration (wrangler.jsonc vars)

Var Meaning
UPSTREAM_URL The MCP/HTTP endpoint ToolMint fronts. Set this to your server.
FREE_MONTHLY_QUOTA Calls per key per month before 402. Default 1000.
HOP_HEADERS Comma-separated headers stripped before forwarding.
SERVICE_NAME Display name on the dashboard / manifest.
X402_ENABLED "true" turns on the x402 paywall for quota upgrades.
X402_NETWORK base-sepolia (testnet, free facilitator) or base (mainnet).
PAY_TO Wallet that receives upgrade payments.
PRICE_PER_UPGRADE Price of one quota upgrade, e.g. "$5.00".
UPGRADE_QUOTA_GRANT Calls added to a key's quota per settled upgrade.

Secrets (never in code — wrangler secret put / .dev.vars): ADMIN_SECRET (required), and on mainnet CDP_API_KEY_ID + CDP_API_KEY_SECRET.

Pricing model

  • Free tier: FREE_MONTHLY_QUOTA calls/key/month. Enough to integrate and demo. Exceed it → 402.
  • Paid quota: a settled payment raises a key's monthly_quota by UPGRADE_QUOTA_GRANT (e.g. $5 → +100k calls). Stack upgrades for more.
  • This is the standard freemium-for-agents shape: zero-friction trial, pay only when volume justifies it, no signup wall — an agent can settle the upgrade itself over x402.

Endpoints

Method / path Auth Purpose
ANY /* API key Proxied to upstream — metered + quota-gated
POST /admin/keys admin Issue a key (api_key shown once)
GET /admin/keys admin List keys + usage (JSON)
POST /admin/keys/:id/revoke admin Revoke a key
POST /billing/upgrade admin / x402 Raise a key's quota
GET /dashboard admin HTML usage dashboard
GET /health free Health check
GET /mcp free ToolMint's own MCP manifest
ANY /__origin free Built-in echo upstream (demo only)

Billing hook — exact integration steps

The grant logic (src/billing.tsgrantUpgrade) is payment-rail agnostic and fully implemented. Two ways to drive it:

Manual / comped (works today, no rail):

curl -X POST http://127.0.0.1:8787/billing/upgrade \
  -H "Authorization: Bearer <ADMIN_SECRET>" \
  -H "content-type: application/json" \
  -d '{"key_id":"<KEY_ID>","quota_add":100000}'

x402 (pre-wired stub — flip on):

  1. In wrangler.jsonc: set X402_ENABLED: "true", X402_NETWORK, and PAY_TO (your wallet).
  2. npm install @coinbase/x402 x402-hono (the dynamic import in src/billing.ts expects them; same versions as the x402-starter repo).
  3. On mainnet, set CDP_API_KEY_ID / CDP_API_KEY_SECRET secrets (testnet uses the free public facilitator — no keys).
  4. Now an agent can GET /billing/upgrade?key_id=..., receive the 402 challenge, pay PRICE_PER_UPGRADE in USDC, and the middleware re-runs the handler — which grants UPGRADE_QUOTA_GRANT calls and writes a billing_events row. (Same settle-then-mint pattern as agentflow's /v1/credits/buy.)

Stripe (v2, not wired): add POST /billing/stripe/webhook, verify Stripe-Signature against STRIPE_WEBHOOK_SECRET, and on checkout.session.completed call the same grantUpgrade(env, keyId, grant, {source:"stripe", ...}).

What's stubbed / deferred to v2

  • Full billing: only the x402 settlement layer is gated behind X402_ENABLED; Stripe is a documented seam, not code. No invoices, proration, or auto-renew (x402 is per-call, so "subscriptions" are time-boxed passes — see agentflow for that pattern).
  • npx create-toolmint packaging: today you clone this repo. v2 = a scaffolder that writes wrangler.jsonc + secrets from a couple of prompts.
  • Hosted multi-tenant: this is single-tenant (one UPSTREAM_URL per deploy). v2 = a control plane where many owners register many upstreams under one ToolMint.
  • Rate limiting / burst control: only monthly quota today; no per-second limits.
  • Usage-based (token) billing: metering already records units (honors an upstream X-Units/X-Tokens-Used header), but quota is enforced on call count, not units.

Schema

schema.sqlapi_keys (id, key_hash, key_prefix, name, monthly_quota, revoked, timestamps), usage_events (key_id, ts, month, path, method, status, units, duration_ms), billing_events (audit of upgrades). A mirror lives in migrations/0001_init.sql for the wrangler d1 migrations apply workflow.

Layout

toolmint/
├── src/
│   ├── index.ts       # Worker: proxy + auth + metering + quota + admin + billing routes
│   ├── db.ts          # D1: key issuance/validation, metering, dashboard reads
│   ├── billing.ts     # the billing seam — grantUpgrade + x402 paywall stub
│   ├── dashboard.ts   # minimal HTML usage dashboard
│   └── types.ts       # Env bindings
├── schema.sql         # D1 tables (apply with wrangler d1 execute)
├── migrations/0001_init.sql
├── wrangler.jsonc
├── package.json
├── .dev.vars.example  # copy to .dev.vars for local secrets
└── README.md

Built on the same primitives as x402-starter (the drop-in paywall) and agentflow (live x402 + D1 metering) — ToolMint productizes that stack for any MCP server.

About

Drop-in auth + metering + billing for MCP servers — API keys, per-call metering, free-tier quota that 402s. Cloudflare Workers + Hono + D1, x402-ready.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors