使用 Cloudflare Agents SDK 向 MPP 服务付款。mppx SDK 负责处理 HTTP 请求和模型上下文协议(MCP)工具调用的支付重试。
创建 Cloudflare Agents 项目。为服务接受的支付方式对应的账户充值。
-
安装 Agents SDK、
mppx和viem:npm i agents mppx viemyarn add agents mppx viempnpm add agents mppx viembun add agents mppx viem -
将支付私钥存储为 Worker 密钥:
npx wrangler secret put MPP_PRIVATE_KEYyarn wrangler secret put MPP_PRIVATE_KEYpnpm wrangler secret put MPP_PRIVATE_KEY -
创建一次支付方式:
src/payments.jsjs import { tempo } from "mppx/client"; import { privateKeyToAccount } from "viem/accounts"; export function createPaymentMethods(privateKey) { const account = privateKeyToAccount(privateKey); return [tempo.charge({ account })]; }src/payments.tsts import { tempo } from "mppx/client"; import { privateKeyToAccount } from "viem/accounts"; export function createPaymentMethods(privateKey: string) { const account = privateKeyToAccount(privateKey as `0x${string}`); return [tempo.charge({ account })] as const; }
在 onStart() 中创建支持支付的客户端。将自动付款限制为受信任的源站:
import { Agent } from "agents";
import { Mppx } from "mppx/client";
import { createPaymentMethods } from "./payments";
export class BuyerAgent extends Agent {
methods;
payments;
async onStart() {
this.methods = createPaymentMethods(this.env.MPP_PRIVATE_KEY);
this.payments = Mppx.create({
acceptPaymentPolicy: { origins: ["https://api.example.com"] },
methods: this.methods,
polyfill: false,
});
}
async buyReport() {
const response = await this.payments.fetch(
"https://api.example.com/reports/latest",
);
if (!response.ok) throw new Error(`Request failed: ${response.status}`);
return response.json();
}
}import { Agent } from "agents";
import { Mppx } from "mppx/client";
import { createPaymentMethods } from "./payments";
type PaymentEnv = Env & { MPP_PRIVATE_KEY: string };
export class BuyerAgent extends Agent<PaymentEnv> {
methods!: ReturnType<typeof createPaymentMethods>;
payments!: ReturnType<typeof Mppx.create>;
async onStart() {
this.methods = createPaymentMethods(this.env.MPP_PRIVATE_KEY);
this.payments = Mppx.create({
acceptPaymentPolicy: { origins: ["https://api.example.com"] },
methods: this.methods,
polyfill: false,
});
}
async buyReport() {
const response = await this.payments.fetch(
"https://api.example.com/reports/latest",
);
if (!response.ok) throw new Error(`Request failed: ${response.status}`);
return response.json();
}
}免费端点的请求会直接通过。付费端点会触发支付重试,并返回 Payment-Receipt 标头。
使用 addMcpServer() 连接 Agent。等待连接完成后再包装其客户端:
import { Agent } from "agents";
import { McpClient } from "mppx/mcp/client";
import { createPaymentMethods } from "./payments";
export class BuyerAgent extends Agent {
methods;
async onStart() {
this.methods = createPaymentMethods(this.env.MPP_PRIVATE_KEY);
}
async paidSearch() {
const connection = await this.addMcpServer(
"premium-search",
"https://mcp.example.com/mcp",
);
if (connection.state === "authenticating") {
return { authUrl: connection.authUrl };
}
await this.mcp.waitForConnections();
const server = this.getMcpServers().servers[connection.id];
const mcpConnection = this.mcp.mcpConnections[connection.id];
if (server?.state !== "ready" || !mcpConnection) {
throw new Error("MCP server is not ready.");
}
const client = McpClient.wrap(mcpConnection.client, {
methods: this.methods,
});
const result = await client.callTool({
name: "premium_search",
arguments: { query: "Cloudflare Agents" },
});
return { content: result.content, receipt: result.receipt };
}
}import { Agent } from "agents";
import { McpClient } from "mppx/mcp/client";
import { createPaymentMethods } from "./payments";
type PaymentEnv = Env & { MPP_PRIVATE_KEY: string };
export class BuyerAgent extends Agent<PaymentEnv> {
methods!: ReturnType<typeof createPaymentMethods>;
async onStart() {
this.methods = createPaymentMethods(this.env.MPP_PRIVATE_KEY);
}
async paidSearch() {
const connection = await this.addMcpServer(
"premium-search",
"https://mcp.example.com/mcp",
);
if (connection.state === "authenticating") {
return { authUrl: connection.authUrl };
}
await this.mcp.waitForConnections();
const server = this.getMcpServers().servers[connection.id];
const mcpConnection = this.mcp.mcpConnections[connection.id];
if (server?.state !== "ready" || !mcpConnection) {
throw new Error("MCP server is not ready.");
}
const client = McpClient.wrap(mcpConnection.client, {
methods: this.methods,
});
const result = await client.callTool({
name: "premium_search",
arguments: { query: "Cloudflare Agents" },
});
return { content: result.content, receipt: result.receipt };
}
}如果 paidSearch() 返回 authUrl,将用户引导至该 URL,并在授权后重试。
包装器携带 MPP 凭证重试付费工具调用。结果通过 result.receipt 包含 MPP 收据。
默认情况下,两个客户端都会自动支付兼容的质询。付款需要审批时,HTTP 使用 onChallenge,MCP 使用 onPaymentRequired。质询金额使用整数形式的基础单位,而非用于显示的小数值。
mppx HTTP 客户端也能识别 x402 质询。在 MPP 支付方式之外配置兼容 x402 的 EVM 支付方式即可,无需修改服务。有关配置,请参阅将 MPP 与 x402 配合使用 ↗。
要接受付款,请参阅使用 MPP 收款。有关 MCP 连接选项,请参阅 MCP 客户端 API。