Paying for tools from an agent
Discovery is free and every MCP client can do it. Paying needs a client that understands HTTP 402 — here is what that means and how to get one.
Why your client returned an error
If you connected a standard MCP client — Claude Desktop, Cursor, or anything else that speaks plain MCP — you can list the catalogue and call any free tool. A paid tool answers HTTP 402 Payment Required, and most clients have no handler for it.
That is not a bug in your client or in ours. Paying means holding a wallet and signing a transfer, and an MCP client is not required to do either. The capability lives in the client, so the fix is a client that has it.
What an x402-capable client is
A client that, on receiving a 402, reads the payment terms from the response, signs an EIP-3009 authorisation for the exact amount, and retries the request with that authorisation attached. The whole exchange is two HTTP round trips, and the payee is the provider’s own wallet — Fatstack is never in the payment path.
Quickstart
payFetch from @fatstack/x402 is a drop-in fetch that does the above. Point it at the aggregating MCP endpoint and call any listing.
Paying for a tool call
import { payFetch } from '@fatstack/x402';
import { privateKeyToAccount } from 'viem/accounts';
const wallet = privateKeyToAccount(process.env.AGENT_PRIVATE_KEY as `0x${string}`);
// payFetch calls, reads the 402, signs an EIP-3009 authorisation, and retries.
// The provider is the payee. Fatstack never receives the funds.
const response = await payFetch(
'https://www.fatstack.net/api/mcp',
{
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({
jsonrpc: '2.0',
id: 1,
method: 'tools/call',
params: { name: 'echo__echo_json', arguments: { payload: { hi: true } } },
}),
},
{
wallet,
networks: ['base'],
// Required. No default, by design.
guards: { maxPerDay: 1, maxPerCall: 0.01 },
},
);The endpoint itself is one URL for the whole catalogue:
MCP client configuration
{
"mcpServers": {
"fatstack": {
"type": "http",
"url": "https://www.fatstack.net/api/mcp"
}
}
}Spend guards are required
guards has no default. A client that can spend money should not be constructible by forgetting something. Omit it and you get a type error, and at runtime a MissingSpendGuardError thrown before anything is fetched — so the failure lands on the line that forgot it rather than looking like a network problem later.
maxPerDay is a hard USD ceiling per UTC day and is required. maxPerCall is optional and refuses any single call above it. Guards are evaluated after the quote is known and before anything is signed, so exceeding one throws with nothing signed and nothing spent.
What happens if you omit it
// Throws MissingSpendGuardError before the catalogue is fetched.
await payFetch(url, init, { wallet, networks: ['base'] });A ceiling is a cap, not a cure. An attacker holding the key can spend up to it, and payments are final. Fund an agent wallet with what you are willing to lose in a day.
Payments are final. No refunds. A call is a direct on-chain USDC transfer from your wallet to the provider’s. Once settled, nobody — including Fatstack — can reverse it.