Server data from the Official MCP Registry
Say what your agent needs: Fizzl buys the right paid x402 API, checks the answer. Free pick.
About
Say what your agent needs: Fizzl buys the right paid x402 API, checks the answer. Free pick.
Remote endpoints: streamable-http: https://buy.fizzl.eu/mcp
Security Report
Valid MCP server (1 strong, 0 medium validity signals). 5 known CVEs in dependencies Imported from the Official MCP Registry. Trust signals: trusted author (9/9 approved); 3 highly-trusted packages.
2 tools verified · Open access · 5 issues found
Security scores are indicators to help you make informed decisions, not guarantees. Always review permissions before connecting any MCP server.
Permissions Found in Source Code
Found by scanning the linked source code. This listing connects to a hosted endpoint, so none of this runs on your machine: it describes what the server software does where it is hosted.
How to Connect
Remote Plugin
No local installation needed. Your AI client connects to the remote endpoint directly.
Add this to your MCP configuration to connect:
{
"mcpServers": {
"io-github-fizzl13-fizzl-buy": {
"url": "https://buy.fizzl.eu/mcp"
}
}
}Documentation
View on GitHubFrom the project's GitHub README.
x402 Doctor
· Live status ·
Diagnoses why an x402-payable endpoint's payment flow is broken, without needing a funded wallet.
Paste a URL (web app) or run x402-doctor <url> (CLI, CI) and get back exactly which check failed, why, and how
to fix it. Every check traces back to a real bug hit while shipping
PlainText and
Ichimoku Signal.
▶ Watch the 70-second explainer (with voice and captions): diagnosing a broken endpoint, the pre-payment check for agents, and the daily Trust Index.
▶ New: the paid fix in 70 seconds: for $0.05 the Doctor hands you the medicine, the exact code that fixes each problem for your stack, in the browser or as JSON for agents.
What it checks
| Group | Check | Catches |
|---|---|---|
| 402 challenge | returns-402 | No 402 for GET or POST (tries both, or --method). Behind Cloudflare or Amazon CloudFront the hint names the usual Monetization Gateway or AWS WAF Monetize rule misses. An endpoint that asks for x401 proof first is info, not a failure. A POST that answers 400 or 422 to an empty body checks its input before payment: Doctor sends the requestBody example from the seller's /openapi.json (or one built from its schema), or your own example body, and without one the check is a warning (needs input), not a failure |
x401 | An x401 proof request (PROOF-REQUEST, x401.id) instead of a 402: the endpoint asks who is behind the agent before it asks for payment. Pass when the base64url payload names scheme x401, a version and credential requests (with their protocols, the token endpoint and the payment hint); a warning when agents can't read it; info for the older header name PROOF-REQUIRED | |
protocol-version, challenge-header | v1 vs v2, missing x402Version, challenge in the wrong header, undecodable header | |
envelope-body-mirror | Header-only challenge (@x402/express sends {}), header and body disagreeing | |
| MCP (payment per tool call) | mcp-server | When the URL answers no 402 but speaks MCP (Streamable HTTP, JSON or SSE, with or without a session): initialize and tools/list without payment |
mcp-paid-tools | No tool description says it is paid (x402, USDC, a price), so agents can't tell | |
mcp-payment-required | One unpaid tools/call per paid-looking tool (at most 2; explicitly paid tools first — "Paid …" or a price / "via x402" in the title; never tools that call themselves free, destructive tools, or write tools unless explicitly paid). A free answer warns only for an explicitly paid tool, otherwise it is info: the x402 payment requirement in the tool result with isError: true (as @x402/mcp), or an HTTP 402 with PAYMENT-REQUIRED instead (payable over HTTP, not by @x402/mcp clients), a JSON-RPC error, a tool that answers for free, or example arguments refused before the payment step (publish one valid call as _meta.examples to avoid that). The requirement then gets the payment-option, settlement and wallet checks below | |
mcp-tool-poisoning | Hidden orders for the agent in tool descriptions (tool poisoning): hidden Unicode characters, <IMPORTANT> blocks, reading ~/.ssh or .env, "do not tell the user", sending the maximum USDC (code rules), then TypeSafe Jev per tool (with TYPESAFE_API_KEY). A sure finding is warn, an unsure one info. Calibrated on 755 tools of 96 servers from the official MCP registry: no false alarm, and five made-up poisoned tools all caught | |
mcp-payment-text, mcp-payment-structured | The requirement only in structuredContent (the x402 MCP transport requires JSON text in content[0]), or only as text (structuredContent preferred) | |
| Payment options | accepts[i]-scheme, -network | Missing scheme; legacy names like base / solana:mainnet instead of CAIP-2 |
accepts[i]-payto, -asset | Invalid EVM, Solana, XRPL or Algorand addresses (XRPL and Algorand with their checksums); a payTo that is a placeholder nobody holds a key for (the zero address, which USDC refuses, 0x…dEaD, or Solana's System Program or incinerator), also as an MPP recipient; asset that is not USDC, or USDC of another network (e.g. Base Sepolia USDC on Base); on Algorand an asset that is not an ASA id (USDC is ASA 31566704); on XRPL an XRP amount that isn't in drops, or "RLUSD" from another issuer than Ripple's | |
accepts[i]-amount | Decimal dollar amounts ("0.02") instead of atomic units, zero or non-integer amounts | |
| Stellar options | x402 exact on Stellar (stellar:pubnet, @x402/stellar): payTo a G…, C… or M… address with a valid StrKey checksum, asset a Soroban token contract (USDC is CCW67TSZV3SSS2HXMBQ5JFGCKJNXKZM7UQUWUZPUTHXSTZLEO7SJMI75; "USDC" or a testnet contract fails), a positive integer amount (USDC has 7 decimals: 100000 is $0.01) and extra.areFeesSponsored: true, without which the client refuses | |
aws-test-mode | A 402 served through Amazon CloudFront that offers only testnets (info): AWS WAF Monetize left in Test currency mode | |
accepts[i]-extra | Solana without extra.feePayer (clients throw "feePayer is required"), EVM without the EIP-712 name/version | |
accepts[i]-batch, -batch-delay, -batch-deposit, batch-escrow | The batch-settlement scheme (one deposit into the x402 escrow, then a signed voucher per call, claimed in batches): extra.receiverAuthorizer missing (clients refuse), withdrawDelay missing or outside 900 s to 30 days, no EIP-712 domain for the EIP-3009 deposit, minDeposit not in atomic units, the escrow not deployed on the network; the deposit and withdraw delay buyers commit to | |
accepts[i]-auth-capture, -auth-escrow, -auth-deadlines, -auth-fees, -auth-domain, -auth-flow, auth-capture-escrow | The auth-capture scheme on EVM (the buyer signs once; the amount is held in the commerce-payments escrow until the seller captures it, with refunds until a deadline): no operator (extra.captureAuthorizer), an escrow that is neither commerce-payments v1.1 nor v1.0, a capture deadline that has passed or a refund deadline before it, fee bounds outside 0 <= min <= max <= 10000 bps or no fee recipient, no EIP-712 domain for the EIP-3009 authorization, a charge (paymentFlow authorization) without receiverAuthorizer, the escrow not deployed on the network; when the money is captured and until when it can be refunded | |
accepts[i]-cloudflare, -payto, -amount, cloudflare-registration | Cloudflare pay per crawl (batch-settlement on network cloudflare:402): payTo must be merchant (Cloudflare settles, as merchant of record), the price is a currency code (USD) and an amount in cents, and the 402 carries the http-message-signatures extension with the URL where agents register their signing key. Paid by crawlers and agents registered with Cloudflare (Web Bot Auth), not by wallets: the preflight says caution (cloudflare_crawler_only), not no-go | |
accepts[i]-extra, circle-gateway, accepts-order | Circle Gateway options ("exact" signed for the Gateway Wallet, domain GatewayWalletBatched): extra.version other than "1" or no verifyingContract (Circle's client skips or can't sign it), a contract that isn't Circle's Gateway Wallet; who can pay them (a Gateway balance and Circle's client, not standard x402 clients or browser wallets; their 7-day timeout is right); a Gateway option listed before the standard one on the same network, which x402 clients would pick and fail | |
accepts[i]-scheme | A scheme standard x402 clients don't pay (anything but exact, upto, batch-settlement and auth-capture; eip3009 gets the hint to use exact): what it requires is unknown, so a missing or unusual payTo, asset or amount is a warning, not a fail (a burn address stays a fail). The preflight never recommends such an option over a standard one; with only such options it says caution (custom_scheme_only) | |
accepts[i]-scheme, -network, -plan | Nevermined plans (nvm:erc4337 on eip155:<id>, nvm:card-delegation on stripe, braintree or visa): no payTo or amount is asked, since the price is in the plan; the network must be the settlement rail (not sandbox or live), planId a plan id and extra.agentId set. The preflight says caution (nevermined_plan): payable only with a Nevermined account and its SDK, not by standard x402 clients | |
| Resource | resource-url | http:// resource URL on an https:// endpoint (Express behind a TLS proxy without trust proxy); a path instead of a full URL (judged against the endpoint, a warning) |
resource-metadata | Missing description / mimeType | |
| Settlement | solana-payout-account | Solana payout wallet without a token account for the asset: every settlement fails on-chain |
xrpl-payout-account, xrpl-payout-trustline | XRPL payout account that was never activated, has Deposit Authorization on, or requires a destination tag the option doesn't give; for a token like RLUSD, no (or a frozen) trust line to its issuer: every payment fails | |
accepts[i]-lightning, lightning-invoice, lightning-request-hash | Bitcoin Lightning (x402 exact on lnbtc, Sept 2026): payTo must be the node key, amount in millisatoshis, paymentFlow: "upfront" and a request binding (http:1/mcp:1); the BOLT11 invoice in extra.invoice is decoded and must match the option exactly (amount, bc/tb, expiry = maxTimeoutSeconds, signed by payTo, not expired) and commit to extra.requestHash, which for http:1 is recomputed for the doctor's own request | |
algorand-payout-optin | Algorand payout address that has not opted in to the asset (an account can only receive an ASA after opting in): every payment fails | |
stellar-payout-trustline | Stellar payout account (G…) that was never funded, or has no (or an unauthorised) trustline to Circle's USDC: every payment fails. Read from Horizon; a contract (C…) needs none | |
solana-wallets | Solana settled by PayAI, which rejects Phantom (Lighthouse instructions before the transfer) | |
| Who can pay | wallets | Per wallet (MetaMask, Coinbase Wallet, Rabby, Phantom, Solflare, Backpack, Pera, Defly, Xaman, Crossmark, GemWallet, x402 agents, which also pay Stellar): the networks where payment works and where it fails, and why. Also in the JSON report as wallets |
metamask-site-scan | Only with METAMASK_SCAN=on (off by default: the endpoint has no published API or licence). MetaMask's site scanner (Blockaid) blocks the domain (e.g. "wallet drainer"): MetaMask users can't open the site or pay in the browser. With how to report a false positive. Agents are not affected | |
evm-payto-eoa | EVM payout wallet is a regular wallet (EOA): MetaMask's Blockaid check may flag the payment signature as "a deceptive request". Info, with how to get it cleared | |
coinbase-agents | Whether Coinbase's agent wallets can pay: Wallet MCP pays x402 in USDC on Base with exact, upto or auth-capture and finds services through the CDP Bazaar (the line says whether this route is listed there, from bazaar-listing); the Coinbase MCP also needs x402 v2 and at most $5 a call, and fetches only its own curated catalog. Info when there is no USDC on Base or only another scheme | |
| Discovery | bazaar, bazaar-output | Missing or invalid Bazaar declaration, output example not matching its schema |
market-price | Where your price sits among comparable paid APIs of other sellers in the x402 Trust Index (median and range; comparable as judged by TypeSafe Jev, with TYPESAFE_API_KEY). Always info; the hint speaks up when agents' preflights would point at cheaper services, or when you charge far less than the rest | |
onchain-payments | Real payments to your payout address on Base in the last 7 days (or on Solana or the XRP Ledger when you have no Base option): how many different wallets paid it, how often and how much, counted from the chain every hour (on Base USDC signed with EIP-3009, the way x402's exact scheme settles; on Solana USDC transfers whose fee an x402 facilitator paid; on the XRP Ledger RLUSD and USDC payments an x402 client marked with SourceTag 804681468 or an InvoiceID; Permit2, Circle Gateway and other networks aren't counted). It says how many payers also paid 10 or more other sellers, as checkers and scanners do, and how to get counted when your endpoint isn't in the Trust Index yet. Always info: new sellers start at zero | |
bazaar-replay | The declared example request not answering 402, so the Bazaar cannot index it | |
payto-stable | The payout address (payTo) changing from one 402 to the next: a buyer asked again sees a new payTo and may pay twice for one call | |
bazaar-route | A Bazaar routeTemplate that is not a path (e.g. :var1) or has a :param without a pathParams value, so the request built from it is an invalid URL | |
openapi-present, openapi-title, openapi-guidance | Missing /openapi.json, info.title, info.x-guidance | |
openapi-contact, openapi-ownership, openapi-input-schema, openapi-free-routes | What x402scan and AgentCash read beyond that: info.contact.email (info), an ownership proof under x-agentcash-provenance.ownershipProofs, checked by recovering the signer of the bare origin against the EVM payTo (pass, or a warning for a trailing slash, another signer, a broken signature or a top-level ownershipProofs that x402scan ignores), paid operations without parameters or requestBody (x402scan does not register them) and operations with neither x-payment-info nor "security": [] (free ones are reported as unprotected). Info lines unless a proof is present but wrong | |
well-known | /.well-known/x402 missing (info), unreadable (resources as URLs or objects with a url are both read), or listing resources on another host than the one checked (built from the request Host header, it keeps pointing crawlers at an old domain). A platform address such as *.onrender.com pointing at its own domain is fine | |
well-known-names | Resources in /.well-known/x402 without a name and description (info): directories such as the XRPL AI Hub list each resource by them. | |
agent-instructions | /skill.md on the origin, so a user can tell an agent connect to <host>/skill.md (Coinbase's pattern); /llms.txt counts as the older form, and an HTML page served on every path does not count. Info when there is none | |
bazaar-listing | Where the CDP Bazaar lists this route (same path, same payTo): under this origin, not yet, or only under another host. The Bazaar keeps the URL the payer used, so after a domain move a route stays listed under the old host until someone pays through the new one. On the web check and the paid API (not the CLI) | |
bazaar-last-payment | When the CDP Bazaar lists the route here: how long ago it counted the last settled payment. From 21 days a warning, since the Bazaar drops a route after 30 days without one (one paid call keeps it listed). | |
cdp-validate | Coinbase's own verdict: Doctor asks CDP's free validate API whether the CDP facilitator would index the route in the Bazaar (the index Coinbase's agents search), and shows the failures it names, without the ones it skips after the first. A warning when the endpoint offers Base or Solana, info otherwise; a pass may carry CDP's advice. HTTPS only; nothing when CDP doesn't answer. Answers cached 10 minutes. On the web check, the paid diagnose and fix, and MCP (not the CLI); the daily health check also runs it on every Fizzl paid route. CDP_VALIDATE=off turns it off | |
merchant | The x402-merchant extension (name, website, logo, categories) that GoPlausible's catalog shows on the seller: a warning when malformed, an info line when it is missing on an endpoint that offers Algorand | |
builder-code | The Base Builder Code (ERC-8021, the x402 builder-code extension): the buyer's client echoes the app code and the facilitator writes it into the settlement, so Base attributes the payment. A warning when the facilitator would drop it (code not under info, an invalid or missing info.a, invalid or too many service codes, an x402 v1 challenge); an info line when a route that settles on Base has none, or when no option settles on an EVM chain | |
| Browser | paywall | Browser paywall in testnet mode on a mainnet endpoint (@x402/paywall defaults to testnet; the flag is read from JS or JSON config) |
Statuses: pass, warn (works, but something is off), fail (payments fail or it is not valid x402), info.
Web app
npm install
npm start # http://localhost:3001
Reports are shareable: https://<host>/?url=<endpoint>&method=GET runs the diagnosis on load (&method=POST&body=<json> for a POST with an example body).
API: POST /api/diagnose with { "url": "...", "method": "GET" | "POST", "body": { ... } } (method and body optional)
returns { url, method, overall, checks[], challenge, share_url }. body is an example request body (JSON, up to
16 KB) for a POST that checks its input before the 402; it implies POST, and the report says which body reached the 402
(body, and body_source when it came from the seller's /openapi.json). share_url is the page link above, to paste into an issue or a chat. Rate-limited to 10 diagnoses per minute per IP.
Paid API for agents (x402)
GET /api/v1/diagnose?url=<endpoint>&method=GET|POST returns the same report, $0.01 USDC per call on Base or
Solana via x402, with no rate limit. It is meant for agents and CI pipelines; the web page stays free.
- Unpaid requests get the x402 challenge (
PAYMENT-REQUIREDheader, mirrored in the body) with a Bazaar input and output schema. body=<URL-encoded JSON>(optional, also on preflight, deep and fix, and asbodyin the MCP tools): an example request body for a POST route that checks its input before the 402. It implies POST; withmethod=GET, or when it is not JSON, the answer is a 400 before payment. The batch takes no body.- Invalid input (bad URL, non-http(s), unknown method) gets a 400 before payment. The bare route without
urlanswers 402, so indexers such as x402scan can register it. Paying without aurlreturns a 400. - The x402 middleware settles only after a 2xx response, so a diagnosis that errors out is never charged.
- Discovery:
/openapi.json(withx-payment-info) and/.well-known/x402. - Browsers opening the route get a wallet paywall (Base first: MetaMask, Coinbase Wallet) instead of the bare 402.
- Bazaar: a facilitator lists a route after the first payment it settles for it. With the CDP keys set, one paid call (e.g. from the browser paywall) puts the route in the CDP Bazaar that agents search.
# pay-per-call from Node with @x402/fetch
const paidFetch = wrapFetchWithPayment(fetch, client); // client with an EVM or SVM signer
const report = await (await paidFetch("https://<host>/api/v1/diagnose?url=https://api.example.com/paid")).json();
Pre-payment check for buyers: GET /api/v1/preflight
GET /api/v1/preflight?url=<endpoint>&max_usd=0.05&network=<caip2>&method=GET|POST, $0.001 USDC per call:
call it before your agent pays an x402 endpoint it has not used before. It never pays the endpoint. Add
client=gateway when your agent pays with Circle's Gateway client from a Gateway balance: Circle Gateway-only
endpoints (gateway_only, otherwise a caution) are then a go, and a Gateway option is recommended first.
{
"verdict": "go", // go | caution | no_go
"safe_to_pay": true,
"summary": "OK to pay: $0.02 on Solana.",
"recommended_option": 1, // index into the endpoint's accepts[]
"options": [{ "network": "eip155:8453", "asset_symbol": "USDC", "usd": 0.02, "payable": true, "problems": [] }, …],
"signals": { "https": true, "advertised_price_usd": 0.02, "listed_in_cdp_bazaar": true },
"reasons": [], // [{ level: no_go | caution | info, code, message }]
"cached": false
}
| Verdict | When |
|---|---|
no_go | No 402 or no valid challenge; every option would fail to settle (bad payTo/amount, a payTo that is the zero or another burn address (payto_burn, caution when another option is payable), missing fee payer or EIP-712 domain, Solana payout wallet without a token account); cheapest option above max_usd; no payable option on the requested network |
caution | Charges more than its OpenAPI advertises; not HTTPS; not a known USDC (or BNB Chain dollar token) contract; decimal amount, or a 6-decimal amount on an 18-decimal token; resource URL differs from the requested URL; testnet only; bait (below); 20x or more above comparable services (below) |
go | None of the above. recommended_option is the cheapest payable USDC option (on network if given); at the same price, one every x402 client can pay (EIP-3009, not Permit2) and USDC before other dollar tokens |
BNB Chain (eip155:56) has no Circle USDC. Sellers price in 18-decimal dollar tokens: Binance-Peg USDC, USDT,
USD1 and United Stables (U), so $0.01 is "10000000000000000". Doctor prices those options like USDC. USDC and USDT
there have no EIP-3009, so an option without assetTransferMethod: "permit2" fails; a value standard x402 clients
don't know is a warning, because @x402/evm then signs EIP-3009 instead. "permit2-exact" and "permit2-upto" are the
methods of Binance's B402 facilitator, so only its own clients pay those options.
Bait check (TypeSafe's Jev, when TYPESAFE_API_KEY is set): for an endpoint that could be paid, Jev judges
what the protocol checks can't. Does it claim to be, or to be official from or endorsed by, a brand that doesn't own
its domain (brand_impersonation; reselling or proxying a brand's product under the seller's own name, such as an
LLM gateway naming the models it serves, is not), lure with free tokens, airdrops or guaranteed returns (lure_description), or
promise something its declared output doesn't deliver (output_mismatch)? A clear yes is a caution, an
in-between answer info; it never makes a verdict no_go and never turns one into go. The probabilities are
in signals.jev_lure. On 300 real CDP Bazaar listings it raised no caution for brand or lure wording. When a bait
question changes (BAIT_VERSION in lib/jev-lure.js), the Trust Index's next run asks again, first, every service
the old wording flagged or was unsure about; clear answers carry over.
Namesakes (same key, from the daily Trust Index scan, lib/namesakes.js): the x402 Bazaar indexes each
listing's service name, so an agent that searches for a known service finds every listing with that name. When
another seller, with its own payout address and fewer payers, lists under the brand name of an established service,
the preflight adds namesake (info: the name, the original's site and both payer counts). Sites that share a payout
address, a distinctive host-name word or three or more names count as one owner, and TypeSafe's Jev must be sure
(0.85) that the name is a brand rather than a description such as "web search". On 23 Oct 2026, 83 names were listed
by more than one owner and one was a brand with a better-known original. It never changes the verdict: a namesake
can be a fair reseller or an unrelated service.
Price check (same key): is the price far above what comparable services ask? Doctor takes up to 24 paid APIs
of other sellers from the x402 Trust Index whose descriptions share rare words with this one (at most two per
seller), and Jev judges per candidate whether a buyer would be served just as well by it. With at least 5 such
services, their median price is the comparison: 5x or more (and at least $0.05 more) is info, 20x or more (and
at least $0.25 more) a caution, both price_high and naming up to three cheaper alternatives. The comparison is
in signals.price_check (comparable_median_usd, comparables, ratio, cheaper[]). It never makes a verdict
no_go: the price is the seller's choice, the agent decides whether it is worth it.
Not being listed in the CDP Bazaar is reported as info only. Results are cached for 10 minutes per URL, budget
and network (cached: true), so checking before every payment stays fast.
Several endpoints at once: GET /api/v1/preflight/batch
GET /api/v1/preflight/batch?url=<a>&url=<b>&max_usd=0.05, $0.005 USDC per call for up to 10 endpoints (one
url parameter each; duplicates count once). For marketplaces, directories and agents that weigh several services.
Each endpoint gets the same verdict as a single preflight; one that errors or does not answer within 20 seconds is
unknown and does not hold up the rest.
{
"count": 2,
"counts": { "go": 1, "caution": 0, "no_go": 1, "unknown": 0 },
"results": [
{ "url": "https://a.example/paid", "verdict": "go", "safe_to_pay": true, "summary": "OK to pay: $0.02 on Base.", "recommended_option": 0, "options": […], "reasons": [] },
{ "url": "https://b.example/paid", "verdict": "no_go", "safe_to_pay": false, "summary": "Do not pay: …", … }
]
}
Before an expensive call: GET /api/v1/preflight/deep
GET /api/v1/preflight/deep?url=<endpoint>&max_usd=0.5, $0.01 USDC per call: everything the preflight answers,
plus
diagnosis: the full diagnosis (overall, every check, and the failing or warning ones asproblems);history: the daily scans of the last 30 days, one{ date, status }per day;seller: the seller's other scanned endpoints on the same origin (how many, payable today, average payable ratio, how many were unreliable). A seller whose endpoints were payable on less than half of the scans turnsgointocaution(unreliable_seller);domain: the domain-move checks (well-known,bazaar-listing), e.g. a Bazaar listing only under an old domain.
Paid and delivered? GET /api/v1/delivery-check
GET /api/v1/delivery-check?url=<endpoint>&method=GET|POST, $0.25 USDC per check: x402 Doctor buys the endpoint
once, with the example input its own listing declares, and publishes what came back. For sellers who want proof that
their endpoint delivers, and for buyers before a large order.
- Checked before you pay: the endpoint must be https, not a fizzl.eu route, get a
gofrom the pre-payment check, be payable in USDC on Base and cost at most $0.10. Anything else answers 400 (or 503 when the day's 20 checks are taken), and nothing is charged. A request with a payment always waits for the whole check before anything settles. A probe without a payment wants the 402: it gets one unless the request itself is malformed (not one https URL, a fizzl.eu route, a bad method), also for an endpoint that can't be bought now, since uptime monitors fillurlwith a placeholder such ashttps://example.com, and within 5 seconds (the CDP Bazaar's validator and health probe give up after 10). To get the answer before paying, sendX-Delivery-Precheck: 1; the homepage does. - The answer comes at once, the purchase shortly after: the paid call answers with a job
idand astatus_url.delivery-check.ymltakes the queue (GET /api/v1/delivery-check/queue, free) and buys with the dedicated spot-buy wallet (SPOT_BUY_KEY; no wallet key on the server). Only a job whose payment settled is released to the queue. The server starts the workflow as soon as a payment settles (DELIVERY_DISPATCH_TOKEN: a fine-grained GitHub token for this repository with only Actions read and write;lib/delivery-dispatch.js); its schedule, every 10 minutes, is the fallback, since GitHub runs scheduled workflows late or not at all. - The same steps as the spot-buy (
lib/spot-buy.js): a fresh preflight with the OFAC payout screen right before paying, the seller's declared example input, the answer checked against the declared output schema and judged by TypeSafe's Jev (is it what was paid for, does it carry instructions for the agent:lib/jev-answer.js), and the charge measured on chain. - Public result:
GET /api/v1/delivery-check/<id>(free) showsqueued, thendonewith the result (delivered,off_schema,empty,charged_not_delivered,payment_rejected,error_not_charged, or the step that stopped it before paying) and the transaction. Every result is on thedelivery-databranch. - Caching: for a delivered GET answer,
cachesays whether a shared cache (a CDN) may store the paid answer and serve it to callers who did not pay (shared_cache:yes,noorunspecified, with theCache-Controlit sent). The x402 payment travels in its own header, not inAuthorization, so onlyCache-Control: privateorno-storekeeps it out (Five Attacks on x402, attack III).
Jobs are kept in the credits Redis (CREDITS_REDIS_URL); without it the route answers 503 before payment.
Prepaid credits: GET /api/v1/credits/1000
Agents that check often can prepay: one x402 payment of $0.80 for 1000 credits or $7.00 for 10,000 (20% and 30% off), valid for a year. A credit is $0.001: a preflight costs 1, a batch 5, a deep preflight or a diagnosis 10, the fix 50. The pack answers with a credit_key; send it as the x-credit-key header with any paid call instead of paying. GET /api/v1/credits (free) shows the prices and, with the header, your balance. A call that fails gives its credits back; with no key or too few credits the normal 402 applies. Needs CREDITS_REDIS_URL (a persistent Redis such as Upstash; the presign-guard instance is fine, the keys are apart); without it, no packs are sold.
The fix, as code: GET /api/v1/fix
GET /api/v1/fix?url=<endpoint>&method=GET|POST&stack=<optional>, $0.05 USDC per call: diagnoses the endpoint,
then returns, per failed or warning check, the concrete change that fixes it, as code for your stack and filled in
with your own values (payTo, amount, network, route).
{
"stack": { "id": "express", "name": "Express (@x402/express)", "detected_from": "x-powered-by: Express" },
"summary": "3 fixes (1 blocking), for Express (@x402/express).",
"fixes": [
{
"recipe": "amount",
"severity": "warn",
"checks": ["accepts[0]-amount"],
"title": "Amount \"0.01\" → \"10000\" ($0.01)",
"why": "x402 amounts are integer strings in the token's smallest unit; USDC has 6 decimals.",
"steps": ["Easiest: let the SDK convert it by using price: \"$0.01\" instead of an amount."],
"code": [{ "language": "javascript", "stack": "node", "label": "Route config", "snippet": "accepts: [{ scheme: \"exact\", price: \"$0.01\", ... }]" }],
"verify": "Run x402 Doctor again on https://…; accepts[0]-amount should pass."
}
],
"unfixed": []
}
The stack is read from the response headers (x-powered-by, server, Vercel/Render/Cloudflare headers) and the
challenge: express, next, hono, node (an @x402 SDK behind another framework), python or generic (raw
HTTP, for any language). Pass stack= when the guess is wrong. Node snippets use the @x402 v2 route config, which is
the same for @x402/express, /next and /hono; lines that only apply to Express say so.
Recipes (lib/recipes.js, one test each in test/recipes.test.js): no 402 at all (200 before the paywall, auth or
validation first, 404/405, unreachable), v1 or invalid challenge, wrong header name, no body mirror, no accepts,
scheme, legacy network names, invalid payTo (spots quotes, spaces, the wrong chain), USDC asset, decimal amounts,
Solana fee payer, EIP-712 domain, http resource URL behind a proxy, resource URL and metadata, Bazaar declaration and
example, Solana payout token account, Phantom on PayAI, testnet paywall on mainnet, and openapi.json. Anything
without a recipe is returned under unfixed with the diagnosis hint.
Learning from outcomes: POST /api/v1/outcome
After a paid preflight, a buyer can report (free) what happened when it then paid the endpoint: paid_ok, paid_failed (402 again) or paid_error. x402-safe-fetch does it with shareOutcomes: true.
{ "outcome": "paid_failed", "status": 402, "preflight": { …the signed preflight answer… }, "query": { "url": "…", "method": "GET", "max_usd": "0.05", "network": "eip155:8453" } }
- A report counts only with a real preflight that Doctor signed for exactly that query, once per preflight (
receipt.request_id), so a false report costs a paid preflight. - Doctor counts reports per endpoint over 30 days. When most reported payments failed, from at least three different paying wallets, later preflights add
payments_fail_after_preflight(caution);signals.agent_outcomesshows the counts. - Reports land in the usage log (endpoint, outcome, status, verdict, payer from the receipt); nothing else about the buyer.
Signed verdicts
Every paid answer (diagnose, preflight, batch, deep and fix; HTTP and MCP) carries a receipt signed by Doctor, so an agent can later prove which verdict it got for which endpoint, for example why it did or didn't pay:
"receipt": {
"request_id": "…", "route": "GET /api/v1/preflight", "input_sha256": "…",
"payment": { "network": "eip155:8453", "amount": "1000", "payer": "0x…", "nonce": "0x…", "proof": "eip3009" },
"signed_at": "2026-09-27T08:00:00.000Z", "signer": "0x…",
"algorithm": "eip191-canonical-json-v1", "signature": "0x…"
}
- Signed: the whole answer without
receipt.signature, as canonical JSON (profilejs-json-stringify-sorted-utf16-ascii-v1: keys sorted by UTF-16 code units, compact, every code unit from U+007F up as lowercase\uXXXX, numbers as JavaScript'sJSON.stringifywrites them —1.0→1,0.000001→0.000001— then UTF-8 bytes; Python'sjson.dumpsmatches only for ASCII keys and integers, so useexamples/canonical.py, which also hasverify_receipt(answer)), with EIP-191personal_sign. Flipping the verdict or moving it to another request breaks it. payment: the payment that bought this answer, from your x402 payment payload. On Base the payer and the EIP-3009 nonce, so anyone can find the settlement on-chain as the USDC contract'sAuthorizationUsed(payer, nonce)event; on Solana the payer and a SHA-256 of the signed transaction you sent.input_sha256: SHA-256 of the canonical JSON of{"route", "input"}, whereinputis your query parameters as strings (HTTP) or the tool arguments (MCP, routemcp <tool>).- Signer:
/.well-known/x402-doctor-signer.json, with retired signers listed so old receipts keep verifying. - Free check:
POST /api/v1/verifywith{"response": …, "route": …, "input": …}returnsvalid,signer,known_signerandinput_matches. Over MCP: the free toolverify_receiptwith the same arguments (routelikemcp x402_preflight,inputthe tool arguments).
Key rotation without client updates: the payout wallet (0x6B0F4651eD42893ab58139938175E4a69f175F25) authorises each signing key with a personal_sign over fizzl receipt signer / service: x402-doctor / signer: <address> / valid_from: <YYYY-MM-DD>. Set it as RECEIPT_SIGNER_CERT (YYYY-MM-DD:0x<signature>, produced by /sign-receipt-key in the wallet's browser). It is checked at startup and carried in every receipt as receipt.cert, so a client that pins only the payout wallet verifies a new key offline.
Same format as presign-guard, so one verifier works for both. The key comes from RECEIPT_SIGNER_SECRET (holds no funds); without it answers are unsigned.
x402 Trust Index
Documentation truncated — see the full README on GitHub.
Reviews
No reviews yet
Be the first to review this server!
More Developer Tools MCP Servers
Rea
Freeby Morluto · Developer Tools
Reverse engineer anything from your terminal or agent with one CLI and MCP server.
Paperclip
Freeby Paperclipai · Developer Tools
Trending hip-hop artist momentum scores across four cultural dimensions.
Git
Freeby Modelcontextprotocol · Developer Tools
Read, search, and manipulate Git repositories programmatically
Fetch
Freeby Modelcontextprotocol · Developer Tools
Web content fetching and conversion for efficient LLM usage
Toleno
Freeby Toleno · Developer Tools
Toleno Network MCP Server — Manage your Toleno mining account with Claude AI using natural language.
MCP Marketplace
Freeby mcp-marketplace · Developer Tools
Search and install MCP servers from inside your AI client.


