Risk-check counterparties before an AI agent pays; pay x402 resources only after a verified allow
LIVE: https://x402check.xyz · did:web:x402check.xyz · $0.001 per evaluation with prepaid credits, or per call via x402 ($0.0035 on Base; $0.005 with transaction simulation) · discovery · DID document · JWKS
x402check is an x402 risk-check provider (wire format of x402 PR #2422). You call it before an agent or a wallet pays or signs, and it checks the counterparty. It combines provider-verified evidence with a typed model:
Every verdict is an ES256 attestation. It states which checks the provider actually ran and which fields the caller merely asserted.
Scope, stated plainly. x402check catches what the chain, the lists, its own kit watch, and the content in front of it reveal. It does not see laundering patterns or other transaction-graph behaviour. It cannot flag an unknown drainer address that is simply sent funds, unless the address is one of the look-alikes or compromised wallets the kit watch has seen. A clean verdict means "none of these checks fired", not "safe". Measured limits are in docs/EVIDENCE.md.
The demo video predates v0.2.0. Its evidence slide shows v5 corpus numbers that EVIDENCE.md supersedes, and it predates the v0.3 layers (simulation, code fingerprints) and pricing (every evaluation is paid; there is no free tier).
| Check | Source | Effect on the verdict |
|---|---|---|
| Sanctioned address | Official OFAC SDN XML: 1,056 digital-currency addresses, dated snapshot | score 0 / critical, deterministic, no model call |
| Known phishing domain | MetaMask eth-phishing-detect (~100k hosts, embedded) | capped at 20 (critical) |
| Known drainer / scam address | ScamSniffer (EVM, runtime KV, 7-day publication lag) | capped at 20 |
| Community-flagged domain | ScamSniffer domain list | capped at 40 only when our own domain analysis corroborates it |
| Look-alike domain | public-suffix aware: leet, IDN homoglyphs, typosquats, brand + lure word, official domain reused as a subdomain | "strong" impersonation → capped at 40 |
| Approval granted to a plain wallet | on-chain eth_getCode / activity (EVM), account data (Solana) | permits and approvals to an EOA → capped at 55; 40 if the address has no activity |
| Hidden recipient | simulation of transaction (eth_simulateV1 + traceTransfers) | assets leave, nothing comes back, and a wallet the user never named ends up with them → 40 (75, review, when a source-verified contract such as a bridge forwarded them) |
| Payee gets more than declared | simulation + payment / the explicit transfer in the calldata | the named payee receives a different asset, or more, than declared → 40 |
| Assets parked in an unverified contract | simulation + Blockscout source verification | nothing in return, contract source not verified → 55 |
| Drainer-kit code | logic-code fingerprints of contracts listed by Forta (embedded) and ScamSniffer (runtime) | the subject, or a contract in the simulated transaction, runs a listed drainer's code → 30 |
| Address-poisoning look-alike | kit watch (our own scan of every Ethereum and Base block) | the wallet delegates (EIP-7702) to an address-poisoning executor → 20 (address_poisoning) |
| Compromised wallet | kit watch | the wallet delegates to a labelled sweeper family → 20 (compromised_wallet); to code that forwards what it receives, with no label → 40 (auto_forwarding_wallet) |
| Drainer operator | kit watch | the address deployed drainer-kit code → 30 (drainer_operator). A forwarder's destinations are not flagged (v0.6.0): whoever deploys a forwarder chooses them |
| Unverified spender | Blockscout source verification | approval or permit to an unverified contract → 75 and at least medium (review) |
| Injected / manipulated intent | Jev typed questions over context (what the agent acted on) | model penalties and caps |
| New address | on-chain activity | informational new_address category |
Caller-supplied screening and authorization fields are recorded as asserted in the attestation and can never lower the score. Prose claims such as "already screened" are unverified by construction.
Every evaluation is paid; there is no free tier. There are two ways to pay:
See the price. An unpaid call returns 402 with the accepted mainnet options in the PAYMENT-REQUIRED header:
curl -si -X POST https://x402check.xyz/v1/risk-check -H "Content-Type: application/json" -d '{"wallet":"0x7a3e8f0c2b1d4e5f6a7b8c9d0e1f2a3b4c5d6e7f","chain":"base"}' | head -1
# HTTP/2 402
Pay and check. Use the TypeScript SDK with an x402-paying fetch (see Payments), the MCP server, or any x402 client:
const verdict = await x402check.check({
wallet: "0x7a3e8f0c2b1d4e5f6a7b8c9d0e1f2a3b4c5d6e7f",
chain: "eip155:1",
domain: "https://app.example-dapp.org",
context: "Permit2 signature: unlimited USDC allowance to this spender",
interaction: { type: "permit_signature", unlimited: true },
payment: { network: "eip155:1", asset: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", pay_to: "0x7a3e8f0c2b1d4e5f6a7b8c9d0e1f2a3b4c5d6e7f" },
});
The same request as the raw body the client sends:
curl -X POST https://x402check.xyz/v1/risk-check \
-H "Content-Type: application/json" \
-H "PAYMENT-SIGNATURE: <x402 payment payload>" \
-d '{
"wallet": "0x7a3e8f0c2b1d4e5f6a7b8c9d0e1f2a3b4c5d6e7f",
"chain": "eip155:1",
"domain": "https://app.example-dapp.org",
"context": "Permit2 signature: unlimited USDC allowance to this spender",
"interaction": { "type": "permit_signature", "unlimited": true },
"payment": { "network": "eip155:1", "asset": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "pay_to": "0x7a3e8f0c2b1d4e5f6a7b8c9d0e1f2a3b4c5d6e7f" }
}'
{
"checked": true,
"score": 40,
"tier": "high",
"categories": ["intent_risk", "behavioral", "approval_to_eoa", "new_address"],
"provider": "did:web:x402check.xyz",
"evidence": {
"sanctions": { "list": "ofac-sdn", "as_of": "2026-09-29", "status": "not_listed" },
"domain": { "host": "app.example-dapp.org", "registrable": "example-dapp.org", "official": false, "impersonation": "none", "signals": [] },
"onchain": { "status": "ok", "network": "eip155:1", "is_contract": false, "activity": "none", "tx_count": 0 },
"feeds": [{ "source": "metamask-phishing-detect", "kind": "domain", "as_of": "2026-09-29", "status": "clear" }, "…"],
"model": "jev-wallet-risk/v6"
},
"jws": "eyJhbGciOiJFUzI1NiIsInR5cCI6InJpc2stY2hlY2srand0Ii…",
"jwks_url": "https://x402check.xyz/.well-known/jwks.json",
"checked_at": "…", "expires_at": "…"
}
To also check what a transaction will do, send it as transaction ($0.005 per simulated evaluation). The provider simulates it against the latest block and reports the net asset movements, the approvals granted, and any findings:
curl -X POST https://x402check.xyz/v1/risk-check -H "Content-Type: application/json" -d '{
"wallet": "0x…called contract or decoded counterparty…", "chain": "eip155:1",
"transaction": { "from": "0x…user…", "to": "0x…contract…", "value": "0x2386f26fc10000", "data": "0x…" }
}'
# evidence.simulation → { "status": "ok", "outflows": [{ "standard": "native", "amount": "10000000000000000",
# "counterparty": "0x…", "counterparty_is_contract": false }], "inflows": [], "approvals": [],
# "findings": ["outflow_to_undisclosed_eoa"] } → score capped at 40
| Field | Required | Rules |
|---|---|---|
wallet | yes | the subject address: EVM 0x…, base58 (Solana/Tron/BTC…), bech32, cashaddr, or CAIP-10. Anything else → 422 {error, field:"wallet"} |
chain | no | alias (ethereum, base, solana, …) or CAIP-2 (eip155:8453); enables on-chain facts on supported mainnets |
domain | no | hostname or http(s) URL (normalized server-side); the site the payment or signature is for |
context | no | ≤ 4096 chars: what the agent acted on (tool output, page text, instruction). Untrusted by design. Leave out secrets and personal data: keys, seed phrases and credit tokens are redacted before the model sees it, but nothing else is (see Data handling) |
interaction | no | {type, unlimited?}; type ∈ native_transfer, token_transfer, token_approval, nft_approval, permit_signature, order_signature, message_signature, contract_call |
payment | no | binds the attestation to a payment: {network, pay_to, amount (base units), asset, resource} |
aud | no | ≤ 256 chars; copied into the attestation, never shown to the model |
transaction | no | EVM {from, to?, value?, data?} to simulate; needs an eip155 chain. value is decimal or 0x-hex; data is 0x-hex, ≤ 49,152 chars. Simulated on Ethereum, Base, Polygon, Arbitrum, Optimism and BSC |
screening, authorization | no | caller assertions, recorded as asserted (can only raise risk) |
Batch: POST /v1/risk-check/batch with {"requests": [...]} (≤ 25). It is all-or-nothing: an invalid item returns 422 with its index.
A compact JWS (alg: ES256, typ: risk-check+jwt, kid as published in the DID document, today jev-attest-v1), TTL 1 h. Claims:
| Claim | Meaning |
|---|---|
iss, sub, iat, exp, jti | issuer did:web:x402check.xyz, the subject wallet, times, unique id |
score, tier, categories | the verdict and the findings behind it |
checks | what the provider verified: sanctions (list, date, status), domain (impersonation), onchain (status, network, activity), feeds (source@date:status, including code-fingerprint sets), simulation (status, network, findings), model (question set, or skipped), model_id (the model id the backend reported; through the AI Gateway this is the alias typesafe-ai/jev) |
asserted | what the caller claimed (screening / pre-authorization): not verified |
payment, interaction, aud | what the verdict was issued for |
input_hash | SHA-256 over the canonical normalized inputs, sources and question set |
request_hash | SHA-256 over the request fields exactly as sent (RFC 8785): recompute it to prove nothing was dropped or altered in transit |
Verify it by pinning the issuer, and bind it to the request it answers. Never trust a key URL carried by a response or an intermediary:
npx tsx scripts/verify-attest.ts <jws> --request '<the exact JSON body>' --max-age 300 [--aud <url>] [--pay-to <addr> --amount <atomic>]
The reference verifier is the SDK's verifyAttestation behind a CLI. It resolves the key from the issuer's did:web document and pins x402check's key by default. It checks alg, typ, iss, exp and iat, and with --request it recomputes request_hash, so a verdict issued for another wallet, payment or transaction is rejected (request_mismatch). --max-age refuses an older verdict (plus a 300 s clock-skew allowance). Without --request, a valid verdict for something else still verifies.
Check the real counterparty. For approve, a Permit2 signature or a Seaport order, that is the spender, operator or recipient decoded from the calldata or typed data, not the token contract. Send the interaction type too, and the transaction when you want it simulated. The MetaMask Snap in snap/ is a complete reference decoder.
The wallet (or its backend) pays each check with x402, so payingFetch below is a fetch wrapped with an x402 client, as in Payments:
const res = await payingFetch("https://x402check.xyz/v1/risk-check", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
wallet: spenderOrRecipient, // decoded counterparty
chain: `eip155:${chainId}`,
domain: location.origin, // the requesting site
context: "Permit2: unlimited USDC allowance to spender 0x…",
interaction: { type: "permit_signature", unlimited: true },
}),
});
if (res.status !== 200) return showNotVerified(res.status); // 402 = payment not settled: never an all-clear
const v = await res.json();
if (!v.checked) return showNotVerified(); // fail-closed, never an all-clear
if (v.tier === "high" || v.tier === "critical") warnOrBlock(v);
| Tier | UX |
|---|---|
low | no warning; optional "checked" badge |
medium | amber: "Some signals suggest caution" |
high | red: "We recommend you do not proceed" |
critical | hard block with override; show the categories and evidence |
Every evaluation is paid; there is no free tier.
Prepaid credits (recommended):
POST /v1/credits {"amount_usd": 1} returns a 402 for $1.00 on any network. Pay it with any x402 client and the response carries a token (x402c_…, shown once) and its balance. Packs run from $0.10 to $100.Authorization: Bearer x402c_… with /v1/risk-check. Each check costs $0.001 ($0.005 when a transaction is simulated), debited atomically.GET /v1/credits with the token returns the balance. POST /v1/credits with the token tops it up.Per call:
Price by payment network (the 402 lists every option): Base $0.0035, Solana $0.002, Sei $0.002, Avalanche $0.001, Monad $0.001, Polygon $0.007, Arbitrum $0.009.
A request whose transaction is simulated costs $0.005, or the network's price if that is higher. The simulated price covers the simulation, the classification of every recipient and spender, and code fingerprints through delegations and proxies. It is charged only on chains where simulation runs.
A batch is billed per item.
Why the prices differ: every x402 payment is an on-chain settlement, and its cost is ours. PayAI settles EVM payments with EIP-3009, which any wallet can pay gaslessly, and bills us the network's gas + 30% per settlement (about $0.0023 on Base). Dexter bills nothing, but on EVM networks it settles only through Permit2, which most payers' wallets cannot use without an on-chain approval. Coinbase CDP settles with EIP-3009 too, at $0.001 per settlement after 1,000 free a month, so it takes the EVM networks where it is cheapest.
Routing: each network settles through the facilitator any payer can pay through, and among those the cheapest to us:
/status shows each network's facilitator, transfer method, fee and margin live. It also lists each facilitator's health and published signers, so anyone can check on-chain who settled a payment.
Settlement: USDC via x402 v2 (PAYMENT-SIGNATURE), mainnet only: Base, Polygon, Arbitrum, Avalanche, Monad, Sei and Solana. The x402 "exact" scheme is gasless for the payer, so USDC alone is enough.
An unpaid request gets 402 with the accepted options in PAYMENT-REQUIRED. Any x402 client pays and retries.
Invalid input is rejected (422/413) before anything is priced.
Release after settlement: the attestation is returned only once the payment settles. If the evaluation cannot be produced, nothing is settled (503, no charge).
One payment, one evaluation: a payment is claimed once, when it verifies. A copy of the same PAYMENT-SIGNATURE, sent at the same time or later, gets 409 payment_already_used.
The payer is screened: a paying wallet on the OFAC SDN list gets 403 payer_sanctioned, and nothing is charged.
HTTPS only: a plain-HTTP API call gets 403, before its body or token is read.
import { createClient } from "@x402check/client";
import { x402Client, wrapFetchWithPayment } from "@x402/fetch";
import { ExactEvmScheme } from "@x402/evm/exact/client";
import { privateKeyToAccount } from "viem/accounts";
const payer = new x402Client();
payer.register("eip155:*", new ExactEvmScheme(privateKeyToAccount(process.env.PAYER_KEY as `0x${string}`)));
payer.setSpendControls({ maxAmountPerPayment: "$1" });
// Once: buy credits (one x402 payment). Store the token like a password.
const { token } = await createClient({ fetch: wrapFetchWithPayment(fetch, payer) }).buyCredits(1);
// Every check after that: $0.001 from the balance, no payment round trip.
const x402check = createClient({ creditToken: token });
const verdict = await x402check.check({ wallet: "0x…", chain: "base" });
// Or pay per call instead: createClient({ fetch: wrapFetchWithPayment(fetch, payer) }).
request ─► validate (422 names the field) ─► credits debit, or x402 payment (per item) ─► Provider
│
deterministic, provider-side ──────────────────────────────────────┤
OFAC SDN screen ── listed? ──► score 0 · critical (no model call)│
domain analysis (PSL, homoglyph, typosquat, lure) │
threat feeds (MetaMask + OFAC refreshed daily, ScamSniffer KV) │
on-chain facts + code fingerprints (JSON-RPC) │
transaction simulation (eth_simulateV1) + contract verification │
model ─ Jev typed questions over provider checks + context ────────┤
code ─ weights, deterministic caps, tiers (src/scoring.ts) ───────┤
▼
settle payment (per call) ─► release ES256 attestation: checks · asserted · payment · jti
Source layout:
src/: provider, validation, enrichment, simulation, code fingerprints, scoring and JWS.deploy/: the Cloudflare Worker: the x402 paywall and pricing, facilitator routing, feed refresh and /status. See deploy/README.md.packages/: the TypeScript SDK (client) and the MCP server (mcp).snap/: the MetaMask Snap.eval/: evaluation layers and production probes.scripts/: data refresh, the feeds publisher and the verifier.docs/: METHODOLOGY, EVIDENCE, STRATEGY.| What | Result |
|---|---|
| Single-use payments (v0.6.0, production): three copies of one payment sent at once | one evaluated and settled, two refused (409); a later copy refused too |
| Kit watch, Ethereum, a 24 h backfill: addresses flagged (6,232 poisoning look-alikes, 575 wallets delegated to sweepers or forwarders, 24 destinations) | 6,831, none of them on ScamSniffer's list, which publishes with a 7-day delay: lead time not yet measured |
| Kit watch: sampled poisoning look-alikes confirmed by a victim's history (lower bound) | 27/37 (73%) |
| Kit watch: new contracts matching an old drainer kit (Ethereum 24 h + Base 6 h, from the backfill's logs, not a tracked report) | 0/2,966: drainer infrastructure moved to EIP-7702 |
| Code sets on held-out legitimate code (verified contracts + callees) | Before the v0.4 collision gate, the v0.4 kit families matched 16/2,500 held-out contracts on Ethereum; the v0.3 production Forta set matched exchange deposit fleets (Luno, Poloniex, BitGo) that Forta labels as phishing. Found and fixed. After the gate, on a second held-out set: 1 match in 1,737 + 0 in 2,935 (Ethereum + Base), and that match was a real, unlisted drainer on our own review |
| PayAI shadow: 7 days of PayAI-settled payments on Base, deterministic layers | 3,132 payments, 207 payees, 0 flagged; $3.13 to check them all |
| OFAC SDN addresses (external labels) | 24/24 critical |
| MetaMask-listed phishing domains · ScamSniffer drainer addresses | 40/40 · 30/30 |
| Drainer permits, drainer feed switched off (approval-to-EOA rule) | 27/30 |
| Simulation: real drainer transactions that still move assets at the latest block | 18/25 flagged (72%), all as hidden recipients |
| Simulation: real transactions to 19 well-known contracts | 0/84 flagged |
| Code fingerprints: listed drainer contracts matched by earlier kits' code, at creation time | 40/82 (Ethereum and Base; 43/100 in v0.3 on Ethereum only) |
| Plain transfers to unlisted drainers | 0/30: not detectable from the address alone, unless the kit watch has seen the wallet |
| Unlisted phishing domains without a feed | 0–4/60 across four samples: feeds do the heavy lifting |
| Well-known contracts and top dApp domains | 0 false positives (0/22, 0/40) |
| Tranco top 200k, deterministic rules | 22 capped (0.011%): 20 on MetaMask's own list, 2 crypto look-alikes |
| Risky cases with an attacker-written context | 20/100 (only look-alike domains) |
| Injected instructions passed as raw agent content | 40/40 |
| Signing guard (v0.6.0): real drainer transactions that still move the victim's assets, refused before the key signs (ScamSniffer feed off) | 22/25 (88%; by contract 10/11): 18 by simulation, 4 by drainer code; the 3 misses are one contract · legitimate: 0/49 that move assets and 0/84 that execute refused; 1/228 in all (a reverting transaction too large to simulate) |
| Payments in production: a check paid per call on Base, and one paid from prepaid credits | $0.0035, 2.7–4.7 s end to end (single samples: PayAI, Coinbase CDP, CDP on v0.6.0) · $0.001, 0.5–0.8 s, with no settlement per check |
| Production, every evaluation paid (settled in USDC on Base, or from credits bought that way) | 53/53 correct and 53/53 attestations verified · security:v2 12/12 (re-run on v0.5) · security:v3 8/8 · security:v4 7/7 · security:v5 9/9, 11/11 through Coinbase CDP (v0.5.1), and 11/11 on v0.6.0 |
Full methodology, confidence intervals and what each number does not show: docs/EVIDENCE.md. How each verdict is formed, with every cap: docs/METHODOLOGY.md. Earlier evidence documents are kept as historical records with correction notes.
npm install
npm test # provider unit tests
npm run typecheck # root + deploy + scripts + snap
AI_GATEWAY_API_KEY=... npm start # :8799 local dev server, no paywall (or TYPESAFE_API_KEY=...)
curl localhost:8799/.well-known/risk-check.json
npm run eval:suite -- --seed 200 # full evaluation (~$0.15 of model calls)
Worker: npm run dev:worker, or wrangler dev --local in deploy/. See deploy/README.md for secrets, feeds, deploy and rollback.
@x402check/client is a typed TypeScript client with zero runtime dependencies. It runs on Node ≥ 20, browsers, Cloudflare Workers, Deno and Bun.
verifyAttestation checks the signature against the issuer's did:web key and binds it to the request you made, including request_hash.interpret applies the fail-closed policy. Its verdicts come from the signed claims only, never from the unsigned body.guardAccount (@x402check/client/guard) makes the check enforced, not advisory. It wraps the account an agent signs with, and every transaction, permit, order, x402 payment or EIP-7702 delegation is signed only after a verified allow bound to that exact request. Otherwise it throws, and the key never signs. The exceptions are stated: an x402 payment of up to $0.25 to x402check's own pay_to (paying for a check) is not checked; a request with no counterparty and nothing to simulate (e.g. a zero-value deployment) is signed as inert; and a warn is signed when your onWarn approves it. See the signing guard.@x402check/mcp is an MCP server for any agent (Claude Code, Claude Desktop, other MCP clients), with the tools x402check_check, x402check_pay, x402check_verify_attestation and x402check_methodology.
x402check_pay fetches an x402 resource and pays only after x402check clears the exact payee, right before signing. A warn goes to the user in the client, never to the agent.X402CHECK_CREDIT_TOKEN) or itself via x402 (USDC on Base, gasless for the payer), with a per-payment cap and a total budget. Both secrets are redacted from every output.# with prepaid credits ($0.001 a check, no payment round trip):
claude mcp add x402check -e X402CHECK_CREDIT_TOKEN=x402c_… -- npx -y @x402check/mcp
# or paying per call from a dedicated wallet with a small USDC balance on Base:
claude mcp add x402check -e X402CHECK_PAYER_KEY=0x… -e X402CHECK_BUDGET_USD=1 -- npx -y @x402check/mcp
Both packages are on npm:
The MCP server is also in the official MCP Registry as io.github.caiovicentino/x402check.
Discovery: agents and their developers can find x402check in three catalogs.
/v1/risk-check and its batch endpoint, with the input schema, a callable example and the price on each network (GET https://api.cdp.coinbase.com/platform/v2/x402/discovery/resources)./openapi.json. That document declares each paid operation's price range, schemas and agent guidance.io.github.caiovicentino/x402check (npm @x402check/mcp).Opening an endpoint in a browser returns an example request and the prices.
snap/ has onTransaction / onSignature insights that decode the request locally and show the real counterparty, the amounts (including UNLIMITED approvals) and local danger findings.
Every check is paid, and this Snap version cannot pay yet. So 0.3.0 sends nothing to x402check.xyz and has no network permission. Every insight says "NOT verified by x402check" and never shows an all-clear.
The paid mode is complete and tested behind a single flag (src/config.ts), ready for when wallet-side payment exists. It checks the counterparty, simulates the transaction ("You send 1.5 ETH → 0x… (wallet)"), and renders the signed verdict with its evidence and warnings for hidden recipients and known drainer code.
Supported decoding:
personal_sign messages, decoded to text.On install and on update it shows a disclosure that states exactly what happens. In this version nothing is sent. It stores only which disclosure you have seen.
cd snap && npm install && npm test # builds, then 322 tests (285 run; paid-mode scenarios also run in Node) incl. the built bundle in SES
npx mm-snap serve # then wallet_requestSnaps "local:http://localhost:8062" in MetaMask Flask
The Snap is not yet published to npm nor allowlisted by MetaMask, so there is no one-click install in regular MetaMask yet.
What a check sends where, so you can decide what to put in a request:
context) and the provider's own findings. Before that, the server redacts private keys, seed phrases and x402check credit tokens from context. Nothing else is redacted. We have not yet confirmed the vendor's retention terms, so leave secrets and personal data out of context.sub, payment, interaction, aud) and hashes of the request (input_hash, request_hash), not the context itself.Code is MIT. Data sources:
See THIRD_PARTY_NOTICES.md. OFAC and MetaMask are refreshed daily by .github/workflows/feeds.yml and swapped in at runtime after verification. /status shows the versions in use. Manual refresh: npm run ofac:update, npm run feeds:update.
The full roadmap is in docs/STRATEGY.md.
upto payment schemes, to spread settlement gas when facilitators stop sponsoring it.kids shipped in v0.6.0: a next key is published before it signs.)decision_provider integration (issue #682); AP2 RiskPayload once upstream stabilizes.Source-derived launch command. Check the maintainer’s required arguments and credentials before running:
npx -y @x402check/mcpMerge this template into ~/Library/Application Support/Claude/claude_desktop_config.json. Keep existing servers. Add any arguments, credentials, and permissions required by the maintainer; this template has not been install-tested.
{
"mcpServers": {
"io-github-caiovicentino-x402check": {
"command": "npx",
"args": [
"-y",
"@x402check/mcp"
]
}
}
}Restart Claude Desktop completely for changes to take effect. Confirm the server appears connected in the client’s tool list, then try a read-only example from its documentation.
Claude Desktop setup referencex402check works with any MCP-compatible client. Copy the config snippet from the Configuration section above and add it to the file shown for your client, then restart the application.
~/Library/Application Support/Claude/claude_desktop_config.jsonRestart Claude Desktop completely for changes to take effect.~/.cursor/mcp.jsonRestart Cursor for changes to take effect..vscode/mcp.jsonReload VS Code window for changes to take effect.~/.codeium/windsurf/mcp_config.jsonRestart Windsurf for changes to take effect..mcp.jsonSave at the project root, then start Claude Code in that project and review the MCP server approval prompt. Keep real credentials out of shared files.