The Agents SDK provides paidTool, which registers a tool with x402 payment requirements. Clients pay per tool call, and you can mix free and paid tools in the same server.
agents/x402 needs @modelcontextprotocol/sdk, which is an optional peer dependency of agents. It does not load the package at runtime, but its types refer to MCP SDK v1. Add the exact version your Agents release expects, such as @modelcontextprotocol/sdk@1.32.1, to your package.json.
Wrap your McpServer with withX402 and use paidTool for tools you want to charge for:
import { McpServer } from "@modelcontextprotocol/server";
import { createMcpHandler } from "agents/mcp/server";
import { withX402 } from "agents/x402";
import { z } from "zod";
const X402_CONFIG = {
network: "base",
recipient: "0xYourWalletAddress",
facilitator: { url: "https://x402.org/facilitator" }, // Payment facilitator URL
// To learn more about facilitators: https://docs.x402.org/core-concepts/facilitator
};
function createServer() {
const server = withX402(
new McpServer({ name: "PaidMCP", version: "1.0.0" }),
X402_CONFIG,
);
// Paid tool — $0.01 per call
server.paidTool(
"square",
"Squares a number",
0.01, // USD
{ number: z.number() },
{},
async ({ number }) => {
return { content: [{ type: "text", text: String(number ** 2) }] };
},
);
// Free tool
server.registerTool(
"echo",
{ description: "Echo a message", inputSchema: { message: z.string() } },
async ({ message }) => {
return { content: [{ type: "text", text: message }] };
},
);
return server;
}
const handler = createMcpHandler(createServer);
export default {
fetch(request, env, ctx) {
return handler(request, env, ctx);
},
};import { McpServer } from "@modelcontextprotocol/server";
import { createMcpHandler } from "agents/mcp/server";
import { withX402, type X402Config } from "agents/x402";
import { z } from "zod";
const X402_CONFIG: X402Config = {
network: "base",
recipient: "0xYourWalletAddress",
facilitator: { url: "https://x402.org/facilitator" }, // Payment facilitator URL
// To learn more about facilitators: https://docs.x402.org/core-concepts/facilitator
};
function createServer() {
const server = withX402(
new McpServer({ name: "PaidMCP", version: "1.0.0" }),
X402_CONFIG,
);
// Paid tool — $0.01 per call
server.paidTool(
"square",
"Squares a number",
0.01, // USD
{ number: z.number() },
{},
async ({ number }) => {
return { content: [{ type: "text", text: String(number ** 2) }] };
},
);
// Free tool
server.registerTool(
"echo",
{ description: "Echo a message", inputSchema: { message: z.string() } },
async ({ message }) => {
return { content: [{ type: "text", text: message }] };
},
);
return server;
}
const handler = createMcpHandler(createServer);
export default {
fetch(request, env, ctx) {
return handler(request, env, ctx);
},
} satisfies ExportedHandler;| Field | Description |
|---|---|
network |
base for production, base-sepolia for testing |
recipient |
Wallet address to receive payments |
facilitator |
Payment facilitator URL (use https://x402.org/facilitator) |
paidTool() takes the same arguments as registering a tool, plus a price:
| Parameter | Description |
|---|---|
name |
Tool name |
description |
Tool description |
price |
Price per call in USD, for example 0.01 |
inputSchema |
Zod shape for the tool's input |
annotations |
MCP tool annotations |
handler |
Async function that runs after payment succeeds |
When a client calls a paid tool without payment, the server returns 402 with payment requirements. The client pays via x402, retries with payment proof, and receives the result.
Use base-sepolia and get test USDC from the Circle faucet ↗︎.
- Pay from Agents SDK — Build clients that pay for tools
- Charge for HTTP content — Gate HTTP endpoints
- MCP server guide — Build your first MCP server