@meshpay/adapters
v0.3.0
Published
MeshPay adapters for Vercel AI SDK, Mastra, and OpenAI Agents SDK
Readme
@meshpay/adapters
Framework adapters for MeshPay — wrap any AI tool with an x402 payment gate. Supports Vercel AI SDK, Mastra, and OpenAI Agents SDK.
Install
pnpm add @meshpay/adapters
# or
npm install @meshpay/adaptersPeer dependencies (install the ones you need):
pnpm add ai zod # for Vercel AI SDK adapterSetup
Create a MeshpayClient once at startup and pass it to each paidTool call.
import { meshpay } from '@meshpay/adapters'
import { createSessionWallet } from '@meshpay/wallet'
import { X402Facilitator } from '@meshpay/protocols'
const client = meshpay()
.withWallet(createSessionWallet({
privateKey: process.env.AGENT_PRIVATE_KEY,
chainId: 'eip155:8453',
caps: { perCall: 0.10, perDay: 5.00 },
}))
.withFacilitator(new X402Facilitator({ apiKey: process.env.COINBASE_CDP_API_KEY }))Required env var:
MESHPAY_AP2_KEY=<32-byte hex>Generate one:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"Vercel AI SDK
import { meshpay } from '@meshpay/adapters'
import { paidTool } from '@meshpay/adapters/vercel'
import { generateText } from 'ai'
import { openai } from '@ai-sdk/openai'
import { z } from 'zod'
const client = meshpay()
.withWallet(createSessionWallet({ ... }))
.withFacilitator(new X402Facilitator({ ... }))
const search = paidTool({
name: 'search',
description: 'Search the web for current information',
parameters: z.object({ query: z.string().describe('The search query') }),
maxCostPerCall: 0.01,
maxCostPerDay: 1.00,
paymentEndpoint: 'https://api.example.com/x402/search',
handler: async ({ query }) => fetchResults(query),
}, client)
const { text } = await generateText({
model: openai('gpt-4o-mini'),
tools: { search },
prompt: 'What happened in AI this week?',
onStepFinish({ toolResults }) {
// toolResults is fully typed — PaidTool guarantees execute is non-optional
},
})paidTool from the Vercel adapter returns a PaidTool<TSchema, TOutput> — a Tool subtype with execute guaranteed non-optional. This means toolResults in onStepFinish is correctly typed by the SDK.
Mastra
import { meshpay } from '@meshpay/adapters'
import { paidTool, withPayment } from '@meshpay/adapters/mastra'
const client = meshpay()
.withWallet(createSessionWallet({ ... }))
.withFacilitator(new X402Facilitator({ ... }))
// Create a new paid tool from scratch
const browse = paidTool({
name: 'browse',
description: 'Open a browser session',
maxCostPerCall: 0.05,
maxCostPerDay: 5.00,
paymentEndpoint: 'https://api.browserbase.com/x402/session',
handler: async (input) => browserbase.createSession(input),
}, client)
// Or wrap an existing Mastra tool with a payment gate
const paidBrowse = withPayment(existingBrowseTool, {
paymentEndpoint: 'https://api.browserbase.com/x402/session',
maxCostPerCall: 0.05,
maxCostPerDay: 5.00,
}, client)OpenAI Agents SDK
import { meshpay } from '@meshpay/adapters'
import { paidTool, createPaymentHooks } from '@meshpay/adapters/openai'
import { Agent, Runner } from 'openai/agents'
const client = meshpay()
.withWallet(createSessionWallet({ ... }))
.withFacilitator(new X402Facilitator({ ... }))
const research = paidTool({
name: 'deep_research',
description: 'Run a deep research query',
maxCostPerCall: 1.00,
maxCostPerDay: 20.00,
paymentEndpoint: 'https://api.heurist.ai/x402/research',
handler: async ({ query }) => heurist.deepResearch(query),
}, client)
const agent = new Agent({
name: 'research-agent',
tools: [research],
})
// Optional: attach payment lifecycle hooks
const hooks = createPaymentHooks({
onPayment: (toolName, amountUsd, txHash) => {
console.log(`[${toolName}] paid $${amountUsd} — tx: ${txHash}`)
},
onSpendCapExceeded: (toolName, requested, cap) => {
console.warn(`[${toolName}] cap exceeded: requested $${requested}, cap $${cap}`)
},
})
await Runner.run(agent, 'Research the latest in AI agents', { hooks })Payment flow
Every paidTool call follows this sequence before the handler runs:
- Build a signed AP2 authorization request and issue a short-lived token
- Probe the
paymentEndpointfor x402 payment terms (HTTP 402 +X-PAYMENT-REQUIRED), attachingX-AP2-AUTHORIZATIONandX-AP2-AGENT-IDheaders - Check spend caps locally — throws
SpendCapErrorbefore any signing if exceeded - Sign the quote with EIP-3009 typed data via the session wallet
- Submit to the CDP facilitator for on-chain USDC settlement
- Record spend, then call the
handler
If payment fails at any step, the handler is never called.
Per-tool wallet and facilitator override
Each tool can use a different wallet or facilitator by passing them directly in the tool options:
const premiumTool = paidTool({
name: 'premium',
maxCostPerCall: 1.00,
maxCostPerDay: 50.00,
paymentEndpoint: 'https://api.example.com/x402/premium',
wallet: premiumWallet, // overrides client wallet
facilitator: customFacilitator, // overrides client facilitator
handler: async (input) => callPremiumApi(input),
}, client)API
// Client factory
import { meshpay, MeshpayClient } from '@meshpay/adapters'
// Vercel AI SDK
import { paidTool } from '@meshpay/adapters/vercel'
// Mastra
import { paidTool, withPayment } from '@meshpay/adapters/mastra'
// OpenAI Agents SDK
import { paidTool, createPaymentHooks } from '@meshpay/adapters/openai'