Skip to main content
Glama

x402-agent-mcp

Universal x402 MCP for AI agents — discover and pay for any x402 endpoint on Base, Solana or Casper.

Agents discover services, pay per call, and consume data — all autonomously. No API keys, no subscriptions, no signup. Just a wallet.

What It Does

Agent: "I need news data"
  → x402_search("news") → finds 2s.io
  → x402_describe("2s.io") → gets endpoint schema + price
  → x402_fetch("https://2s.io/api/news/search?q=x402&limit=3") → pays $0.003 USDC → gets results

The agent never sees wallets, private keys, or x402 protocol details. Just search, discover, fetch.

Related MCP server: obolpay-x402-mcp

Tools (9)

Tool

Cost

Description

x402_search

Free

Search x402 endpoints by keyword, category, or chain

x402_list_categories

Free

List all endpoint categories with counts

x402_describe

Free

Get detailed info for a specific service (paths, prices, schema)

x402_discover_url

Free

Discover any x402 service by URL via well-known files + auto-add to directory

x402_health

Free

Check if a service is live and responding with 402

x402_discover_urls

Free

Batch discover multiple x402 services in parallel

x402_crawl_directory

Free

Crawl x402scan.com to discover new x402 services and auto-add to directory

x402_check_payment

Free

Evaluate a prospective payment against policy — ALLOW / DENY / APPROVAL_REQUIRED with reason codes. Never pays.

x402_fetch

Endpoint price

Fetch any x402 endpoint — handles 402 payment on Base, Solana or Casper

Multi-Chain Support

Chain

Env var

Payment

Solana

SOLANA_PRIVATE_KEY

USDC via @x402/svm

Base

EVM_PRIVATE_KEY or BASE_PRIVATE_KEY

USDC via @x402/evm

Casper

CASPER_PRIVATE_KEY

wCSPR via @make-software/casper-x402

Chain is auto-detected from the 402 response. Override with chain parameter.

Casper

Casper endpoints advertise CAIP-2 networks casper:casper (mainnet) and casper:casper-test (testnet), and settle in wCSPR, a CEP-18 token with 9 decimals (motes). Amounts are handled as exact integer motes — a requirement with sub-mote precision is rejected rather than rounded.

Env var

Default

Description

CASPER_PRIVATE_KEY

Hex secret key, PEM file path, or PEM contents

CASPER_KEY_ALGORITHM

ed25519

ed25519 or secp256k1

CASPER_NETWORK

auto

Force casper:casper or casper:casper-test when a server offers both

CASPER_MAX_PAYMENT_PER_CALL

disabled

Maximum per authorization in decimal wCSPR (e.g. 1.5)

CASPER_MAX_DAILY_SPEND

disabled

Daily authorization budget in decimal wCSPR (e.g. 10)

Both budgets must be explicitly set and positive. No USD conversion is performed. Only the network-specific wCSPR package hashes from Casper Wallet Core are accepted. scheme: "exact" and x402 v2 are required. Forced-chain calls still probe payment requirements, and the SDK checks the actual requirements again before signing. Settlement is performed by the endpoint's facilitator; this client does not configure a separate facilitator.

x402_fetch({ url: "https://some-casper-endpoint.example/api", chain: "casper" })

Enabling the Casper leg

Before live paid Casper calls work, four prerequisites must be in place:

Prerequisite

How to satisfy it

Funded account key

Create a key with Casper Wallet or cspr.live and export the hex secret key or PEM. On testnet, request free CSPR from the Casper testnet faucet. On mainnet you need real CSPR from an exchange or the staking ecosystem.

wCSPR balance

Endpoints settle in wCSPR (CEP-18), not raw CSPR. On mainnet you may need to wrap CSPR to wCSPR via a supported contract interaction first; on testnet the faucet plus a testnet wCSPR mint may apply. The exact wrap/mint flow varies — confirm it with the endpoint operator.

Target endpoint

This client ships no Casper endpoint list, and the x402 directory currently lists none. You need the endpoint URL from the operator — ask the endpoint operator or the Casper team.

Mote budgets

Both CASPER_MAX_PAYMENT_PER_CALL and CASPER_MAX_DAILY_SPEND must be set and positive, or all paid Casper requests fail closed. This is deliberate safety design, not a bug.

Worked testnet .env (faucet-funded, small budgets — values are decimal wCSPR, converted to integer motes under the hood):

CASPER_PRIVATE_KEY=<hex-key-or-pem-path>
CASPER_NETWORK=casper:casper-test
CASPER_MAX_PAYMENT_PER_CALL=1
CASPER_MAX_DAILY_SPEND=5

Smoke test your first call:

x402_fetch({ url: "https://your-casper-endpoint.example/api", chain: "casper" })

Check the payment ledger for an entry with currency: "wCSPR" and an exact amount_motes string. Before the env vars are set, paid Casper calls return a NOT_CONFIGURED-style error; after, they sign and settle. An unset budget means no Casper signing happens at all.

Why fail-closed: if the key or either budget is unset, no Casper payment is ever signed — there is no silent fallback. Ambiguous failures retain their budget reservation (authorized, not settled), and spend stays bounded in native motes without any USD-conversion assumptions.

Spending Limits & Payment Logging

Env var

Default

Description

MAX_PAYMENT_PER_CALL

0.50

Reject any single call above this amount (USDC)

MAX_DAILY_SPEND

10.00

Reject after cumulative daily spend exceeded (USDC)

PAYMENT_LOG_PATH

./x402-payments.jsonl

Path to payment log file (gitignored)

X402_DIRECTORY_PATH

./endpoints.json

