Guide · tested 2026-10-15 · about 5 minutes

How do I charge for an MCP tool with x402?

Quick answer: a paid MCP tool doesn’t send HTTP 402. Under the x402 MCP transport spec it returns a tool result with isError: true and the payment requirements, the client retries the same call with the payment in _meta["x402/payment"], and the server settles and adds _meta["x402/payment-response"]. On Cloudflare, withX402 and paidTool from agents/x402 do this for you. Before mainnet, check three things we hit in testing: the facilitator, the wire format, and when settlement happens.

1. The flow, step by step

  1. The client calls the tool with no payment.
  2. The server answers with isError: true and a PaymentRequired object (x402Version, resource, accepts). The spec requires it in both structuredContent and content[0].text.
  3. The client signs a payment for one of the accepts entries and repeats the call with it in _meta["x402/payment"].
  4. The server verifies the payment, runs the tool, settles, and returns the result with _meta["x402/payment-response"]. If settlement fails, it returns the payment error and not the tool’s content.

2. The Cloudflare setup

Cloudflare’s guide wraps an McpServer with withX402 and registers paid tools with paidTool(name, description, priceUSD, schema, annotations, handler). Free and paid tools can sit in the same server. Its x402-mcp example uses network: "eip155:84532" (Base Sepolia) with the x402.org facilitator, and that combination worked in our test.

3. On mainnet, the docs’ facilitator fails

The Cloudflare page’s config pairs network: "base" with https://x402.org/facilitator. We ran it on 2026-10-15 with agents 0.28.1 (the current npm release) and @x402/core 2.28.0. Every call to the paid tool returned:

{"x402Version":2,"error":"PRICE_COMPUTE_FAILED"}

The reason is the facilitator’s /supported list: on 2026-10-15 it had eip155:84532 (Base Sepolia) and no eip155:8453 (Base mainnet). We changed only the facilitator URL to https://facilitator.payai.network, whose /supported list includes eip155:8453. The tool then returned valid requirements for Base mainnet USDC (0x8335…2913, amount 10000 for $0.01). Pick a mainnet facilitator by cost with this comparison, or read which facilitators work on Base mainnet.

To reproduce it yourself (nothing is paid, and the recipient is a burn address):

// test.mjs: npm i agents@0.28.1 @x402/core @x402/evm @modelcontextprotocol/sdk zod
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { withX402 } from "agents/x402";
import { z } from "zod";

for (const network of ["base-sepolia", "base"]) {
  const server = withX402(new McpServer({ name: "t", version: "1.0.0" }), {
    network,
    recipient: "0x000000000000000000000000000000000000dEaD",
    facilitator: { url: "https://x402.org/facilitator" },
  });
  server.paidTool("square", "Squares a number", 0.01, { number: z.number() }, {},
    async ({ number }) => ({ content: [{ type: "text", text: String(number ** 2) }] }));
  // Test-only shortcut: _registeredTools is a private McpServer field. A real client sends
  // tools/call over a transport; here we call the handler with no payment, like that first call.
  const res = await server._registeredTools["square"].handler(
    { number: 3 }, { _meta: {}, requestInfo: { headers: {} } });
  console.log(network, res._meta["x402/error"].error);
}

On 2026-10-15 this printed base-sepolia PAYMENT_REQUIRED and base PRICE_COMPUTE_FAILED.

4. Check the wire format against your client

We read the agents 0.28.1 source and tested it. It differs from the spec in two places:

Whatx402 MCP specagents 0.28.1 paidTool
Payment requirementsstructuredContent and content[0].text (both required)_meta["x402/error"] and content[0].text, no structuredContent
Payment from the clienta JSON object in _meta["x402/payment"]a base64 string there, or a PAYMENT-SIGNATURE or X-PAYMENT header

When we sent a spec-shaped object in _meta["x402/payment"], the server ignored it and answered PAYMENT_REQUIRED again. The same payload as a base64 string went on to the facilitator (which rejected our fake signature, as expected). Cloudflare’s own withX402Client sends the string, so the two work as a pair. The official @x402/mcp 2.28.0 client code sends the object form; we didn’t run that pairing end to end, so test it before you depend on it.

5. Know when settlement happens

6. Test before mainnet

Run the whole loop on Base Sepolia first with faucet USDC; this guide covers the network, faucet and USDC address. Our free x402 endpoint checker tests HTTP endpoints that answer 402, not MCP tool results, so for MCP the script above (or Cloudflare’s example client) is the check.

FAQ

Does a paid MCP tool return HTTP 402?

No. Under the x402 MCP transport spec the server returns a normal tool result with isError: true and the PaymentRequired object. The client retries the same tools/call with the payment in _meta["x402/payment"].

Why does my Cloudflare paidTool return PRICE_COMPUTE_FAILED?

In our test (agents 0.28.1) it happened when network was "base" (Base mainnet) and the facilitator was https://x402.org/facilitator. That facilitator’s /supported list has Base Sepolia but not Base mainnet. Pointing the same code at a facilitator that lists eip155:8453 fixed it.

Can any x402 MCP client pay a Cloudflare paidTool?

Not necessarily. agents 0.28.1 only accepts the payment as a base64 string in _meta["x402/payment"] (or a PAYMENT-SIGNATURE or X-PAYMENT header). The spec’s example sends a JSON object there, and in our test an object got PAYMENT_REQUIRED back. Cloudflare’s own withX402Client sends the string form.

Does the tool run before the payment settles?

Yes, in agents 0.28.1: it verifies the payment, runs your tool, then settles. If settlement fails it returns a payment error instead of the result, as the spec says, but anything your tool already did has happened.

Sources, checked 2026-10-15: x402 MCP transport spec, Cloudflare: Charge for MCP tools, agents x402.ts source, Cloudflare x402-mcp example, x402.org /supported, PayAI /supported, @x402/mcp package, x402 docs: MCP Server with x402. Test versions: agents 0.28.1, @x402/core 2.28.0, @x402/mcp 2.28.0, @modelcontextprotocol/sdk 1.32.1.

Selling a file rather than a tool? The x402 Seller Kit is a tested Cloudflare Worker that sells a file for USDC on Base mainnet without a facilitator. The README is free to read.

Get the kit · $29