Public API · schema 2026-08-11

One public computation. Four ways to read it.

Three CORS-open GET endpoints and one MCP server. Read-only, anonymous, and free—without a second data tier or a different score behind authentication.

Abridged live response shape
GET /api/score?id=host:2s.io

{
 "subject": { "id": "host:2s.io", … },
 "rating": {
  "status": "not_rated",
  "grade": "NR",
  "score": null,
  "published": false,
  "publication_floor": {
   "met": false,
   "unmet": [ …, … ],
   "eligible_from_date": "…"
  }
 },
 "observations": { … },
 "components": [ … ],
 "evidence": [ … ]
}
A withheld score is null, never a placeholder number. The floor names both thresholds — 7 archive days and 3 successful observations — and exactly which are unmet.
§ 01

GET /api/score

The full public scorecard for one listing: rating, publication floor, measured components, cited evidence, constraints, financial evidence, history, accepted corrections, and coverage limits.

curl
curl -s 'https://mcpscores.com/api/score?id=host:2s.io'
JavaScript
const r = await fetch('https://mcpscores.com/api/score?id=host:2s.io');
const card = await r.json();
if (card.rating.published) console.log(card.rating.grade, card.rating.score);
else console.log('NR —', card.rating.reason);

Returns 200 when a research record exists and 404 with a well-formed not-rated payload when it does not. A 404 here is data, not an error: it means the identifier is outside the archive.

Open a live response →

What a withheld score looks like

When published is false, grade is NR and score is null. There is no provisional figure anywhere in the payload, and publication_floor states exactly which conditions are unmet and the earliest date the listing could become eligible.

Top-level response fields
FieldTypeMeaning
subjectobjectIdentifier, kind, name, title, publisher, endpoint, registry dates.
ratingobjectGrade, score, published flag, confidence, outlook, and the publication floor. When published is false, score is null — there is no provisional figure to read.
rating.publication_floorobjectThresholds, current archive days and observations, what is unmet, and the earliest eligible publication date.
observationsobjectAs-of date, archive days, successful observations, archive coverage, timestamp precision.
componentsarrayFive measured components with 0–100 value, weight percent, and applicability.
evidencearrayMeasured statements with source table, coverage confidence, and observation date.
constraintsarrayMaterial observations that capped or forced the grade.
financial_evidenceobjectDeclared payee, balance snapshot, observed inflow with block range, payer count and concentration.
historyobjectStored engine score records and daily observed wallet inflow.
corrections_appliedarrayAccepted operator corrections, dated. Empty array when none.
coverageobjectWhat is included, the stated limitations, and pending model inputs.
§ 02

GET /api/top

Highest published ratings. Candidates are drawn from the stored rating sweep and then every figure is recomputed through the authoritative path before it is returned.

curl
curl -s 'https://mcpscores.com/api/top?limit=10'

limit is 1–10, default 10.

Open a live response →

An empty list is a real answer

When nothing clears the publication floor the response carries status: "no_published_ratings", an explanation, the floor itself, the real archive coverage, and a per-candidate reason in evaluation.blocking_reasons. Ratings are never invented to fill the list — parse status rather than assuming an empty array means failure.

Right now this endpoint has evaluated 4 candidate(s) and returns 0 published rating(s), while the archive holds 2 day(s) against a 7-day floor.

§ 03

GET /api/field

The whole register as a point field: one row per researched listing with kind, observed state, tool count, USDC treasury, observed on-chain inflow, and domain year. This is the exact dataset the homepage network map plots — same computation, same cache.

curl
curl -s 'https://mcpscores.com/api/field'

No parameters. Rows are ordered by observed state, then kind, then id — the array index is the register rank the map uses for placement. Attributes the observatory has not recorded are 0, never estimated.

Open the live response →

Columns per row: id, kind (0 x402 host, 1 MCP server), state (0 answering, 1 silent, 2 unprobed), tool_count, usdc_balance, usdc_inflow_observed, distinct_payers, domain_created_year. The payload carries its own counts, max, and limitations fields.

§ 04

POST /mcp

The same two reads as MCP tools, over Streamable HTTP and JSON-RPC 2.0. Free: there is no x402 gate on this server, so an unpaid tools/call simply returns the data.

List the tools
curl -s -X POST 'https://mcpscores.com/mcp' \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
Call score_lookup
curl -s -X POST 'https://mcpscores.com/mcp' \
  -H 'content-type: application/json' \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call",
       "params":{"name":"score_lookup","arguments":{"id":"host:2s.io"}}}'

No account, no gate

There is no x402 challenge on this MCP server and no API key anywhere in the reference. An unpaid tools/call returns the same structured content the website renders.

Registry manifest: /server.json · AI-readable site guide: /llms.txt · readiness: /health

ToolArgumentsReturns
score_lookupid (string, required)The full scorecard as structured content.
top_ratedlimit (integer 1–10)Published ratings with the same empty-result semantics as /api/top.
§ 05

Listing identifiers.

Every listing has one canonical identifier.

host:<hostname>          an x402 endpoint host
mcp:<publisher>/<name>   a registry-listed MCP server

Hostnames are lower-cased with a trailing dot stripped. If you only have a URL, GET /lookup?q=https://api.example.com/pay resolves it and redirects to the canonical scorecard.

§ 06

Rate limits and caching.

60 requests per minute per client address on /api/* and /mcp; 120 per minute on site pages. Enforced by a per-address counter, not per PoP. Responses carry RateLimit-Limit, RateLimit-Policy, RateLimit-Remaining and, on a 429, a bounded Retry-After. If the limiter itself fails, requests are served rather than blocked.

Scorecards are cached 60s in the browser and 300s at the edge. X-MCP-Scores-Methodology carries the model version on every API response, so a client can detect a model change without diffing payloads.

§ 07

Attribution and reuse.

The API is free for commercial and non-commercial use, including inside a paid product.

Cite a figure as: MCP Scores, MCP Authority, model 1.0, with the scorecard URL and the observation date shown on the card.

Two requests, both enforceable by reputation rather than by licence: carry the observation date with the number, and do not present a withheld figure as a low score. NR means the archive cannot support a grade yet.

Do not cache a rating forever

Ratings move when the endpoint's behaviour moves. A number scraped once and displayed for months stops being a measurement. Re-read at least daily, or embed the live badge and let it stay current on its own.