Skip to content

Tools reference

The PipRail MCP server advertises eight tools, built by the SDK’s paymentTools(client) and dropped straight onto the wire — the SDK descriptors carry draft-07 JSON Schema, so the server forwards them untouched. Only piprail_pay_request moves funds; piprail_register writes a listing to an external index (so it’s not flagged read-only) but moves none; the other six are read-only. Every result is emitted both as a text block and as structuredContent, so a client that ignores structured output still reads the text.

// every tool, in advertised order
"piprail_discover" · "piprail_quote_payment" · "piprail_plan_payment" ·
"piprail_pay_request" · "piprail_register" · "piprail_budget" · "piprail_guide" ·
"piprail_verify_receipt"

Each tool carries advisory MCP annotations (readOnlyHint, destructiveHint, openWorldHint, …). They are hints only — the real boundary is the spend policy, enforced before any send.

Find x402 payment-gated resources on the open indexes — a phone book of payable APIs — without paying. Use it to answer “what can I buy?”, then quote and pay a chosen one. All arguments are optional.

ArgumentTypeMeaning
querystringFree-text topic to search for.
networkstringCAIP-2 id, 'self' (your chain — default), or 'any' (all chains).
categorystringKeep only this category (strict — uncategorized results are dropped).
assetstringKeep only resources paying in this token symbol, e.g. 'USDC'.
maxPricenumberDrop results whose index-advertised price is above this number.
minReliabilitynumberDrop results below this health score (0–100); unscored results pass through.
verifiedbooleanPrefer verified listings.
sortstring'relevance' | 'reliability' | 'price' | 'uptime' | 'name'.
limitnumberMax results per index (default 20).

Returns { count, resources[] }, each resource carrying resource, name, description, source, priceUsd, category, reliabilityScore, health, verified, and the distinct networks it offers. priceUsd and maxPrice are the index’s own advertised metadata — PipRail has no price oracle, so always piprail_quote_payment the chosen resource for the live, true price before paying. It is read-only and open-world.

Price a gated URL without paying. Call it first to decide whether a resource is worth buying.

ArgumentTypeMeaning
urlstring (required)Full URL of the gated resource.

Returns the quote (gated: true plus amount, token, chain, recipient, and whether it sits within your spend policy), or { gated: false, url } when the URL needs no payment. Carries an open outputSchema so a strict client can validate structuredContent.

{ "gated": true,
"amountFormatted": "0.10", "symbol": "USDC", "asset": "0x…",
"network": "eip155:8453", "payTo": "0xYourWallet",
"withinPolicy": true }

Check whether you can pay before committing — reads your wallet balance, native gas, and recipient readiness across every rail the URL offers on your chain. Call it before piprail_pay_request so you never start a payment you can’t finish.

ArgumentTypeMeaning
urlstring (required)Full URL of the gated resource.

Returns { gated, payable, status, fundingHint, summary, best, options[] } (and session when a time policy is set). summary is one model-readable line distilling the whole plan; each options[] entry carries state, blockers, warnings, and recipientReady.

{ "gated": true, "payable": false, "status": "blocked",
"fundingHint": "Can't settle on Base: top up 0.04 USDC (to pay 0.10 USDC).",
"summary": "NOT payable: Can't settle on Base: top up 0.04 USDC (to pay 0.10 USDC).",
"best": null,
"options": [
{ "network": "eip155:8453", "symbol": "USDC", "amount": "0.10",
"state": "blocked", "blockers": ["INSUFFICIENT_TOKEN"],
"warnings": [], "recipientReady": "n/a" }
] }

The summary line comes verbatim from the SDK’s summarizePlan() — a payable plan instead reads "Payable: 0.10 USDC on eip155:8453 (gas ~0.00002 ETH). 1 other rail(s) not settleable." Gas is shown in the native coin only; there is no fiat figure.

The one tool that moves funds. It fetches the URL and makes the required payment if needed, subject to the spend policy and the approval hook. It pays whichever rail the client is configured for — PipRail’s backendless on-chain rail, or the standard exact rail when enabled. Its annotations mark it readOnlyHint: false, destructiveHint: true, idempotentHint: false.