Path to the endpoint directory file (gitignored); set to isolate tests/sandboxes from the live directory

X402_INTENT_TTL_MS

60000

Payment-intent time-to-live in milliseconds (see Payment Intent Boundary); an expired intent can never be signed

Payments share one x402-payments.jsonl ledger with timestamp, URL, chain, amount, tx hash, and status. USDC entries use amount_usdc; Casper entries use currency: "wCSPR" and an exact amount_motes string. Base/Solana counters are tracked by chain and summed for the existing USD daily limit. Casper has an independent mote counter.

Casper reserves budget synchronously before signing to prevent concurrent overspending. Failed or ambiguous requests retain that reservation; it represents authorized spend, not confirmed settlement. Only one authorization is permitted per fetch. A server-provided settlement receipt is not independently verified on-chain. Payment response bodies/headers are size-bounded and Casper redirects are refused.

Counters are process-local and reset at UTC midnight or process restart. They are not a durable, multi-instance wallet limit.

Limitations — read before relying on these budgets

  • Per-process counters. Daily spend lives in the memory of one MCP process (rehydrated once from the ledger on the first budget check). It is never a wallet-level limit.

  • Multiple instances = separate budgets. Running two MCP processes gives each its own counter, so the real daily spend can reach N × MAX_DAILY_SPEND. Durable multi-instance enforcement requires an external store and is on the roadmap; until then, run one instance per budget scope.

  • The USDC daily cap can be overshot by in-flight concurrency. The guard checks MAX_DAILY_SPEND before paying and records spend only after settlement; the await points between the check and the log inside a paid fetch mean several in-flight requests can pass the same check. The synchronous check-then-log span itself is exact (locked by the concurrent-consumption test in src/payment-utils.rehydrate.test.ts), but cross-await atomicity must not be assumed.

  • Casper is the fail-closed equivalent class. Casper reserves budget synchronously before signing, so concurrent Casper calls cannot overspend, and an unset or invalid budget disables Casper payments entirely. Verified by src/casper/budget.test.ts: "daily reservations prevent concurrent callers overspending", "checks changed requirements at signing and blocks retries", "unset either Casper budget disables signing", "invalid, zero and negative budgets disable payment", and "rolls only the Casper counter at UTC day change".

Payment Policy Engine (Phase 1)

Every payment passes a deterministic policy gate before any payment code runs. The policy engine (in src/policy/) is deliberately small, pure (same inputs → same decision, always) and independent of payment mechanics: x402_fetch calls policyEngine.evaluate(context, budgetState) and refuses to pay unless the decision is ALLOW. The pre-existing budget guards stay in place as belt-and-braces inside the payment layer — the policy engine is the outer gate, not a replacement.

Agent request (x402_fetch or x402_check_payment)
   |
   v
Policy Engine  ← policy config + trust level + today's budget state
   |
   +-- DENY -------------> structured refusal, NO payment
   |
   +-- APPROVAL_REQUIRED -> refusal with that reason code (Phase 1: see below)
   |
   +-- ALLOW
          |
          v
     belt-and-braces budget checks (payment-utils / casper budget)
          |
          v
     payment execution (x402 protocol, unchanged)
          |
          v
     settlement receipt (server-attested — see Trust Model)

Decisions and reason codes

Decisions are exactly ALLOW, DENY, APPROVAL_REQUIRED. Every non-ALLOW result carries stable machine-readable reason codes — code against these, never against the human-readable message:

Reason code

Fires when

PAYMENTS_DISABLED

Global payments kill switch (payments.enabled: false)

REQUEST_LIMIT_EXCEEDED

Amount above the per-request cap (level override or global); also fails closed on non-finite/negative amounts

DAILY_LIMIT_EXCEEDED

Today's global spend + amount would exceed the daily cap

SERVICE_LIMIT_EXCEEDED

Today's spend for this service would exceed its per-service daily cap

CHAIN_NOT_ALLOWED

Chain not in the network allowlist

TOKEN_NOT_ALLOWED

Token not in the token allowlist

SERVICE_BLOCKED

Host is BLOCKED, or its trust level is configured to deny

UNKNOWN_SERVICE

Host is not in the directory while services.unknown is configured to deny

APPROVAL_REQUIRED

The trust level is configured to approval (Phase 1: treated as a refusal — see below)

CONFIG_INVALID

Policy configuration failed validation — the engine fails closed

RECIPIENT_NOT_ALLOWED

