products / pay-sdk
The open-source payment layer for tools: price any MCP tool or HTTP endpoint, and give your agent a hard budget to buy with. Self-hosts with no account, settles straight to your wallet, and you keep 100% of what you charge.
import { createPaywall, l402Rail } from "@bolthub/pay";
// A rail needs a signing secret and something that makes invoices —// your wallet (NWC / LND / phoenixd / LNbits) or a bolthub facilitator.const pay = createPaywall({ rails: [l402Rail({ secret: process.env.PAY_SECRET!, invoiceProvider })],});
// Charge 2000 sats for one MCP tool call:pay.tool(server, "get_satellite_image", "Recent satellite imagery", schema, { price: { amount: 2000 } }, async (args) => ({ content: [{ type: "text", text: await fetchImage(args) }] }),);Sell with paywall() and rails; buy with ToolClient and payers. The challenge one side emits is exactly what the other side answers.
Nothing between your agent and its tools but code you can read. Wallets and heavier adapters live in isolated subpaths you opt into.
Lightning (L402) is live today; x402 stablecoin adapters ship in the package. Price a tool once and swap or add rails without touching the handler.
A paid tool answers an unpaid call with a payment_required challenge listing the rails it accepts. The buyer pays one offer, retries with the proof, and the tool runs. Money moves buyer to seller on the rail itself; the SDK only orchestrates the loop, so there is no middleman to trust with funds.
Works with any MCP server or HTTP handler you already have. Want managed metering, replay protection, and analytics behind the same code? Point the rail at the hosted facilitator later; the handler doesn’t change.
bun add @bolthub/payThe buyer side is ToolClient: per-asset spending ceilings enforced before any payment leaves, free tools passed through untouched.
import { ToolClient, l402Payer } from "@bolthub/pay";
// Hard ceilings, per asset. Zero configured = the agent can't spend at all.const client = new ToolClient({ payers: [l402Payer({ wallet })], maxTotal: { sat: 10_000 }, maxPerCall: { sat: 500 },});
// Free tools pass through untouched; paid ones are paid and retried.const result = await client.callTool(mcp, "get_satellite_image", { lat: 47.4979, lon: 19.0402,});Real-world use
You maintain an MCP server with one expensive tool, say satellite imagery that costs you real money per fetch. Wrap that one tool at 2,000 sats, leave the rest free, and publish the server as usual. Agents with a budget call it and pay per use; agents without one get a clean challenge instead of a bill you have to chase. No API keys to issue, no subscriptions to support, no card processor that won’t touch sub-cent amounts.
start selling
Self-host the SDK free, or start on the hosted platform: 1-month free trial, usage-based billing after that.