Your agent pays for a tool call in 30 seconds
Checked live on Oct 17, 2026. The script in step 3 ran exactly as written with @x402/mcp 2.28.0 and a funded wallet at 11:57 AM CT and settled on Base (tx 0xfee8d931…9dfcd0).
What you need
- A wallet on Base with a little USDC. One call costs between $0.002 and $0.012 (prices in https://grokzilla.shop/api/catalog). You don't need ETH for gas: you sign a USDC authorization and the facilitator submits it.
- Node 18 or later.
1. Add the server
Streamable HTTP, no auth, no API key:
{
"mcpServers": {
"grokzilla-micro-pay": {
"url": "https://grokzilla.shop/mcp"
}
}
}
Any MCP client can list the tools and call the two free ones, list_skills and get_skill. A paid tool returns a payment challenge until your client can pay. That's step 3.
2. Look before you pay (free)
Ask your client for tools/list. Each paid tool's description ends with its price, for example json_repair: "Price $0.0041 via x402."
3. Make one paid call
npm i @x402/mcp @x402/evm @modelcontextprotocol/sdk viem
// pay.mjs: run with PRIVATE_KEY=0x... node pay.mjs
import { createx402MCPClient } from "@x402/mcp";
import { ExactEvmScheme } from "@x402/evm/exact/client";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
import { privateKeyToAccount } from "viem/accounts";
const account = privateKeyToAccount(process.env.PRIVATE_KEY);
const PAY_TO = "0xc22f9caebac37fe72d5142f35f21f6696ea9ef69";
const client = createx402MCPClient({
name: "my-agent",
version: "1.0.0",
schemes: [{ network: "eip155:8453", client: new ExactEvmScheme(account) }],
// Pay only our address, only USDC on Base, at most 2 cents a call.
policies: [(_v, reqs) => reqs.filter(r =>
r.network === "eip155:8453" &&
r.payTo.toLowerCase() === PAY_TO &&
BigInt(r.amount) <= 20_000n)],
onPaymentRequested: ({ toolName, paymentRequired }) => {
console.log(`${toolName}: paying ${paymentRequired.accepts[0].amount} atomic USDC`);
return true;
},
});
await client.connect(new StreamableHTTPClientTransport(new URL("https://grokzilla.shop/mcp")));
const result = await client.callTool("json_repair", { text: "{a: 1, b: [2,3,],}" });
console.log(result.content[0].text);
console.log("tx:", result.paymentResponse?.transaction);
What you get back
The actual output of the run above:
json_repair: paying 4100 atomic USDC
{"skill": "json_repair", "ok": true, "json": {"a": 1, "b": [2, 3]}, "repaired": "{\"a\":1,\"b\":[2,3]}", "fixes": ["unquoted_keys", "trailing_commas"], "changed": true}
tx: 0xfee8d9319effe4eac28e91d3f3c484aed22356846b0db0ea2d758882999dfcd0
What happened:
The first call gets a challenge for 4100 atomic USDC ($0.0041) to 0xc22f9CAEBAc37fE72D5142f35f21f6696Ea9Ef69 on eip155:8453. The client signs it and retries for you. Then you get the repaired JSON. The example in the challenge, for a messier input, looks like this:
{"skill":"json_repair","ok":true,"json":{"name":"Ada","tags":["math","code"],"active":true},
"repaired":"{\"name\":\"Ada\",\"tags\":[\"math\",\"code\"],\"active\":true}",
"fixes":["unquoted_keys","single_quotes","trailing_commas","python_literals","removed_comments"],"changed":true}
result.paymentResponse holds success, payer, transaction and network. transaction is the Base transaction hash, so you can check the payment on-chain.
If the call fails, you get isError: true. Only count it as paid if result.paymentResponse?.transaction is set: the client also reports paymentMade: true when it signed but nothing settled. Bad arguments and a payment that can't be verified both come back this way, unsettled.
For production, also check scheme and asset as shown in spend limits.
More: paid call, step by step · spend limits · MCP quickstart