x402 Doctor

com.twelvepermissionsv1.0.0更新于 Sep 30, 2026

Diagnose x402 seller endpoints: what is wrong with your 402 challenge, and how to fix it.

已验证Streamable HTTP可网页运行Other

安装

在 SourceWeft 中

  1. 打开 控制台中的 x402 Doctor,将其添加到工作区。
  2. 为需要使用其工具的对话启用该服务。

Web executable,通过 Streamable HTTP。 远程服务在工作区中配置后即可从网页运行时运行。

其他 MCP 客户端

把它添加到你客户端的 mcpServers 配置中。

{
  "mcpServers": {
    "x402-doctor": {
      "type": "http",
      "url": "https://x402-doctor.tsharpe.workers.dev/mcp"
    }
  }
}

README

x402 Doctor

A free diagnostic for x402 seller endpoints. Point it at your paid endpoint and it performs the handshake a paying client would — a GET with no X-PAYMENT header — then reports what is wrong with the 402 challenge you answered with, and what to change.

Live: https://x402-doctor.tsharpe.workers.dev

bash
curl -s -X POST https://x402-doctor.tsharpe.workers.dev/probe \  -H 'Content-Type: application/json' \  -d '{"url":"https://your-service.example/paid-endpoint"}'

Why seller-side

Buyer-side x402 is well served by the official SDKs. Seller-side is where people get stuck, because the failure happens inside a facilitator you cannot see into: your endpoint looks fine, the payment does not settle, and the error surfaces somewhere you do not control.

Every check carries a provenance field, so no finding has to be taken on trust:

  • spec — the x402 specification requires it.
  • observed (source) — we watched a real facilitator reject it, and the source is named.

What you get back

json
{  "target": "https://your-service.example/paid-endpoint",  "finalUrl": "https://your-service.example/paid-endpoint",  "status": "advisories",  "http": { "status": 402, "contentType": "application/json" },  "findings": [    {      "id": "challenge-cacheable",      "severity": "warn",      "title": "402 challenge is cacheable",      "why": "…",      "fix": "…",      "provenance": "observed (ours, 2026-08-15)",      "evidence": "cache-control: public, max-age=300"    }  ],  "checksRun": 16,  "bodyTruncated": false,  "bodyChecksSkipped": 0,  "bodySkipReason": null}

status is one of:

statusmeaning
healthynothing to report
advisoriesnotes worth reading, but no errors
defects_foundat least one error
not_x402the endpoint did not answer with an x402 challenge
unreachablethe probe could not complete — see reason

If the body was truncated or unparseable, body checks are skipped and the report says so (bodyChecksSkipped, bodySkipReason). A check that did not run is never reported as a check that passed.

The 16 checks

idseveritycheckprovenance
no-402errorEndpoint did not answer 402 without paymentspec
body-not-jsonerror402 body is not parseable JSONspec
oversized-bodywarn402 body exceeded the read capobserved (this probe)
missing-x402-versionerrorx402Version is absent or not 1spec
accepts-emptyerroraccepts is missing, not an array, or emptyspec
output-schema-nullerroroutputSchema is explicitly nullobserved (Coinbase CDP facilitator, 2026-07-17)
amount-not-atomic-stringerrormaxAmountRequired is not an atomic-unit stringspec
asset-network-mismatchwarnasset is not the USDC contract for this networkspec
missing-eip712-extraerrorscheme "exact" without the EIP-712 domain in extraspec
unknown-network-nameinfonetwork name is not one this probe recognisesspec
payto-not-an-addresserrorpayTo is not a valid address for this networkspec
payto-not-checksummedinfopayTo is not a checksummed addressspec
no-timeout-declaredinfomaxTimeoutSeconds is absentspec
challenge-cacheablewarn402 challenge is cacheableobserved (ours, 2026-08-15)
cors-headers-not-exposedinfobrowser clients will need payment headers exposed on the settlement responseobserved (x402-foundation/x402#2112)
bazaar-ext-inside-acceptswarnBazaar extension declared inside an accepts entryobserved (ours, 2026-08-14)

Also an MCP server

POST /mcp, stateless Streamable HTTP. Three tools:

toolwhat it does
probe_x402_endpointrun the diagnostic against a URL
explain_defectfull explanation of one check by id
list_checksthe whole rule table with provenance

What it deliberately does not do

  • It never validates through a facilitator. Doing so would route your traffic through someone else's facilitator credentials. Every check here is derived from the challenge you actually returned.
  • It never sends a payment, and never asks for a key, a seed, or a wallet.
  • It does not judge networks it does not know. An unrecognised network name is an info note about the limits of this probe's list — not a claim that your network is wrong. Address-format rules apply only where the address format is known.

Limits worth knowing

  • The body is read to a cap; past that, body checks are skipped and the report says so rather than guessing.
  • Redirects are followed to a depth of 3, with the SSRF guard re-run on every hop.
  • Rate limited to 20 requests/hour per IP and 300/hour overall, because the service fetches whatever URL it is given.
  • The only thing stored is a per-IP request counter for that rate limit, which expires within two hours. No analytics, and probe targets are never logged.

Security posture, and the residual risks that were accepted rather than fixed, are documented in SECURITY.md.

Reading and running the source

bash
cd doctornpm test          # 163 tests, no dependencies of any kind

Zero dependencies, runtime or dev — the suite is node --test. The rules are pure functions with no I/O; all network access lives in src/probe.js, which is also where the SSRF guard lives.

The hosted service above is free to use and needs no licence. The source is published for inspection and verification under the same terms as the rest of this repository: no licence granted at this time, all rights reserved. If you want to reuse or self-host it, ask.


Built by Twelve Permissions. Free, and unrelated to anything sold there.

来源:doctor/README.md,提交 20ce551

工具

0
工具元数据尚未被收录。

版本历史

1
  1. v1.0.0最新Sep 16, 2026