Rule 4.5 recipient gate (issue #26): the probed recipient is not on the effective allowlist (allowlist mode — fail-closed on an empty effective list or a missing/unusable probed recipient), or differs from the recorded baseline (change-detect mode)

Rules are evaluated in a fixed, documented order and reasons accumulate (all triggered codes are returned, not just the first). DENY outranks APPROVAL_REQUIRED outranks ALLOW. Cap boundaries match the inner payment guards exactly: > cap denies, reaching the cap exactly is allowed.

Trust levels

Derived from operator env allowlists plus directory provenance (the source metadata on directory entries). No reputation system.

Level

Derived from

Default behavior

BLOCKED

host listed in POLICY_BLOCKED_HOSTS (comma-separated)

always deny

TRUSTED

host listed in POLICY_TRUSTED_HOSTS (user-managed allowlist)

payable at global caps

DISCOVERED

host is a directory entry (source: "seed" or "discovery")

payable at global caps

UNKNOWN

host not in the directory

governed by services.unknown (default: allow — see the compat decision below)

Precedence is fail-closed: BLOCKED > TRUSTED > directory > UNKNOWN. Per-level configuration can tighten any level (deny, approval, or a lower maxPerRequest / per-service maxDaily).

Configuration

JSON via POLICY_CONFIG_PATH (no new dependencies), with X402_POLICY_* env overrides. A complete, commented, validated example lives in policy.example.json (usage notes: policy.example.README.md) — copy it, edit it, and point POLICY_CONFIG_PATH at it; node scripts/validate-policy-example.mjs proves it loads clean and behaves as documented. Precedence: MAX_PAYMENT_PER_CALL / MAX_DAILY_SPEND (the legacy defaults) < config file < env overrides.

{
  "payments": {
    "enabled": true,
    "maxPerRequest": 0.50,
    "maxDaily": 10.00
  },
  "services": {
    "unknown":    { "action": "allow" },
    "discovered": { "action": "allow" },
    "verified":   { "action": "allow" },
    "trusted":    { "action": "allow" },
    "blocked":    { "action": "deny" }
  },
  "networks": { "allowed": ["base", "solana", "casper"] },
  "tokens":   { "allowed": ["USDC", "wCSPR"] },
  "recipients": { "mode": "change-detect", "allowed": [], "perService": {}, "known": {} }
}

The example above is the behavior-compat default: non-directory hosts are payable at the global caps (services.unknown: allow — before the policy engine, directory membership played no role in the limit checks), and the recipient gate is inactive by construction (recipients defaults to change-detect with no recorded baselines — nothing to compare, so rule 4.5 never fires). Tightening is opt-in and never the default — for example, the following refuses every non-directory host and tightens directory-service caps (a copy-paste of the block above does NOT apply any of this):

{
  "services": {
    "unknown":    { "action": "deny" },
    "discovered": { "action": "allow", "maxPerRequest": 0.25, "maxDaily": 1.00 },
    "trusted":    { "action": "allow", "maxPerRequest": 5.00 }
  }
}

Recipients (issue #26). The recipients block gates who may be paid — rule 4.5 emits RECIPIENT_NOT_ALLOWED. Comparison happens on the normalized (canonical) recipient, chain-aware: EVM 0x… addresses are compared case-insensitively against their EIP-55-valid spelling (a wrong-checksum spelling is not repaired — it is unusable), Solana wallets as the canonical 32-byte base58 re-encoding, Casper payTo as 00 + 64 hex with an optional account-hash- prefix stripped. Formatting can therefore never bypass or break the gate. Two modes:

  • allowlist — active always, fail-closed. A payment is refused unless the probed recipient normalizes to an entry on the effective allowlist for the host: recipients.perService[host] replaces the global recipients.allowed list when present (keys are lowercase hostnames). An empty effective list denies every recipient, and a missing or unusable probed recipient is denied too — membership can never be proven.

  • change-detect — active only for a host with a recorded baseline. recipients.known maps a lowercase hostname to its expected recipient (e.g. "known": { "merchant.example": "00ab…" }); the payment is refused when the probed recipient differs from the baseline. With no baseline for the host nothing fires — nothing to compare. This is the compat default (empty known ⇒ inactive).

Compat default block:

{
  "recipients": {
    "mode": "change-detect",
    "allowed": [],
    "perService": {},
    "known": {}
  }
}

Tightening example — only ever pay one global recipient, except one host which pays only its own:

{
  "recipients": {
    "mode": "allowlist",
    "allowed": ["0x833589fcd6edb6e08f4c7c32d4f71b54bda02913"],
    "perService": {
      "trusted-merchant.example": ["0x2222222222222222222222222222222222222222"]
    },
    "known": {}
  }
}

The recipients block is file-only. A per-host map cannot be expressed cleanly as a flat env var, so unlike the sections above there is deliberately no X402_POLICY_* override for it (the other sections keep their knobs, below). Unknown keys inside recipients are errors (typo protection), like everywhere else. In allowlist mode, x402_fetch passes the payTo address from the 402 challenge into the gate for both the USD legs (Base/Solana) and the Casper leg, so the recipient is validated before any payment machinery runs; the payment intent then binds exactly the validated value.

Env overrides (each fails closed on a malformed value — never silently ignored):

Env var

Overrides

X402_POLICY_PAYMENTS_ENABLED

true / false (exact strings)

X402_POLICY_MAX_PER_REQUEST

global per-request cap

X402_POLICY_MAX_DAILY

global daily cap

X402_POLICY_NETWORKS

comma-separated network allowlist

X402_POLICY_TOKENS

comma-separated token allowlist

X402_POLICY_SERVICE_<LEVEL>

allow / deny / approval for unknown|discovered|verified|trusted|blocked

X402_POLICY_SERVICE_<LEVEL>_MAX_PER_REQUEST / _MAX_DAILY

per-level caps

POLICY_TRUSTED_HOSTS / POLICY_BLOCKED_HOSTS

comma-separated hostnames for the TRUSTED / BLOCKED trust levels

Fail closed. A config file that is unreadable (e.g. revoked permissions — any read error other than a missing file), malformed JSON, wrong types, missing critical fields (payments is required), unrecognized keys (typo protection — a misspelled cap is an error, not a silent no-op), or unparseable env values puts the engine into a payments-disabled error state: evaluate() returns DENY with CONFIG_INVALID + PAYMENTS_DISABLED for every request. A missing file at POLICY_CONFIG_PATH (ENOENT) loads the default policy (fail-closed applies to unusable content, not to an absent file). The policy layer never weakens a malformed setting into a permissive one.

The two explicit Phase 1 decisions

  1. APPROVAL_REQUIRED is a refusal in Phase 1. This MCP runs over stdio and has no human-approval channel; returning a decision the agent could treat as "pending" would be worse than refusing. The engine returns APPROVAL_REQUIRED with that reason code preserved, and x402_fetch refuses to pay — the issue's fail-closed principle applied to the approval gap.

  2. The default policy reproduces pre-policy behavior exactly (the explicit backwards-compatibility decision the issue demands — made explicit here rather than silently weakening the safety model): payments enabled, caps from MAX_PAYMENT_PER_CALL (default $0.50) / MAX_DAILY_SPEND (default $10.00), networks [base, solana, casper], tokens [USDC, wCSPR], every directory service payable at the global caps, services.unknown: allow — because today any host is payable at the global caps (directory membership plays no role in the pre-policy gate) — and the recipient gate inactive (recipients defaults to change-detect with no baselines). The unchanged test suite is the proof of that compatibility. Tightening — e.g. services.unknown: "deny" so non-directory hosts are refused, or a recipient allowlist — is opt-in via config. The zero-behavior-change claim is test-locked: the full pre-existing suite passes unchanged under the default policy, and the fetch integration tests assert both the refusal path and the untouched default path.

Inspecting a payment without paying

x402_check_payment evaluates a prospective payment and returns the structured decision — it never touches payment code paths (locked by a zero-payment-calls test):

{
  "decision": "DENY",
  "service": "example.com",
  "amount": "2.50",
  "currency": "USDC",
  "chain": "base",
  "trust_level": "DISCOVERED",
  "reasons": [
    { "code": "SERVICE_LIMIT_EXCEEDED", "message": "Service example.com daily limit is $1.00 and $0.27 remains" }
  ],
  "limits": { "trustLevel": "DISCOVERED", "maxPerRequest": 0.5, "maxDaily": 10, "perServiceDaily": 1.0 },
  "note": "Inspection only — no payment was attempted. Resolve DENY reasons before calling x402_fetch."
}

Per-service daily spend is tracked in the same payment ledger (grouped by URL hostname, rehydrated like the global counter — no parallel state). Per-service caps are enforced for USD-settled chains (Base/Solana); Casper remains governed by its mote budgets (CASPER_MAX_PAYMENT_PER_CALL / CASPER_MAX_DAILY_SPEND) inside the payment layer.

x402_check_payment also accepts an optional recipient argument (issue #26) — the payTo address from the 402 challenge — so the recipient gate can be checked before fetching. In allowlist mode the argument is required (without it the gate denies); in change-detect mode it is compared against the recorded baseline. The response echoes recipient verbatim plus recipient_normalized, the canonical form rule 4.5 compares (null when no recipient was supplied or it is not a valid address for the chain).

Deliberately not in Phase 1 (future extensions, tracked separately in issue #19): approval workflows, price-change/anomaly detection, payment velocity limits, circuit breakers, transaction simulation, response size limits, untrusted-data labelling, prompt-injection-aware response handling, and a persistent audit ledger. (Recipient allowlisting — formerly on this list — shipped as rule 4.5, issue #26.)

Payment Intent Boundary (issue #25)

Between the policy decision and the wallet there is a second, internal authorisation boundary. The layers have distinct jobs — policy engine: "is this permitted?"; payment intent: "exactly what was authorised"; executor: "how it is executed" on Base, Solana or Casper. After the policy gate returns ALLOW, x402_fetch binds the evaluated offer (service, URL, chain, CAIP-2 network, token, asset, integer atomic amount, recipient, scheme) into a short-lived, immutable payment intent, and the payment layer can only sign through an intent-validating executor:

LLM input (URL/method/body — no payment parameters)
   |
   v
Policy decision (ALLOW / DENY / APPROVAL_REQUIRED)
   |
   +-- not ALLOW -----------> structured refusal, NO intent, NO payment
   |
   v
Authorised payment intent  (in-memory registry; paramsHash +
   |                        policyDecisionId bound at creation;
   |                        TTL-bounded, one-shot)
   v
Validated executor         (executeGuarded: validate + beginAttempt,
   |                        enforcement hook on the x402 client)
   v
Wallet / signing           (onBeforePaymentCreation: final check
                            immediately BEFORE payload is signed)

The enforcement point is the x402 SDK's onBeforePaymentCreation hook — exactly where parameters become a signature. Any drift between the authorised intent and the offer the SDK actually selected (amount, recipient, asset, network, scheme) aborts with OFFER_MISMATCH before a signature exists. The boundary is at signing/payload creation, never at the HTTP request: an endpoint that answers the paid request without a 402 passes through unchanged, while any attempt to charge is verified against the intent.

Six security properties:

  1. Immutable after authorisation. The registry keeps a frozen record; paramsHash (sha256 over the security-sensitive fields in fixed canonical order) and policyDecisionId (sha256 of decision:paramsHash) are recomputed and deep-compared at validation. Tampering any field ⇒ PARAM_MISMATCH.

  2. Policy binding. Only an ALLOW decision can mint an executable intent; DENY / APPROVAL_REQUIREDNOT_AUTHORISED. The engine itself is untouched (the intent layer never re-implements policy rules).

  3. Expiry. Intents live for X402_INTENT_TTL_MS (default 60 s, invalid values fall back to the default). After that, validation ⇒ EXPIRED.

  4. Replay protection. One authorisation per intent: issued → in-flight → consumed; a second execution or consume ⇒ ALREADY_USED.

  5. Fail closed. Unknown, malformed, mismatched, expired or replayed ⇒ a structured reason code (NOT_AUTHORISED / MALFORMED / UNKNOWN_INTENT / PARAM_MISMATCH / EXPIRED / ALREADY_USED / OFFER_MISMATCH / AMOUNT_UNBINDABLE), never a guess, never a default price. Money is integer atomic units (amountAtomic); the USD figure policy evaluated is informational only and never the binding.

  6. No bypass. A structural test (src/payment-intent/no-bypass.test.ts) locks wrapFetchWithPayment( / new x402Client( to the sanctioned call sites; any new payment path added elsewhere fails the suite.

The intent registry is in-memory per process — the same limitation class as the budget counters (see Limitations above): intents cannot be forged from the MCP tool surface (the LLM never sees intents), and a restart simply invalidates all of them.

Deliberate tightening (AMOUNT_UNBINDABLE). Previously, when the probe offer had no parseable amount, x402_fetch fell back to a $0.01 estimate for the policy/limit checks and the real amount was only discovered when the SDK built the payload. Now: an offer that cannot be bound to a payment intent can never be paid — the payment-payload creation aborts before any signing (INTENT_UNAUTHORISED). Unpaid/non-402 responses still pass through unchanged, so endpoints that do not actually charge are unaffected. With a forced chain of base/solana the same single free 402 probe still runs to observe the offer (the probe never replaces the forced chain and never refuses the HTTP request), so a well-formed forced-chain request binds and pays exactly like the auto-detected one; the blocking rule applies only when no bindable offer was observed at all (an unrecognised forced chain, or a probe that legitimately cannot yield one). The policy's USD estimate for such offers remains the informational fallback for the policy evaluation itself.

Structured refusals. Intent refusals reuse the #19 refusal shape keys (error, url, chain, estimated_cost_usdc, daily_spent_usdc, max_per_call, max_daily, policy_decision, reasons[{code, message}]) with primary reason code INTENT_UNAUTHORISED plus the specific intent code.

The boundary is internal to the server: no new MCP tool, no new tool argument, and nothing about intents (or wallets) is exposed to the agent.

Trust Model

Settlement receipts are server-attested, not independently verified. When a paid fetch settles, the seller's PAYMENT-RESPONSE header is decoded and surfaced as payment_receipt in the tool output. That receipt comes from the endpoint operator's server: it is an attestation, not proof. Every paid-fetch output therefore also carries receipt_verified: false and receipt_note: "server-provided, not independently verified on-chain" so the agent never mistakes an attestation for an on-chain fact. A malformed or hostile receipt is surfaced as-is (or absent) rather than treated as payment confirmation.

Independent on-chain verification is roadmap work — it requires a chain client per network (Base, Solana, Casper) to confirm the settlement transaction. Until then, treat receipt_verified: false as the ground truth: if a payment's settlement matters to you, verify the tx_hash / receipt yourself on the relevant chain explorer.

The other trust boundaries are explicit: the discovery fetcher refuses private/loopback/link-local addresses before any request and never follows redirects (see x402_discover_url), payment paths refuse redirects and size-bound all response bodies and payment headers, and the directory is written atomically with corrupt-file quarantine rather than silent overwrite.

Quick Start

1. Install

git clone https://github.com/dchu3/x402-agent-mcp.git
cd x402-agent-mcp
npm install
npm run build

2. Configure

# .env
SOLANA_PRIVATE_KEY=your-base58-solana-key
EVM_PRIVATE_KEY=your-hex-base-key
CASPER_PRIVATE_KEY=your-hex-casper-key-or-pem-path
SOLANA_RPC_URL=https://mainnet.helius-rpc.com/?api-key=your-key
BASE_RPC_URL=https://mainnet.base.org
MAX_PAYMENT_PER_CALL=0.50
MAX_DAILY_SPEND=10.00

You only need the key for chains you want to pay on. Solana-only? Just set SOLANA_PRIVATE_KEY.

3. Connect to Your Agent

Hermes Agent

hermes config set mcp_servers.x402.command "node"
hermes config set mcp_servers.x402.args '["/path/to/x402-agent-mcp/dist/index.js"]'
hermes config set mcp_servers.x402.enabled true

# Set env vars
python3 -c "
import yaml
with open('$HOME/.hermes/config.yaml') as f:
    config = yaml.safe_load(f)
config['mcp_servers']['x402']['env'] = {
    'SOLANA_PRIVATE_KEY': 'your-base58-key',
    'EVM_PRIVATE_KEY': 'your-hex-key',
}
with open('$HOME/.hermes/config.yaml', 'w') as f:
    yaml.dump(config, f, default_flow_style=False, allow_unicode=True)
"

hermes gateway restart
hermes mcp test x402

Claude Desktop

{
  "mcpServers": {
    "x402": {
      "command": "node",
      "args": ["/path/to/x402-agent-mcp/dist/index.js"],
      "env": {
        "SOLANA_PRIVATE_KEY": "your-base58-key",
        "EVM_PRIVATE_KEY": "your-hex-key"
      }
    }
  }
}

Usage Examples

Search for endpoints

x402_search({ query: "news" })
x402_search({ category: "social" })
x402_search({ chain: "solana" })

Discover a service by URL

x402_discover_url({ url: "https://svm402.com" })

Batch discover multiple URLs

x402_discover_urls({ urls: ["https://svm402.com", "https://2s.io"] })

Crawl x402scan for new services

x402_crawl_directory({ max_results: 20 })

Check if a service is live

x402_health({ name: "svm402" })
x402_health({ url: "https://svm402.com" })

Fetch an x402 endpoint

x402_fetch({
  url: "https://svm402.com/analyze",
  method: "POST",
  body: '{"address": "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263"}'
})
x402_fetch({
  url: "https://2s.io/api/news/search?q=x402&limit=3",
  chain: "solana"
})

Endpoint Directory

The endpoints.json file contains known x402 endpoints. It is gitignored — each installation builds its own directory.

  • endpoints.example.json is shipped as a template (empty, with categories)

  • On first run, the MCP loads the template and populates from there

  • x402_discover_url auto-adds new services when discovered

  • x402_crawl_directory scrapes x402scan.com for new services

  • Only true x402 endpoints (no API keys) are included

  • Set X402_DIRECTORY_PATH to point the directory elsewhere (consulted first by all reads/writes) — useful for tests and sandboxed installs so the live endpoints.json is never modified

To bootstrap a fresh install:

cp endpoints.example.json endpoints.json
# Then run x402_crawl_directory to populate

Directory entries carry a source field for provenance: "seed" marks the operator-curated baseline, "discovery" marks entries added by x402_crawl_directory. This is the baseline for the trust-level classification planned in issue #19.

Automated Directory Refresh

The endpoint directory stays fresh by running x402_crawl_directory on a schedule. Here's how to set it up in popular agent frameworks:

Hermes Agent (cron job)

Hermes supports scheduled cron jobs that can run the crawler automatically:

# Create a weekly cron job (every Monday at 03:00 UTC)
hermes cron create \
  --name "x402 Crawl Directory" \
  --schedule "0 3 * * 1" \
  --toolsets terminal \
  --deliver local \
  --prompt 'Run the x402-agent-mcp crawler to discover new endpoints from x402scan.com:

cd /path/to/x402-agent-mcp && echo "{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2024-11-05\",\"capabilities\":{},\"clientInfo\":{\"name\":\"hermes-cron\",\"version\":\"1.0\"}}}
{\"jsonrpc\":\"2.0\",\"method\":\"notifications/initialized\"}
{\"jsonrpc\":\"2.0\",\"id\":2,\"method\":\"tools/call\",\"params\":{\"name\":\"x402_crawl_directory\",\"arguments\":{\"max_results\":20}}}" | timeout 120 node dist/index.js 2>/dev/null | tail -1

Parse the JSON response and report how many new services were added. If none found, say "No new x402 endpoints discovered this week."'

The --deliver local flag keeps the cron job silent (no chat messages) — it just updates endpoints.json in the background.

Other Agents (crontab)

For agents without built-in scheduling, use system crontab:

# Add to crontab — runs every Monday at 03:00
crontab -e

# Add this line:
0 3 * * 1 cd /path/to/x402-agent-mcp && echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"cron","version":"1.0"}}}
{"jsonrpc":"2.0","method":"notifications/initialized"}
{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"x402_crawl_directory","arguments":{"max_results":20}}}' | timeout 120 node dist/index.js >> /var/log/x402-crawl.log 2>&1

Custom Scripts

The crawler can also be called programmatically:

import { registerCrawlX402ScanTool } from "./tools/crawl-directory.js";
// Or call the MCP via stdio — see usage examples above

Roadmap

Explicitly deferred — tracked here so the boundary is visible, not forgotten:

  • Discovery freshness & trust levels (issue #18.2 detail) — the directory records provenance (source: "seed" / source: "discovery") but does not track freshness or verification state. Enforcement of freshness, trust levels and per-service policy belongs to the #19 policy engine (its trust-level model consumes exactly this metadata) and is deliberately not implemented ad hoc here.

  • Self-describing service manifests (issue #18.7) — machine-readable service metadata is an ecosystem-wide direction: services must publish manifests before clients can consume them. Deferred to the ecosystem roadmap; x402_discover_url already consumes /.well-known/ai-catalog.json and /.well-known/x402 where present.

  • Multi-instance budget durability — enforcing one budget across several MCP processes needs an external spend store (see Limitations under Spending Limits).

  • On-chain settlement-receipt verification — independently verifying receipts needs a chain client per network (see Trust Model).

  • Persistent audit ledger for payments/intents — durable, multi-instance audit trails (payment intents are process-local by design, like the budget counters); needs an external store and is deferred with the multi-instance budget work.

Disclaimer

This software is experimental and provided "as is", without warranty of any kind. Use at your own risk.

This software initiates real cryptocurrency transactions that are irreversible.

Tech Stack

License

MIT

Available Tools

8 tools
x402_crawl_directoryA

Crawl x402scan.com resources page to discover new x402 endpoints. Extracts service URLs, probes each for x402 support, and auto-adds confirmed services to the local directory. Returns summary of newly discovered services.

ParametersJSON Schema
NameRequiredDescriptionDefault
max_resultsNoMaximum number of new services to add (default: 20)

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full behavioral burden and largely succeeds: it discloses network probing and the key side effect of 'auto-adds confirmed services to the local directory.' It does not mention rate limits, idempotency, or behavior toward already-known services, so it is not a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, each earning its place: the target and purpose, the execution steps, and the return output. There is no filler, repetition, or irrelevant detail.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with no output schema and no annotations, the return contract is only described as a 'summary of newly discovered services' — enough to know the general kind of result but not its shape or contents. The tool's effect on existing directory entries and behavior at max_results is also left implicit.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The single parameter max_results is already fully described in the input schema with a default of 20, and the description adds no extra semantics about how the limit affects crawling or discovery. This aligns with the baseline for high schema_description_coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description identifies a concrete action, target, and outcome: 'Crawl x402scan.com resources page to discover new x402 endpoints.' It also details the process (extract URLs, probe for support, auto-add confirmed services) and returns a summary, which clearly differentiates it from the sibling discovery/search tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The intended use is clear: run it to discover and auto-add new x402 endpoints found on the resources page. It does not explicitly state when not to use it or name alternatives, but the context is unambiguous enough for an agent to select it over the other discovery/search tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

x402_describeB

Get detailed information about a specific x402 endpoint, including all available paths, methods, prices, and well-known discovery files.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesService name from x402_search results (e.g. 'svm402', 'Tavily')

TDQS

B3.4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the burden of explaining behavior. It does convey what information is returned ('paths, methods, prices, and well-known discovery files'), which is useful. However, it does not explicitly state that the operation is read-only, whether it performs network requests, or what happens on failure, leaving some behavioral ambiguity.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, front-loaded sentence that immediately states the tool's purpose and quickly lists the main output categories. Every phrase contributes meaning, and there is no wasted or redundant wording.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with one well-documented parameter and no output schema, the description gives a reasonable overview of what the tool returns. It is likely enough for an agent to decide whether to call it and what to expect, though it stops short of detailing exact response structure or edge cases.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema already documents the single 'name' parameter with 100% coverage, including guidance that it should come from x402_search results. The description adds minimal semantic value beyond the schema, so the baseline of 3 is appropriate; there is no parameter documentation gap but also no extra clarification.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool retrieves detailed information about a specific x402 endpoint and enumerates the key content: paths, methods, prices, and well-known discovery files. It is specific about the verb and resource, though it doesn't explicitly differentiate itself from sibling tools like x402_discover_urls or x402_fetch.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no explicit guidance on when to use this tool versus alternatives such as x402_search, x402_discover_urls, or x402_fetch. The input schema's mention of 'Service name from x402_search results' implies a workflow, but the description itself does not state when this tool is appropriate or when another sibling should be used.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

x402_discover_urlA

Discover any x402 service by URL. Fetches /.well-known/x402 (payment details), /.well-known/ai-catalog.json (capabilities), and /llms.txt (agent summary). Returns a unified discovery object with chains, wallet, endpoints, and prices.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYesBase URL of the service to discover (e.g. https://svm402.com)

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the behavioral burden and adequately discloses that the tool performs network fetches to three specific well-known paths and returns a unified discovery object. It does not detail error behavior, authentication, or failure cases, but the network-read nature is clear.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two tight sentences with no filler. It leads with the core action, lists the fetched endpoints, and summarizes the returned object, every sentence earning its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-parameter tool with no output schema, the description conveys the essential return fields (chains, wallet, endpoints, prices) and the discovery mechanism. It does not specify the exact output shape or failure behavior, but the tool is simple enough that this is a minor gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and the single url parameter is already documented with a description and example. The tool description adds no additional parameter semantics beyond restating that the URL is the service base URL, so baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb and resource: discover an x402 service by URL, and enumerates the exact well-known endpoints fetched. It is clear on its own but does not explicitly distinguish itself from the sibling x402_discover_urls, which may cover the plural/multi-URL case.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage: use this when you have a base URL and need discovery details such as chains, wallet, endpoints, and prices. It does not explicitly state when not to use it or mention alternative sibling tools, notably the similarly named x402_discover_urls.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

x402_discover_urlsA

Batch discover multiple x402 services in parallel. Provide a list of URLs, each is probed for /.well-known/x402 and ai-catalog.json. Returns a summary array.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlsYesArray of base URLs to discover (e.g. ["https://svm402.com", "https://2s.io"])

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure, and it delivers: it reveals the probing targets (/.well-known/x402 and ai-catalog.json), discloses that requests run in parallel (which has rate-limit and load implications the agent should know), and states the return shape is a summary array. Minor gaps remain — no disclosure of failure handling, malformed-URL behavior, or what the summary entries contain — but the core operational traits are honestly surfaced.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences totaling roughly 40 words, perfectly front-loaded with the core purpose. Each sentence earns its place: batch/parallel scope, probing targets, and return shape. There is zero filler, no repetition of schema content, and no buried critical information — the most important operational fact (parallel batch discovery) leads.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter tool with 100% schema coverage and no output schema, the description covers the essentials: what the tool does, how it operates (which endpoints it probes), and what it returns. The main omission is the contents of the 'summary array' — an agent doesn't know what fields or statuses to expect in the results — and there's no explicit pointer to the singular sibling. Both are minor given the low complexity, but they keep this from a 5.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%: the urls parameter has a description and concrete examples ('https://svm402.com', 'https://2s.io'). The description adds mild value by explaining what happens to each URL (it is probed for the two discovery files), which enriches the parameter's meaning slightly. No additional format, normalization, or constraint details are needed given the schema already handles it — baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb-resource-scope pairing: 'Batch discover multiple x402 services in parallel.' It goes further, specifying exactly what probing occurs (/.well-known/x402 and ai-catalog.json), which makes the tool's behavior concrete. The word 'Batch' and 'multiple... in parallel' clearly differentiate it from the singular sibling x402_discover_url without needing to open either schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage context is implied through 'Batch... multiple... in parallel' — an agent can infer this is for multi-URL discovery rather than single-URL discovery via x402_discover_url. However, the description never names the sibling alternative or states an explicit when-to-use/when-not-to-use rule. The distinction is inferable but left to the agent to deduce, so it stops short of explicit guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

x402_fetchA

Fetch any x402-paid endpoint — handles 402 payment challenge automatically on Base, Solana or Casper. The agent never sees wallets or payment details. Just provide a URL and optional body.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlYesFull URL of the x402 endpoint (e.g. https://svm402.com/analyze)
bodyNoJSON body for POST requests (as string)
chainNoForce chain: 'solana', 'base' or 'casper'. Auto-detected if omitted.
methodNoHTTP method: GET or POST (default: GET)

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full behavioral burden. It discloses significant non-obvious behavior: automatic 402 payment handling, support for Base/Solana/Casper, and that wallets/payment details are hidden from the agent. It does not mention payment costs, failure behavior, or response format, but it covers the most important hidden traits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences with no fluff. The core action, automatic payment behavior, supported chains, and privacy property are front-loaded. Every sentence conveys useful operational information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's payment-related complexity and lack of annotations/output schema, the description conveys the core behavior well. The main gap is that it does not describe what is returned (raw response, status, parsed body) nor explicitly caution that invoking it may incur payment, so an agent has to infer some operational expectations.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the baseline is 3. The description adds only 'optional body' as extra context, which lightly reinforces the schema but does not deepen understanding of method/chain/body semantics beyond what the parameter descriptions already provide.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Fetch') and a specific resource ('any x402-paid endpoint'), and clarifies that payment challenge handling is automatic. This clearly differentiates it from sibling discovery/health/description tools like x402_search and x402_describe, which do not actually fetch paid endpoints.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'Fetch any x402-paid endpoint' and 'Just provide a URL and optional body' establishes the core use case: call this tool when you have a concrete x402 URL to invoke. It does not explicitly name sibling alternatives or state when not to use it, but the context makes the primary usage clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

x402_healthA

Check if an x402 service is live and responding with 402 Payment Required. Verifies the service is operational before an agent pays for it.

ParametersJSON Schema
NameRequiredDescriptionDefault
urlNoDirect URL to probe (alternative to name)
nameNoService name from directory (e.g. 'svm402')

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the behavioral disclosure burden. It clearly indicates that the tool probes a service over the network, expects a 402 response, and does not itself make a payment. It does not describe the exact return format or error behavior, but the core side-effect profile is transparent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with no filler. The first sentence states the mechanism and expected response; the second explains why it matters. Each sentence earns its place and the most important information is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple health-check tool with no output schema and no annotations, the description covers what is checked, how it is checked, and when to use it. It does not spell out the return value, but 'Check if' strongly implies a boolean or status result, so the omission is minor.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, with both 'url' and 'name' already clearly documented as alternatives. The description does not add detail beyond what the schema provides, so the baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action ('Check if an x402 service is live and responding with 402 Payment Required') and a clear resource ('x402 service'). It also connects the check to a concrete use case ('before an agent pays for it'), which distinguishes it from sibling tools like x402_search or x402_fetch.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives a clear usage context: use this tool to verify a service is operational before paying. It does not explicitly name alternatives or say when not to use the tool, but the purpose is distinct enough from the siblings that an agent can infer the right situation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

x402_list_categoriesA

List all available x402 endpoint categories with counts.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the behavioral disclosure burden. 'List' appropriately signals a read-only action with no side effects, and 'all available' plus 'with counts' adds scope and output expectations. It does not mention authentication, rate limits, or exact response formatting, but for a zero-parameter listing tool this is a reasonable level of transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, front-loaded sentence that contains no filler. Every phrase earns its place: the resource, the scope, and the expected output detail are all present without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple zero-parameter list tool, the description is largely complete: it names the resource, states the scope ('all available'), and indicates the output includes counts. It falls slightly short by not defining the exact return shape and by leaving 'counts' slightly ambiguous, but this is a minor gap given the tool's low complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has no parameters and the input schema is empty, so there is nothing for the description to clarify about parameter semantics. Given the zero-parameter baseline, the description adequately avoids inventing meaningless parameter details.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('List') and a concrete resource ('all available x402 endpoint categories'), with a clear output detail ('with counts'). This clearly distinguishes it from siblings like x402_search, x402_fetch, and x402_health, which serve different purposes.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies its usage: it is the tool to call when an agent needs a category-level overview of x402 endpoints. However, it does not explicitly state when to prefer this over sibling tools or mention any exclusions or alternative routing, so the guidance remains implicit rather than explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 8 tool updatesv1.0.0
    • First observedx402_crawl_directory
    • First observedx402_describe
    • First observedx402_discover_url
    • First observedx402_discover_urls
    • First observedx402_fetch
    • First observedx402_health
    • First observedx402_list_categories
    • First observedx402_search

TDQS

A3.9/5.0

Scored across 8 tools

Disambiguation4/5

Each tool has a clearly defined role covering category listing, searching, describing, discovering, health-checking, and fetching. The main overlap is between discover_url and discover_urls, which are the same operation in single and batch form, but this is a reasonable convenience rather than a true ambiguity.

Naming Consistency4/5

All tools share the x402_ prefix and most use a verb or verb_noun pattern (list_categories, search, describe, discover_url, crawl_directory, fetch). The exceptions are health, which is a noun, and two discover verbs with slightly different forms, but the overall convention remains predictable.

Tool Count5/5

Eight tools is well within the ideal range for this domain. Each tool addresses a distinct stage of discovering, evaluating, and consuming x402 services without excessive redundancy or missing core functions.

Completeness5/5

The toolset covers the full lifecycle from discovery (search, crawl, list categories), to verification (health, describe, discover_url), to interaction (fetch with automatic payment handling). No obvious dead ends or missing capabilities are apparent for an agent needing to work with x402 endpoints.

Maintenance

ActivityNo data
ResponsivenessResponsive

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    An MCP server that enables AI agents to search, pay for, and call paid APIs using the x402 protocol, with automatic USDC settlement.
    2
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    MCP server that allows AI agents to discover and pay for thousands of APIs (x402 on Solana/Base) using a single key, with automatic payment handling and a federated catalog of machine-payable endpoints.
    234
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    MCP server that provides AI agents with pay-per-call access to a suite of tools (honeypot check, token market, DeFi yields, etc.) via USDC on Base using the x402 protocol.
    3 npm
    MIT