How to monetize your MCP server in 5 minutes
Wrap any tool with a per-call USDC charge. Two lines of code. Agents pay automatically. You keep 99.5%.
spawnpay-paywall. Wrap your tool's async handler with paywall({ price, vendor }, fn). Done. Calling agents already have wallets — they pay the moment they call.
The problem
You shipped an MCP server. Agents are using it. You're eating LLM costs, scrape costs, or compute, and there's no way to charge for it. Stripe forces a credit-card form, every agent would need a human in the loop, and most agents can't move money in the first place.
That's the gap Spawnpay fills.
STEP 1Get a wallet
This is for your side, the tool author. Either:
- Run
npx -y spawnpay-mcpin any MCP client (Claude Desktop, Cursor, Cline, …). On first use you'll get aspk_live_key plus aSP_xxxreferral code. That code is your vendor address. - Or hit
POST https://spawnpay.ai/api/signupand capture thereferralCodefrom the response.
STEP 2Install the SDK
npm install spawnpay-paywall
Python? pip install "git+https://github.com/Robocular/spawnpay#subdirectory=packages/paywall-py"
STEP 3Wrap your tool
You have an async function that does the work. Wrap it:
import { paywall } from 'spawnpay-paywall';
// Your original implementation, untouched.
async function decompile({ binary_path }) {
return await runGhidraOn(binary_path);
}
// Add a price + vendor. That's it.
export const paidDecompile = paywall(
{ price: 0.10, vendor: 'SP_yourCode', description: 'decompile' },
decompile,
);
Every call to paidDecompile now does this in order:
- Look up the calling agent's
SPAWNPAY_API_KEY. - Charge $0.10 USDC from their wallet to
SP_yourCode. - If the charge fails, throw
PaywallErrorand never run the original. - If it succeeds, run the original and return the result.
STEP 4Wire it into your MCP server
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';
server.setRequestHandler(CallToolRequestSchema, async (req) => {
if (req.params.name === 'decompile') {
try {
const result = await paidDecompile(req.params.arguments);
return { content: [{ type: 'text', text: JSON.stringify(result) }] };
} catch (err) {
// err.code is one of: NO_API_KEY, INSUFFICIENT_BALANCE,
// CREDIT_LOCKED, BUDGET_DAILY, BUDGET_PER_CALL, etc.
return { content: [{ type: 'text', text: `[${err.code}] ${err.message}` }], isError: true };
}
}
});
STEP 5Ship
Publish to npm or attach the tarball to a GitHub release. The agent's MCP config just points command: "npx", args: ["-y", "your-tool"], with SPAWNPAY_API_KEY in env.
That's the whole loop. Your tool now charges agents per call without Stripe, without subscriptions, without card forms.
What you get for free
- Idempotency. Auto-keyed by hashing your description + input + 60-second bucket. Retries from the agent don't double-charge.
- Receipts. Every charge writes a tx hash to the transactions table. Public on Basescan.
- Budgets. Pass
budget: { daily, perCall, warnAt }and the SDK enforces a rolling-24h cap before charging. - 3-level referrals. Agents who signed up via your code earn you 15% of their platform fees + 5% + 2% on the next two levels.
Common gotchas
The agent has no SPAWNPAY_API_KEY
They need to install spawnpay-mcp first (one-time signup → $5 free credit). Then the MCP client passes the key through to your tool's environment via the MCP server's env map.
The first charge fails with CREDIT_LOCKED
Signup credit has a 24-hour lockup so people can't farm-and-dump bonuses to scam authors. Treasury-bound charges (scrape, proxy, our own tool calls) are exempt — they spend signup credit immediately. Agent-to-vendor charges via your paywall enforce the lock unless the agent has run any send already (which unlocks it instantly).
Want to be exempt? Configure your paywall to charge a small fixed treasury fee on top so the agent never hits the lock. Or accept that first-touch friction = built-in spam protection.
I don't want USDC payouts, just an analytics signal
Set the vendor to a wallet you control on Base. Withdraw whenever. Or use Spawnpay's spawnpay_send from your dashboard to off-ramp internally.
Bonus: route premium calls through the universal proxy
If your tool needs to hit OpenAI / Anthropic / Replicate / etc., you can either pay yourself with your own keys, or route them through Spawnpay's universal proxy for unified billing. Your agent's spk_ key pays for the routing + provider cost; you keep your provider relationship clean.