pay_x402
Pay for an x402-protected HTTP resource after receiving a 402 Payment Required response. Provides a payment header to include in the retry request.
Instructions
Pay for an x402-protected HTTP resource (HTTP 402 Payment Required). Use after receiving a 402 response. Returns a paymentHeader to include in the retry request as X-PAYMENT header.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| url | Yes | The URL that returned HTTP 402 | |
| maxAmount | Yes | Maximum USDC to pay, e.g. "1.00" | |
| recipient | Yes | Merchant's Ethereum address (from the 402 response) | |
| network | No | Chain ID, defaults to "eip155:8453" (Base Mainnet) | |
| asset | No | USDC contract address (from the 402 response) | |
| idempotencyKey | No | Optional key to prevent duplicate payments on retry |
Implementation Reference
- src/index.ts:184-208 (registration)The server.tool() call that registers the 'pay_x402' tool with the MCP server, including its description, input schema, and handler.
server.tool( "pay_x402", "Pay for an x402-protected HTTP resource (HTTP 402 Payment Required). Use after receiving a 402 response. Returns a paymentHeader to include in the retry request as X-PAYMENT header.", { url: z.string().describe("The URL that returned HTTP 402"), maxAmount: z.string().describe('Maximum USDC to pay, e.g. "1.00"'), recipient: z.string().describe("Merchant's Ethereum address (from the 402 response)"), network: z.string().optional().describe('Chain ID, defaults to "eip155:8453" (Base Mainnet)'), asset: z.string().optional().describe("USDC contract address (from the 402 response)"), idempotencyKey: z.string().optional().describe("Optional key to prevent duplicate payments on retry"), }, async ({ url, maxAmount, recipient, network, asset, idempotencyKey }) => { try { const body: Record<string, unknown> = { url, maxAmount, recipient }; if (network) body.network = network; if (asset) body.asset = asset; if (idempotencyKey) body.idempotencyKey = idempotencyKey; const res = await callApi("POST", "/x402/pay", body); if (!res.ok) return errorResponse("x402 payment failed", res); return successResponse(res.json); } catch (e) { return { content: [{ type: "text" as const, text: `x402 payment error: ${e}` }], isError: true }; } }, ); - src/index.ts:187-194 (schema)Zod-based input schema for pay_x402: url, maxAmount, recipient (required), network, asset, idempotencyKey (optional).
{ url: z.string().describe("The URL that returned HTTP 402"), maxAmount: z.string().describe('Maximum USDC to pay, e.g. "1.00"'), recipient: z.string().describe("Merchant's Ethereum address (from the 402 response)"), network: z.string().optional().describe('Chain ID, defaults to "eip155:8453" (Base Mainnet)'), asset: z.string().optional().describe("USDC contract address (from the 402 response)"), idempotencyKey: z.string().optional().describe("Optional key to prevent duplicate payments on retry"), }, - src/index.ts:195-207 (handler)The async handler function that executes pay_x402 logic: calls POST /x402/pay on the CardZero API with the provided parameters, returns the payment header for retrying the original 402 request.
async ({ url, maxAmount, recipient, network, asset, idempotencyKey }) => { try { const body: Record<string, unknown> = { url, maxAmount, recipient }; if (network) body.network = network; if (asset) body.asset = asset; if (idempotencyKey) body.idempotencyKey = idempotencyKey; const res = await callApi("POST", "/x402/pay", body); if (!res.ok) return errorResponse("x402 payment failed", res); return successResponse(res.json); } catch (e) { return { content: [{ type: "text" as const, text: `x402 payment error: ${e}` }], isError: true }; } },