跳转到内容
本站为社区维护的非官方中文翻译,与 Cloudflare, Inc. 无关联。本站不提供账户登录,请勿在任何非官方站点输入您的 Cloudflare 账户信息。官方文档:developers.cloudflare.com

使用 MPP 收款

最后更新 查看 MarkdownAgent 设置

使用 Cloudflare Workers 接受机器支付协议(MPP)付款。根据要保护的服务选择集成方式:

  • mpp-proxy ↗ — 无需修改源站代码即可对 HTTP 内容收费。参阅为 HTTP 内容收费。
  • Worker 路由 — 向 Worker 应用添加 mppx 支付中间件。
  • MCP tool — 在 MCP tool 返回结果前要求完成支付。

前提条件

创建 Cloudflare 账户。你还需要支付收款方和 MPP 密钥。

示例使用 testnet 上的稳定币支付方式。其他方式请参阅 MPP 支付方式 ↗。

为 Worker 路由收费

当你控制 Worker 应用时,添加 mppx 中间件:

  1. 在 Worker 项目中安装 Hono 和 mppx:

    npm i hono mppx
  2. 将 MPP 签名密钥存储为 Worker 密钥:

    npx wrangler secret put MPP_SECRET_KEY
  3. 在付费路由处理函数之前添加支付中间件:

    src/index.jsjs
    import { env } from "cloudflare:workers";
    import { Hono } from "hono";
    import { Mppx, tempo } from "mppx/hono";
    
    const workerEnv = env;
    const app = new Hono();
    const mppx = Mppx.create({
    	methods: [tempo.charge({ testnet: true })],
    	secretKey: workerEnv.MPP_SECRET_KEY,
    });
    
    app.get(
    	"/premium",
    	mppx.charge({
    		amount: "0.01",
    		currency: "0x20c0000000000000000000000000000000000000",
    		description: "Premium API access",
    		recipient: "<YOUR_WALLET_ADDRESS>",
    	}),
    	(c) => c.json({ access: "paid" }),
    );
    
    export default app;
    src/index.tsts
    import { env } from "cloudflare:workers";
    import { Hono } from "hono";
    import { Mppx, tempo } from "mppx/hono";
    
    const workerEnv = env as Env & { MPP_SECRET_KEY: string };
    const app = new Hono();
    const mppx = Mppx.create({
      methods: [tempo.charge({ testnet: true })],
      secretKey: workerEnv.MPP_SECRET_KEY,
    });
    
    app.get(
      "/premium",
      mppx.charge({
        amount: "0.01",
        currency: "0x20c0000000000000000000000000000000000000",
        description: "Premium API access",
        recipient: "<YOUR_WALLET_ADDRESS>",
      }),
      (c) => c.json({ access: "paid" }),
    );
    
    export default app;
  4. 部署 Worker:

    npx wrangler deploy
  5. 在不携带支付的情况下请求付费路由:

    curl -i https://<YOUR_WORKER>.workers.dev/premium

    Worker 返回 402 Payment Required 和 WWW-Authenticate: Payment 标头。完成支付后重试会到达处理函数,并返回 Payment-Receipt 标头。

为 MCP tool 收费

为 Workers 上 MCP 服务器的工具调用收费。mppx 会通过 MCP SDK v1 请求上下文 (Transport.mcpSdk()) 读取支付凭据,因此此服务器使用 SDK v1 McpServer 和 createLegacyMcpHandler。此服务器仍为无状态:Worker 会为每个请求创建新的服务器,无需 Durable Object。

  1. 在 Agents 项目中安装所需软件包:

    npm i agents mppx @modelcontextprotocol/sdk zod
  2. 配置 Worker:

    {
      "$schema": "./node_modules/wrangler/config-schema.json",
      "name": "mpp-server",
      "main": "src/index.ts",
      "upload_source_maps": true,
      // Set this to today's date
      "compatibility_date": "2026-11-14",
      "compatibility_flags": [
        "nodejs_compat"
      ]
    }
    name = "mpp-server"
    main = "src/index.ts"
    upload_source_maps = true
    # Set this to today's date
    compatibility_date = "2026-11-14"
    compatibility_flags = ["nodejs_compat"]
  3. 将 MPP_SECRET_KEY 存储为 Worker 密钥:

    npx wrangler secret put MPP_SECRET_KEY
  4. 在返回 tool 结果前检查支付:

    src/index.jsjs
    import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
    import { createLegacyMcpHandler } from "agents/mcp";
    import { Mppx, tempo, Transport } from "mppx/server";
    import { z } from "zod";
    
    function createServer(env) {
    	const server = new McpServer({ name: "paid-search", version: "1.0.0" });
    	const mppx = Mppx.create({
    		methods: [tempo.charge({ testnet: true })],
    		secretKey: env.MPP_SECRET_KEY,
    		transport: Transport.mcpSdk(),
    	});
    
    	server.registerTool(
    		"premium_search",
    		{
    			description: "Search premium content",
    			inputSchema: { query: z.string() },
    		},
    		async ({ query }, extra) => {
    			const payment = await mppx.charge({
    				amount: "0.01",
    				currency: "0x20c0000000000000000000000000000000000000",
    				description: "Premium search",
    				recipient: "<YOUR_WALLET_ADDRESS>",
    			})(extra);
    
    			if (payment.status === 402) throw payment.challenge;
    
    			return payment.withReceipt({
    				content: [{ type: "text", text: `Results for: ${query}` }],
    			});
    		},
    	);
    
    	return server;
    }
    
    export default {
    	fetch(request, env, ctx) {
    		return createLegacyMcpHandler(createServer(env))(request, env, ctx);
    	},
    };
    src/index.tsts
    import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
    import { createLegacyMcpHandler } from "agents/mcp";
    import { Mppx, tempo, Transport } from "mppx/server";
    import { z } from "zod";
    
    type PaymentEnv = Env & { MPP_SECRET_KEY: string };
    
    function createServer(env: PaymentEnv) {
      const server = new McpServer({ name: "paid-search", version: "1.0.0" });
      const mppx = Mppx.create({
        methods: [tempo.charge({ testnet: true })],
        secretKey: env.MPP_SECRET_KEY,
        transport: Transport.mcpSdk(),
      });
    
      server.registerTool(
        "premium_search",
        {
          description: "Search premium content",
          inputSchema: { query: z.string() },
        },
        async ({ query }, extra) => {
          const payment = await mppx.charge({
            amount: "0.01",
            currency: "0x20c0000000000000000000000000000000000000",
            description: "Premium search",
            recipient: "<YOUR_WALLET_ADDRESS>",
          })(extra);
    
          if (payment.status === 402) throw payment.challenge;
    
          return payment.withReceipt({
            content: [{ type: "text", text: `Results for: ${query}` }],
          });
        },
      );
    
      return server;
    }
    
    export default {
      fetch(request, env, ctx) {
        return createLegacyMcpHandler(createServer(env))(request, env, ctx);
      },
    } satisfies ExportedHandler<PaymentEnv>;
  5. 部署 Worker:

    npx wrangler deploy

    未付费的 premium_search 调用会返回 MPP Challenge。完成支付后重试会返回 tool 结果,并在 _meta 中附带 MPP Receipt。

要从 Cloudflare Agent 测试这两种支付流程,请参阅通过 Agents SDK 付款。生产环境计费模式请参阅 MPP 支付意图 ↗。

这篇文档对您有帮助吗?