@zeam-labs/x402-mcp-bridge
OfficialProvides an ethers 6+ provider (PrismProvider) that connects to the x402 bridge, enabling paid RPC calls, line-based time purchases, and channel management through ethers-compatible clients.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@@zeam-labs/x402-mcp-bridgeget the current BTC price from the paid crypto oracle"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
ZEAM :: Pass client
@zeampass/client, version 4.0.0. Source: https://github.com/zeam-labs/x402-mcp-bridge
The Pass client is for an agent that carries its own wallet: it stands in front of a paid MCP server or URL and pays from that wallet. To fund an agent without installing anything, give it a pass, a funded link: https://zeampass.com/pass
ZEAM :: Pass is the buyer side: a pass, or this client. Over MCP the client pays x402: per call, or it buys time and
rides a line on a ZEAM :: Bridge seller. Over HTTP, paid_fetch pays a URL's 402 as an x402 exact payment, as an
MPP charge, or from an x402 batch-settlement channel. It works with ZEAM Prism, with any ZEAM :: Bridge seller over MCP and over HTTP, with any x402 seller and, over HTTP, with a URL that takes an MPP evm charge.
With a session escrow pinned in PASS_SESSION_ESCROW it also pays by MPP session, over MCP and over HTTP: see
Paying by session.
Formerly x402-mcp-bridge
Up to 3.2.2 this was @zeam-labs/x402-mcp-bridge. It is now part of ZEAM :: Pass and pays MPP charges as well as
x402. What you already run keeps working:
@zeam-labs/x402-mcp-bridge3.2.2 and earlier stay on npm and run as before; new versions are@zeampass/client;the command
x402-mcp-bridgeis installed besidezeam-pass;every
X402_…setting is read when itsPASS_…name is not set. With both set and different,PASS_…wins and the Pass client says so once on stderr;the tool name
x402_fetchis answered aspaid_fetch. Onlypaid_fetchis listed;the state directory is still
~/.x402-mcp-bridge, so a channel you funded is still found;the error code
x402_bridge_spend_cap_reachedis unchanged.
Related MCP server: x402 MCP Proxy
Run it
--help and --version print and exit; neither contacts a server.
It needs Node.js 20 or later. Export your key as PASS_PRIVATE_KEY. It signs locally and is never sent.
npx -y @zeampass/client --tools
npx -y @zeampass/client --call call_rpc \
'{"chain":"base","method":"eth_blockNumber","params":[]}'
PASS_MCP_URL=https://seller.example/agents/mcp \
npx -y @zeampass/client --call add '{"a":1,"b":2}'--times N repeats a --call in one process. With no arguments the Pass client is an MCP stdio server:
{
"mcpServers": {
"prism": {
"command": "npx",
"args": ["-y", "@zeampass/client@4.0.0"],
"env": { "PASS_PRIVATE_KEY": "0x..." }
}
}
}Without a key it serves tools/list and the free tools; a paid call returns the seller's terms. --tools and
--call do the same: a free tool runs, and a paid one prints the seller's terms and exits 1. --refund and
paid_fetch need the key. A key that is set and malformed is reported as that, and --call stops.
The seller's instructions reach your MCP client, under a note that the Pass client is paying.
Results pass through whole: content, structuredContent, isError and _meta.
Paying per call
The Pass client reads the terms once from
/.well-known/x402, or from the seller's first 402.The first paid call deposits into a batch-settlement channel: price ×
PASS_DEPOSIT_MULTIPLIER(default 40, minimum 3), raised to the seller's floor (the 402'sdepositline, orneededMicroUSD), and no more thanPASS_MAX_SPENDleaves room for. On Prism: 250 µUSD × 40 = $0.01.Later calls sign vouchers against that deposit. No gas, no round trip to ask the price.
The deposit sits in x402's batch-settlement escrow 0x4020074e9dF2ce1deE5A9C1b5c3f541D02a10003, hardcoded in
@x402/evm. No owner, no pause, no upgrade. Only your key can withdraw it.
Line time
A ZEAM :: Bridge seller that sells time lists buy_time and line, and tags its time tools {"per":"time"}. Prism:
1 µUSD per ms. A paid call without a line costs $0.00025 and runs at most 250 ms. On a line a call costs the
milliseconds it runs; calls at once burn once.
Buy.
buy_time {"ms": N}pays for N milliseconds from the channel. Before a call the Pass client fills an empty line toPASS_LINE_AHEAD_MS(default 2000 ms): no more per purchase than the channel's collateral covers, never less than 250 ms. A seller on an older version of the plugin that sells time in blocks is asked for blocks.Open.
POST <base>/line {"op":"open","channelId"}returns a message. The Pass client signs it (EIP-191) with the payer key and posts{"op":"prove","channelId","nonce","signature"}; the answer carries the credential.Ride. Each time-tool call carries the credential in
_meta["zeam-pass/line"]; no payment per call. The answer's_meta["zeam-pass/meter"]statesmsRemaining. A call runs until the seller answers, the connection drops or the MCP client that asked cancels it, which the Pass client passes on to the seller and which stops its purchases.Stay ahead. While a call runs the line burns 1 ms per ms and the seller keeps the call going as long as the line holds time. When half of
PASS_LINE_AHEAD_MSis left (or twice the slowest purchase so far, if longer; one that carried a deposit counts only while the next will carry one) the Pass client buys again: as much as the call has run so far, at leastPASS_LINE_AHEAD_MS. The call is not run again. AtPASS_MAX_SPENDit stops buying; the call ends when the line runs out and the answer isx402_bridge_spend_cap_reached. A purchase that fails is said and tried again; the call runs on what is left.Meter. After
PASS_LINE_IDLE_MS(default 1000) with no call the Pass client sends{"op":"off"}; the next call sends{"op":"on"}.meter_offis switched on and called again;line_unknownopens a new line;out_of_time, which now means a purchase failed or came late, buys twice the time and calls again.Exit. On exit the Pass client sends
off, thenclose. Unburned time comes back with a refund.
PASS_LINE:
auto(default): per call until 2 time-tool calls arrive within 10 s (PASS_AUTO_FAST_RUN,PASS_AUTO_GAP_MS), then a line while it holds time. A call cut for running past what one call buys (out_of_time) is called again on a line. When the seller says how long the call needs (needsMs), the Pass client buys that much, plus a quarter, before it calls again.on: every time-tool call rides a line.off: per call only.
Tools priced per call never ride a line.
Refunds
npx -y @zeampass/client --refundThe Pass client posts
{channelId, issued, signature}to the refund route the seller names (its 402 or/.well-known/x402), else<base>/refund. The key signs:ZEAM Pass refund channel: <channel id, lowercase> issued: <ISO time>When the channel's fees cover the gas, the seller sends the balance and the unburned time:
returnedMicroUSD,timeReturnedMs,gasMicroUSD: 0.When they do not, the seller answers 409
refund_quotewith the exact gas. The Pass client signs a gasless USDC payment of it and posts again; one transaction returns the rest.When the gas is more than what is left:
nothing_to_returnwith the numbers.
--refund --self-send asks for a signed refund of all of it and sends it from your key, at your gas, if the key holds
ETH on Base. Otherwise it prints the transaction for any wallet to send.
No answer from the seller: initiateWithdraw, then finalizeWithdraw after the channel's withdrawDelay.
--refund also closes an MPP session channel: see Paying by session.
Paying by session
An MPP session (draft-evm-session-00, method evm) is a payment channel in an escrow contract: one deposit, then
one signed voucher per call for the running total, and what is not spent comes back when the channel closes. The
seller's relay sends the deposit from an EIP-3009 authorization the key signs, so the key needs USDC and no ETH.
It is off until you pin an escrow. No escrow is built in: the contracts are deployed on Base and are not audited.
PASS_SESSION_ESCROW: the escrow, or escrows, the Pass client may pay into. A session into any other escrow is not paid.PASS_SESSION_FACTORY: that escrow's payee factory. With it, before the deposit, the Pass client checks that the payee in the challenge is the factory's address for the seller's signer and split (receiverAuthorizerandpayToin the seller's 402) and signs nothing when it is not. Without it, or when the 402 names neither, the Pass client says the payee could not be checked, and pays.PASS_SESSION(defaultauto):autopays by session when the seller offers one into a pinned escrow: after an x402exactquote, before an MPP charge and before a newbatch-settlementchannel. Abatch-settlementchannel that still holds money is spent first; an open session channel is used before either.onpays by session first whenever one is offered.offnever does.
Over MCP, with an escrow pinned, a tool priced per call is asked without payment for its session challenge: once
when it offers none, and again each time the challenge is about to expire when it does. The answer of a free tool is
returned as it is. A tool sold by time is paid the same way when it does not ride a line: with PASS_LINE=off, and
with auto until a line holds time. A session channel opened over HTTP pays the MCP calls to the same seller.
What it signs, over MCP and in paid_fetch alike:
The deposit is price ×
PASS_DEPOSIT_MULTIPLIER, at least the seller'ssuggestedDeposit. When the next call would pass the deposit, a top-up of the same size is signed first.A voucher is for what the seller's receipts show spent plus the price of the call, and never for more than the deposit. A receipt that claims more than the key has signed is refused, and nothing more is signed on that channel.
The deposit and every top-up count toward
PASS_MAX_SPENDwhen they are signed, and one that would pass it is not signed. A call paid out of a deposit this run signed is not counted again; a call paid out of an earlier run's deposit is. Inpaid_fetch,maxAmountrefuses a deposit or top-up above it, as it refuses a price.One channel per seller, payee, token and escrow. Its record is
<state directory>/session/<channel id>.json; it holds amounts and addresses, and the signed payments the Pass client may have to send again rather than sign a second one: a deposit or top-up until the escrow shows it, the gas payment of a close, and, after--refund --exit, the withdrawal and gas payment the relay holds. Each pays only the addresses it names (the escrow, the relay's gas wallet, the key), so the file cannot send money anywhere else, but anyone who reads it can send them while they are valid: keep the state directory private. A new run resumes the channel after checking the record against the escrow. When a seller later names another escrow or payee, nothing is signed and the open channel stays where it is until you close it.
Leaving:
--refundasks the seller to close the channel: the seller is paid what was spent and the rest returns to the key in the same transaction. When the channel's fees do not cover that transaction's gas, the seller quotes it and the Pass client pays it in USDC out of what returns, under the checks in Limits. The key needs no ETH.--refund --exitleaves without the seller and without ETH, through the relay: a close request signed by the key, and, run again after the escrow's grace period (15 minutes in ZEAM's escrow), a signed withdrawal of everything the seller has not settled. These two signed calls are ZEAM's addition to the draft's escrow. The relay sends them free when the fees on what the channel has settled cover their gas. When they do not, the Pass client asks the relay its price and signs the withdrawal and a USDC payment of that price along with the request; the relay sends the request, holds the rest and sends it after the grace period. The gas comes out of what returns, the key needs no ETH, and there is nothing to run again: a later--refundshows the channel closed. The relay needs the seller's split, which a ZEAM :: Bridge seller publishes beside its session challenge and the Pass client keeps in the channel's record; for a seller that publishes none, give it asPASS_SESSION_SPLIT,{"split":{"recipients":[…],"allocations":[…],"totalAllocation":"…","distributionIncentive":0},"salt":"0x…"}. The Pass client uses it only when the 0xSplits factory gives the seller's split address for it.--refund --self-sendsends the draft's ownrequestClose, and after the grace periodwithdraw, from the key at its own gas. It needs nothing from the seller or the relay.
Gates and grants
A ZEAM :: Bridge gate admits listed keys by a zero-value payment: nothing moves. PASS_GRANT is sent as the x-grant
header on every request to the seller's own origin (the origin of PASS_MCP_URL), over MCP and HTTP, so a key
admitted by grant passes the gate. It is not sent to a relay, to a paid_fetch URL on another origin, or across a
redirect to another origin.
Any paid URL
paid_fetch is offered beside the seller's tools. It calls a URL and pays a 402 with the first of these the URL
offers:
x402
exact: one signed transfer.An MPP (
WWW-Authenticate: Payment) charge, methodevm.x402
batch-settlement: a payment channel, as in Paying per call. A ZEAM :: Bridge seller quotes this on its HTTP routes (POST <base>/v1/<tool>, and its own routes behind the paywall), with an MPP charge beside it only where the price covers the gas.
With a session escrow pinned, an MPP session the URL offers into it is paid after 1 and before 2, as Paying by
session says. The result carries protocol: "mpp", intent: "session", channelId, charged, the receipt,
payeeVerified and, when one was signed, deposit or topUp.
npx -y @zeampass/client --call paid_fetch \
'{"url":"https://api.example.com/v1/quote","body":{"symbol":"ETH"}}'pay: falsereturns the terms without paying.maxAmount(base units) refuses a larger quote before signing.USDC counts toward
PASS_MAX_SPEND. Another asset is paid only withmaxAmount.A zero-value gate: signed, admitted,
paid: false.An MPP charge is paid when it is method
evm, intentcharge, on the Pass client's network, taking an EIP-3009authorization: one signed USDC transfer, no channel. The result carriesprotocol: "mpp"and thereceipt.A signed MPP charge counts toward
PASS_MAX_SPENDwhen it is sent, receipt or not: its seller can collect it until the challenge expires. With no receipt the result sayssigned: trueandpaid: false. A signed x402exacttransfer counts the same way; a URL that answers it with an error getssigned: trueandpaid: false.Other MPP methods (
tempo,stripe) are listed undermppin the terms and not paid.A
batch-settlementpayment: the first call to a seller signs a deposit, price ×PASS_DEPOSIT_MULTIPLIER, at least the floor its 402 names; later calls sign vouchers against it. The result carriesscheme,channelId,chargedand, when one was signed,deposit.A deposit counts toward
PASS_MAX_SPENDwhen it is signed, andmaxAmountrefuses a deposit above it as it refuses a price. Refused, nothing is signed andneededis the amount that would be. A call paid out of a deposit this run signed is not counted again; a call paid out of an earlier deposit is.Channel state is kept per host:
~/.x402-mcp-bridge/<host>/<address>, or<PASS_STATE_DIR>/hosts/<host>/<address>whenPASS_STATE_DIRis set. A URL on the host ofPASS_MCP_URLpays from the channel the MCP tools pay from. A record is named by its channel, which the receiver in the terms fixes: other terms are another channel, and a seller's answer updates only the channel its own terms name.To take back what such a channel has not spent:
PASS_MCP_URL=https://<host>with--refund, and withPASS_STATE_DIRset, that host's directory asPASS_STATE_DIR. The Pass client prints the settings when it signs a deposit.A 402 after a payment:
funding_requires_open_feedeposits the floor it names; a count the seller proves with this key's own voucher resyncs the channel;payment_invaliddrops the local record and resyncs from the chain. The call is then paid again, three payments at most, every deposit among them insidemaxAmountandPASS_MAX_SPEND.A seller that takes the voucher and fails: its error comes back,
paid: false, nothing counted. An answer with noPAYMENT-RESPONSE:signed: true,paid: false, and the price counts towardPASS_MAX_SPEND.
Chain clients
import { createPublicClient } from 'viem'
import { base } from 'viem/chains'
import { prism } from '@zeampass/client/viem'
const client = createPublicClient({
chain: base,
transport: prism({ key: process.env.PASS_PRIVATE_KEY }),
})
await client.getBlockNumber()The ethers provider needs ethers 6 or later installed beside the Pass client (npm install ethers).
import { PrismProvider } from '@zeampass/client/ethers'
const provider = new PrismProvider({ key: process.env.PASS_PRIVATE_KEY })The first request pays per call at
/rpc/base(or/rpc/eth,chain: 'eth') and funds the channel: 40 × the price, at least the seller's floor.Then it opens a line, buys
aheadMs(2000) of time, and sendsx-line. While a request runs it buys more before the line runs out, as above.maxMicroUSD(defaultPASS_MAX_SPEND) bounds everything one request signs for: a deposit or top-up, the call, the line time bought before and during it. Each counts when it is signed; a call or line time paid out of a deposit the same request signed is not counted again, and one paid out of an earlier request's deposit is. A deposit that would pass it is made smaller to fit, down to what the call and the seller's floor need. Below that nothing is signed and the request is refused with an error whosecodeisx402_bridge_spend_cap_reachedand whoseneededis the amount. During a call, purchases stop at it and the call runs on the time left.refund()holds its gas payment to it.The meter goes off after
idleMs(1000) idle; the line is let go afterdropAfterMs(10000).state(),close(),refund(). Callclose()orrefund()before exit.
Options: url, chain, network, stateDir, depositMultiplier, asset, salt, rpcUrl, grant, relayUrl,
maxMicroUSD, aheadMs, idleMs, dropAfterMs, log. The PASS_* variables are the defaults; the state directory is shared with the Pass
client.
Configuration
PASS_PRIVATE_KEY(no default): funds the channel and signs.PASS_MCP_URL(defaulthttps://mcp.zeamprism.com/mcp): any x402 MCP endpoint.PASS_LINE(defaultauto):auto,on,off.PASS_LINE_AHEAD_MS(default2000): line time kept ahead of a call; the least bought perbuy_time.PASS_LINE_IDLE_MS(default1000): meter off after this idle.PASS_MAX_SPEND(default10000000, $10): ceiling on what this run pays, µUSD;0removes it. Every deposit and top-up counts when it is signed, x402 or session, for an MCP tool or inpaid_fetch; so does every signed transfer: anexactpayment, an MPP charge, a gas payment. A call paid out of a deposit this run signed is not counted again. What the channel was charged before this run is not counted. For an MCP tool an x402 deposit that would pass the cap is made smaller to fit, down to what the call and the seller's floor need; below that nothing is signed.PASS_DEPOSIT_MULTIPLIER(default40): deposit = price × this, at least the seller's floor; minimum 3.PASS_GRANT(no default):x-granton every request to the seller's own origin.PASS_RPC_URL(default the chain's public RPC): your node for chain reads.PASS_STATE_DIR(default~/.x402-mcp-bridge/<host>/<address>): channel state; keep it.PASS_SALT(default the scheme's): a distinct channel.PASS_ASSET(default first quoted): address or symbol.PASS_NETWORK(defaulteip155:8453): CAIP-2.PASS_SESSION(defaultauto):auto,on,off. Nothing is paid by session until an escrow is pinned.PASS_SESSION_ESCROW(no default): the MPP session escrow addresses the Pass client may pay into.PASS_SESSION_FACTORY(no default): the payee factory of that escrow, to check a seller's payee.PASS_SESSION_SPLIT(no default): a seller's split and its salt, for--refund --exit.
Every request to a seller, a relay or a paid_fetch URL is sent with User-Agent: zeam-pass-client/<version> node,
so the other side can see it is the Pass client and which version. A User-Agent you put in paid_fetch's
headers is sent instead. Nothing else about you is added: no address, no host name.
USDT, DAI and WETH settle through Permit2: approve 0x000000000022D473030F116dDEE9F6B43aC78BA3 once. USDC needs no
approval.
Limits
It exits when stdin closes, and lets its line go.
It stops at
PASS_MAX_SPEND: further calls returnx402_bridge_spend_cap_reached.On
--refund, when the seller asks for the refund's gas in USDC, it signs only a payment to the relay's own gas wallet, in USDC on its own chain, for the amount quoted, no more than twice what the relay prices that gas at, less than the refund and withinPASS_MAX_SPEND. Otherwise it signs nothing and says why. The relay is ZEAM's (https://api.zeampass.com/relay);PASS_RELAY_URLnames another. The gas of a session channel's close is checked the same way. For--refund --exitthe price is the relay's own, and the payment is signed only when it is less than what is left in the channel and withinPASS_MAX_SPEND; it cannot be taken before the grace period ends. Signed with the close request, it is valid from 30 s after the grace period the chain gives at that moment, for 15 minutes; the answer says from when (gasPaymentValidFrom), and says so if the request landed so late that this falls inside the grace period. Signed after the request is on chain, it is valid from the end of that request's grace period. A close's gas payment is signed only when it is valid at once and for no more than 10 minutes, is less than what the escrow shows would return, and the relay does not say the channel's fees cover the gas. Each payment is kept in the channel's record, and no other is signed for that channel while one is unexpired and unused: the same one is sent again, or--refundsays until when to wait (gas_payment_pending).On
--refund --self-sendit sends only the escrow's signed refund of this channel:refundWithSignature, alone or with its claim in the escrow'smulticall. Any other transaction a seller hands back is not sent; the answer issigned_refund_refusedand says why.initiateWithdrawneeds nothing from the seller.The ETH gas that
--self-sendpays is not counted towardPASS_MAX_SPEND. The Pass client knows its cost in ETH before sending but holds no ETH price of its own, and a price asked of the seller or the relay would make the exit depend on them. It sends only when the key holds 1.5 × the estimate, and the answer states what was paid (gasWei).Lost state costs one probe to resync, then one deposit.
Verify before you run it
The versions are pinned exactly.
npm view @zeampass/client@4.0.0 version dist.integrity
npm pack @zeampass/client@4.0.0
less package/index.mjsApache-2.0. Patent pending.
This server cannot be deployed
Maintenance
Related MCP Connectors
Monetize any MCP server: x402 paywall, pay-per-call billing in USDC on Base, agent marketplace.
Pay-per-action access to APIs and MCP tools over Lightning L402 and Base USDC x402.
Paid MCP tools behind one endpoint. Agents pay per call in USDC on Base via x402.
Billing proxy for MCP servers. Adds Stripe and x402 crypto payments without writing billing code.
Related MCP Servers
- FlicenseNot gradedqualityFmaintenanceEnables micropayments for MCP tool invocations using the X402 payment protocol, allowing servers to charge per tool usage in USDC and clients to automatically handle payments.27 npm4-
- AlicenseNot gradedqualityDmaintenanceA local MCP proxy that connects to remote MCP servers and automatically handles x402 payments, signing USDC on-chain when a tool returns HTTP 402.16 npm1MIT
- AlicenseAqualityFmaintenanceEnables MCP clients to access all endpoints of an x402 gateway by paying real-time microtransactions (USDC on Base) per API call, with automatic tool discovery and spend guardrails.2357 npmMIT
- AlicenseNot gradedqualityFmaintenanceAn MCP server whose tool invocations are metered and charged over x402, plus a paying-proxy reference client that lets any standard MCP client use the paid tool without knowing x402 exists.MIT