I Put Trading Tools Behind MCP With Per-Call Pricing — and Fixed the One Bug That Breaks x402 for MCP Builders ScriptMasterLabs shipped a paid MCP gateway where tools/list is free and tools/call costs $0.05 in USDC per call, settled via x402 v2 on Base with no signup or API keys. The developer reports that MCP clients swallow JSON-RPC errors before the model sees them, so the payment challenge never reaches the agent; the fix is to return the challenge as a successful result with isError: true and the x402 accepts array in structuredContent. The gateway exposes trading and telemetry tools (get_market_cycle, scrape_url) with fail-closed commerce, returning no-charge errors on failed delivery. I shipped a paid MCP gateway today: tools/list is free, tools/call costs $0.05 in USDC per call, settled via x402 v2 on Base. It's live right now — no signup, no API keys. The payment is the credential. But the real story isn't the pricing. It's the implementation detail that every MCP builder attempting x402 will hit — and that quietly breaks the entire payment flow if you miss it. Here's what happens when you bolt x402 onto an MCP server the naive way. The agent calls tools/call without payment. Your server returns a JSON-RPC error: -32000, Payment Required . Done, right? Wrong. MCP clients swallow JSON-RPC errors before the model ever sees them. The client sees an error code, the model sees "tool call failed," and the payment challenge — the accepts array, the price, the payTo — never reaches the agent. The agent can't pay because it never learned the price. This is documented by anchor-x402 18 paid x402 services, MIT-licensed , and I hit it myself. The fix is simple but non-obvious: Return the payment challenge as a successful result with isError: true , not as a JSON-RPC error. { "jsonrpc": "2.0", "id": 3, "result": { "content": { "type": "text", "text": "Payment required: $0.05 USDC. Sign and retry with PAYMENT-SIGNATURE." } , "structuredContent": { "x402Version": 2, "accepts": { "scheme": "exact", "network": "eip155:8453", "amount": "50000", "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", "payTo": "0xc29185fa176357612f3194735753e520e91adc46" } }, "isError": true } } The agent model reads this, sees the price and the challenge, signs an EIP-3009 transferWithAuthorization , and retries. The flow works end-to-end. isError: true means the client passes it through to the model instead of eating it. The second design decision I copied from anchor-x402: tools/list and discovery are always free. This is correct by construction — agents can't discover what they can't see. Charging for tools/list is a paywall on your own storefront. The full pattern: tools/list → free, always tools/call → paid, isError: true result on unpaid attempts /.well-known/x402 → free, machine-readable manifest Every byte of actual data sits behind a 402. Everything the agent needs to decide to buy is free. That's the whole distribution model for machine commerce. The x402 MCP space is filling fast at the utility layer: converters, validators, formatters at $0.001–$0.02/call anchor-x402, agent402 . Real numbers from the wild: an MCPize author reports ~$8,500/mo net on a security-auditor server; self-hosted x402 did 3.3M transactions in 30 days at ~$0.46 average. But nobody does trading or telemetry MCP tools. That's the lane I took: get market cycle scrape url Both follow fail-closed commerce: bot-blocked pages, bad symbols, garbled output return no-charge errors. Failed delivery never earns payment. Firecrawl's charge-on-4xx is a cited complaint in the ecosystem; I went the other way. Free: list the tools curl -X POST https://squeezeos-api.onrender.com/v1/mcp \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}' Paid: this returns the challenge as an isError result curl -X POST https://squeezeos-api.onrender.com/v1/mcp \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","id":2,"method":"tools/call", "params":{"name":"get market cycle","arguments":{"symbol":"AAPL"}}}' The manifest is at https://squeezeos-api.onrender.com/.well-known/x402 . x402 v2, USDC on Base, CDP facilitator sponsors gas. If you're putting x402 payments on your MCP server: never return the challenge as a JSON-RPC error. isError: true result, challenge in structuredContent . That's the difference between a payment flow that works and one that silently dies in the client. Built by ScriptMasterLabs service-disabled veteran-owned small business . Happy to answer questions about the x402 integration or the verify→execute→accept→settle flow.