demo demo/open-server.receipt.json  ·  signed with the published demo key
AUTH-OPEN  ·  the tool list was served to an unauthenticated caller

X190

Proof,
not trust.

Does this endpoint enforce authentication? X190 sends initialize, replays tools/list with no token, and records what came back. If the server hands its tool list to an unauthenticated caller, that is the finding.

That is the whole tool.

Three requests, one record. Nothing is installed, nothing is proxied, nothing is held.

Two fault classes. Nothing invented.

X190 checks exactly what the measurement observed, and only that.

F1

auth-absence

tools/list returned a JSON-RPC result with no token. The probe requires a result echoing the request id before it claims anything — a correct refusal inside a 200 is never recorded as open.

F2

incomplete-oauth-rs

The endpoint refused — but with no RFC 9728 challenge a client could actually follow, or with protected-resource metadata that does not resolve. A refusal you cannot act on is a finding, not a pass.

The measurement behind the checks

Re-measured on 2026-09-11 with v0.9.1: 100 endpoints drawn from the official MCP registry, at most one per publisher domain, probed once each. The registry then held 5,897 active servers, 4,942 of them exposing a remote HTTP endpoint.

45%served the tool list to a caller with no token (F1)
40refused, and published RFC 9728 metadata that resolved
9refused with a broken, absent or unfetchable challenge (F2)
6inconclusive — no posture observable, and none claimed
Read this before quoting the number

One endpoint per publisher stops a single operator with 763 listed servers from setting the rate, but it over-weights small publishers; an endpoint-weighted rate would differ and we have not measured it. Registry listing is itself a filter. One probe, one timestamp, one network position. Some of the 45 are certainly public on purpose — whether an open endpoint is a fault is not a judgement this tool makes. The earlier 40-of-74 headline remains suspended and is not restated. Read the full report, or EVIDENCE.md ↗

A receipt proves exactly one thing.

That someone holding the key produced this byte-for-byte content. Nothing else.

  • Tamper evidence, not attestation. The scheme is symmetric: a party who can verify a receipt can also mint one. It is tamper evidence for your own archive — not proof you can hand to a third party. If you need transferable proof, this design cannot give it to you.
  • An observation, not a verdict. AUTH-OPEN says: at this timestamp, from this network position, the endpoint served a JSON-RPC result for a tokenless tools/list. Whether that is a fault is the operator's call — a deliberately public MCP server is a legitimate design.
  • No freshness. A receipt carries a timestamp and nothing binds it to now. The verifier reports age_seconds; your staleness policy is yours.
  • Demo keys are marked. Receipts signed with the published demo key carry "demo_key": true, and the verifier warns about them.
Verify one from the repo's own demo — and one that was tampered with
X190_KEY=X190-demo-key-not-a-secret X190 verify-receipt demo/open-server.receipt.json
-> valid

X190_KEY=X190-demo-key-not-a-secret X190 verify-receipt demo/tampered.receipt.json
-> false, exit 1

Getting started

No install step. There is no install step.

Probe an endpoint

# a live endpoint
X190 check https://host/mcp

# a local server
X190 check http://127.0.0.1:3000/mcp

# verify a receipt later
X190 verify-receipt x.receipt.json
Exit codes — 0 pass or inconclusive only  ·  1 at least one fault  ·  2 target is not an http(s) URL

Gate it in CI

- uses: unempyd/X190@v0.9.2
  with:
    target: https://your-host/mcp
    gate-key: ${{ secrets.X190_KEY }}
The step fails the build when a fault is found. Read steps.<id>.outputs.failures to gate on the count yourself.

Set a real key

X190_KEY=your-real-secret # anywhere you intend to verify receipts, including CI
No key set? A per-machine key is created at ~/.X190-key, permissions 0600.

Servers distributed for stdio can still ship an HTTP mode — 3 of 23 npm packages measured did, and all three could serve MCP without authentication in a documented configuration. Start the HTTP mode and probe that URL like any other. The fault is the same fault; only the discovery is different. README ↗

What this is not. What it cannot do.

Stated plainly, because a verification tool that overstates itself is worthless.

Ready in one command

Ask the endpoint
instead of assuming.

MIT licensed  ·  v0.9.2  ·  Evidence and methodology ↗

Get X190.

Checkout is hosted by Stripe. We never ask for your endpoint URLs on the payment page — scope is agreed privately afterwards. See terms, refunds and privacy.

The tool is free and MIT licensed, and we do not sell a second licence — you already have every right you need. What is for sale is the work the tool cannot do for you: judgement on what a finding means, and someone still watching next month.

Install

$0

One command

Pip-installable straight from the repository. No dependencies, no build step, no account.

Install instructions ↗

Endpoint review

$2,500

Fixed fee, up to 25 endpoints

We probe your endpoints, then do the part X190 refuses to claim: whether a token is actually validated, whether scopes are enforced, and exactly what to change to make a broken RFC 9728 challenge followable. Written findings in five business days.

Book a review or scope it with us first

Continuous watch, previously $250 a month, has been withdrawn. We measured the population it was priced for and it is not there. 97% of publisher domains run a single endpoint, the largest genuine fleet we can find is 19, and every large vendor we probed already enforces the authentication it documents. Selling a fleet subscription into that would have been selling something nobody needs. If you do run enough endpoints that checking them by hand is a real problem, say so and we will work out what it should cost. We are not going to put a price on it before someone has the problem.

Talk to us.

Reviews, continuous watch, or tell us what X190 missed on your endpoint.

These open a GitHub issue, which is public — send the shape of the problem, not your endpoints. We move to a private channel before anything sensitive changes hands, and we never publish findings that name your systems.