It always hands the model a structured outcome — success or failure — never an exception. A settled fetch returns { status, ok, body, receipt, verifiableReceipt? }; anything that goes wrong (a refused payment, a server rejection, a broadcast that didn’t confirm) comes back as a structured { ok: false, … } object the agent can branch on. The two shapes are below.

ArgumentTypeMeaning
urlstring (required)Full URL to fetch.
methodstringHTTP method, default GET.
bodyobject | stringRequest body for POST/PUT. An object is JSON-serialised and sent with content-type: application/json set automatically; a string is sent verbatim with no content-type set.

On success it returns { status, ok, body, receipt, verifiableReceipt? }, where receipt is the parsed payment receipt if one settled. verifiableReceipt is present only when the gate emitted a verifiable-receipt extension — the PipRailReceipt JSON ({ piprail, receipt, resource, … }, where piprail is the literal string "1") stamped with the URL you fetched, which you keep and later re-check with piprail_verify_receipt.

{ "status": 200, "ok": true,
"body": { "...": "the resource you paid for" },
"receipt": { "transaction": "0x…", "network": "eip155:8453", "payer": "0xYourWallet" },
"verifiableReceipt": { "piprail": "1", "receipt": { "...": "" }, "resource": "https://…" } }

Every failure is structured — never a crash

Section titled “Every failure is structured — never a crash”

This tool is the single funnel where every PipRailError reaches the model as a structured object instead of a thrown error, so the agent reasons about it rather than crashing. The fields are mutually contextual — they’re populated by the kind of failure, so you’ll never see all of them on one object at once (a clean decline has no ref; a timeout has no declined):

{ "ok": false, "code": "INSUFFICIENT_FUNDS",
"reason": "", "explain": "",
"ref": "0x…", // only on PAYMENT_TIMEOUT / MAX_RETRIES_EXCEEDED — the broadcast proof
"reasonCode": "POLICY", // only on a decline
"declined": true } // only on a policy/approval refusal
FieldWhen presentMeaning
codealwaysThe stable PipRailError code — branch on this.
reasonalwaysThe error message.
explainalwaysA one-line human explanation (explainDecline).
declinedpolicy / approval refusaltrueno funds moved.
reasonCodea declineSESSION_EXPIRED, APPROVAL, OUTSIDE_WINDOW, POLICY, BUDGET — some are terminal.
refPAYMENT_TIMEOUT / MAX_RETRIES_EXCEEDEDThe on-chain proof of a broadcast-but-unconfirmed tx.

A genuine, non-SDK bug is the only thing that still surfaces as an MCP isError result.

List an x402 resource you run on the open indexes so other agents can find it. The default target is 402 Index — no auth, no signature, no payment. Moves no funds; nothing is PipRail-hosted.

ArgumentTypeMeaning
urlstring (required)Full URL of the resource to list.
namestringDisplay name (defaults to the host).
descriptionstringWhat the resource offers.
categorystringThe top findability lever — most listings have none. A real category ('ai', 'finance', …) makes a listing rank + filter.
tagsstring[]Keywords — folded into the description for search and sent as a tags field.
priceUsdnumberAdvertised price (metadata).
networkstringNetwork slug to advertise, e.g. 'base' (defaults to the paying chain) — set it when registering from a multi-chain (PIPRAIL_CHAINS) wallet.
assetstringPayment asset symbol, e.g. 'USDC' (metadata).
providerstringWho runs the resource (provider/org name).
contactEmailstringContact email for the listing (also used by the domain claim).

Returns { outcomes[] } — one { source, ok, detail, visibility, note } per index; a step the chain can’t satisfy comes back ok: false with the reason.

Read how much of your spend budget and time leash is left — per (network, asset) remaining, the session time envelope, and your spend so far. Use it in Mode A (headless) to self-check before paying, so you never discover the leash by hitting a decline. Read-only and idempotent; takes no arguments.

