diff --git a/src/pages/partner-sdks/cloudflare-agents.mdx b/src/pages/partner-sdks/cloudflare-agents.mdx new file mode 100644 index 00000000..86eef39b --- /dev/null +++ b/src/pages/partner-sdks/cloudflare-agents.mdx @@ -0,0 +1,99 @@ +--- +description: "Use mppx to let a Cloudflare Agent pay for MPP-enabled MCP tools." +imageDescription: "Connect Cloudflare Agents to paid MPP MCP tools" +--- + +# Cloudflare Agents [Pay for MCP tools from your agent] + +Use `withMppClient` to let a [Cloudflare Agent](https://developers.cloudflare.com/agents/) call free and MPP-protected MCP tools through the same MCP client. + +Free tools pass through normally. Paid tools can return an MPP Challenge; the wrapped client creates an MPP Credential, retries the tool call, and returns the successful MCP result. The Agent does not need to know ahead of time whether a tool is free or paid. + +## Install + +```bash [terminal] +$ npm install agents mppx viem accounts +``` + +Use Tempo Accounts access keys for agent payments. `mppx` also accepts any viem account, which is useful for simpler server-wallet setups. + +## Use `withMppClient` + +Bootstrap an Agent, connect an MCP server, create an Accounts provider, then wrap the connected MCP client. + +```ts [src/index.ts] +import { Agent } from 'agents' +import { tempo } from 'mppx/client' +import { withMppClient } from 'mppx/mcp-sdk/client' +import { getAccountsProvider } from './accounts' + +type Env = { + MCP_SERVER_URL: string +} + +export class MyAgent extends Agent { + private mppClient!: withMppClient.McpClient + + async onStart() { + const { id } = await this.mcp.connect(this.env.MCP_SERVER_URL) + const provider = await getAccountsProvider(this.env) + + this.mppClient = withMppClient(this.mcp.mcpConnections[id].client, { + methods: [tempo({ provider })], + }) + } + + async onToolCall(toolName: string, toolArgs: unknown) { + return await this.mppClient.callTool({ + name: toolName, + arguments: toolArgs, + }) + } +} +``` + +The wrapper mutates the MCP client in place, so Cloudflare tool surfaces created after wrapping use the same payment-aware client, including `this.mcp.getAITools(...)` and `this.mcp.callTool(...)`. Cloudflare documents these methods in the [MCP client API](https://developers.cloudflare.com/agents/model-context-protocol/apis/client-api/). + +Paid calls expose `result.receipt` when the MCP server returns an MPP Receipt. Free calls use the same client and usually have no receipt. + +## Accounts access keys + +`getAccountsProvider(...)` returns a connected Accounts SDK `Provider` with an authorized access key. Provision or renew that key before tool calls, persist Accounts storage with KV, Durable Objects, R2, or your own storage adapter, and scope the key to the chains, tokens, and spend limits your agent needs. + +```ts +const provider = await getAccountsProvider(env) + +const client = withMppClient(mcpClient, { + methods: [tempo({ provider })], +}) +``` + +Access keys are chain-scoped; the authorized chain must match the chain ID in the MPP Challenge. `tempo({ provider })` intentionally uses `provider.getAccount()` internally so Accounts can route transactions through access keys. Do not pass `provider.getAccount({ signable: true })` to `mppx` unless you explicitly want to bypass Accounts transaction routing. + +For access-key policy details, see the Tempo Accounts [Spend Permissions guide](https://accounts.tempo.xyz/docs/guides/spend-permissions) and [`wallet_authorizeAccessKey`](https://accounts.tempo.xyz/docs/rpc/wallet_authorizeAccessKey). + +## Viem account fallback + +If you are not using Accounts yet, store a server-wallet private key as a Worker secret and pass a viem account directly. + +```bash [terminal] +$ npx wrangler secret put MPP_PRIVATE_KEY +``` + +```ts +import { tempo } from 'mppx/client' +import { privateKeyToAccount } from 'viem/accounts' + +const account = privateKeyToAccount(env.MPP_PRIVATE_KEY as `0x${string}`) + +const client = withMppClient(mcpClient, { + methods: [tempo({ account })], +}) +``` + +## Related + +- [Cloudflare MCP client API](https://developers.cloudflare.com/agents/model-context-protocol/apis/client-api/) +- [Cloudflare MPP payment overview](https://developers.cloudflare.com/agents/tools/payments/mpp/) +- [Charge for HTTP content with MPP](https://developers.cloudflare.com/agents/tools/payments/mpp-charge-for-http-content/) +- [Use with agents](/quickstart/agent) diff --git a/src/pages/quickstart/agent.mdx b/src/pages/quickstart/agent.mdx index b82dd650..6c2893cc 100644 --- a/src/pages/quickstart/agent.mdx +++ b/src/pages/quickstart/agent.mdx @@ -9,6 +9,8 @@ import { Badge, Card, Cards, Tab, Tabs } from 'vocs' Agents can automatically interact with MPP-enabled services, paying for API calls without human intervention. Learn more about [agentic payments](/use-cases/agentic-payments) or get started below. +If you're building an agent with a partner SDK, see [Cloudflare Agents](/partner-sdks/cloudflare-agents) for a framework-specific integration. + | Tool | Best for | Setup | |------|----------|-------| | [Tempo Wallet](#tempo-wallet) | MPP services with spend controls and service discovery | `tempo wallet login` | @@ -223,4 +225,10 @@ $ mppx https://mpp.dev/api/ping/paid title="Wallets" to="/tools/wallet" /> + diff --git a/vocs.config.ts b/vocs.config.ts index 03e702d8..6aefaccc 100644 --- a/vocs.config.ts +++ b/vocs.config.ts @@ -289,6 +289,15 @@ export default defineConfig({ { text: "Use with your app", link: "/quickstart/client" }, ], }, + { + text: "Use with partner SDKs", + items: [ + { + text: "Cloudflare Agents", + link: "/partner-sdks/cloudflare-agents", + }, + ], + }, { text: "Guides", items: [