Returns { spent, remaining, session, report, grandTotal, counts, policy }, where report is a formatted line of the spend ledger and the last three mirror the grand-total leash:

FieldMeaning
grandTotalThe per-denomination cross-token cap — one row per capped denomination ({ denom, spentFormatted, capFormatted, remainingFormatted, fraction }), present from the start. Empty when no maxTotalPerDenom is set.
countsThe payment-count leash{ settled, lifetimeCap?, lifetimeRemaining?, windowCap?, windowSettled?, windowRemaining? }. settled is always present; the caps appear only when maxPayments / maxPaymentsPerWindow are set.
policyThe configured spend policy read back, so the model sees the leash it’s bound by (undefined when none is set).
{ "spent": "0.10", "remaining": "19.90", "report": "",
"session": { "start": "2026-06-10T00:00:00Z", "expiresAt": "2026-06-10T02:00:00Z", "secondsRemaining": 3500 },
"grandTotal": [
{ "denom": "USD", "spentFormatted": "0.10", "capFormatted": "20.00",
"remainingFormatted": "19.90", "fraction": 0.005 }
],
"counts": { "settled": 1, "lifetimeCap": 100, "lifetimeRemaining": 99 },
"policy": { "maxTotalPerDenom": { "USD": "20.00" }, "maxPayments": 100 } }

The grand total is a user-declared unit-of-account sum, not a price oracle: tokens you group as one unit (USDC/USDT/… → USD) are summed 1:1; native and unknown tokens have no denomination and are never summed. It still spans chains when the server runs in multi-chain mode, because all chains share one ledger.

Read the PipRail agent contract — the quote → plan → pay loop, how to read a refusal (and which declines are terminal), the never-re-pay rule, and Mode A vs Mode B. Read-only and idempotent; takes no arguments. Returns { guide }, the full PIPRAIL_AGENT_GUIDE string. Call it once if you’re unsure how to use these tools.

Re-verify a PipRail verifiable receipt against the chain — confirm a payment really settled (the funds provably moved to payTo for at least the stated amount) without trusting whoever handed you the receipt. Read-only and wallet-free: pass the PipRailReceipt JSON from a prior piprail_pay_request verifiableReceipt, or any third party. Read-only and idempotent.

ArgumentTypeMeaning
receiptobject (required)The PipRailReceipt JSON ({ piprail, receipt, resource, decimals? }) to re-verify.
rpcUrlstringOptional RPC URL for the receipt’s chain (required for chains outside the common presets).

Returns { ok, onChain: { payTo, asset, amount, payer }, matchesClaims, ageSeconds, error? }. ok is true when the chain confirms the settlement; onChain.payer is re-derived from the transaction, so matchesClaims: false means the receipt forged the payer; amount is a verified lower bound. It is read-only and open-world (it reads the on-chain tx via RPC). Unlike most tools it never throws — a chain or RPC problem comes back in the error field, never as an exception. It calls the static PipRailClient.verifyReceipt, so the same check is available wallet-free in code; see Verifying receipts and Verifiable receipts.

{ "ok": true,
"onChain": { "payTo": "0xMerchant", "asset": "0x…", "amount": "100000", "payer": "0xBuyer" },
"matchesClaims": true, "ageSeconds": 42 }

When the server is built with guide on (the default — PIPRAIL_GUIDE off only suppresses it), two extra MCP surfaces are exposed alongside the tools. They are purely additive: with guide off, the tools path is byte-identical.

SurfaceKindContent
piprail_agent_guidepromptThe full agent contract — how to pay, reading a refusal, Mode A vs B.
piprail://guideresource (text/markdown)The same PIPRAIL_AGENT_GUIDE text.
piprail://budgetresource (application/json)The live spend leash: { spent, remaining, grandTotal, counts, session, policy } — the same as the piprail_budget tool, minus the one-line report summary (the resource omits it).

The piprail://budget resource mirrors the running client’s budget — including the grand-total (grandTotal), payment-count leash (counts), and the configured policy read back (policy) — so a client can poll the remaining leash as a resource read rather than a tool call. See Modes for how the guide and the confirm hook fit together.