Remote MCP endpoint scoring rubric
A remote server is a hosted endpoint you connect to but don’t run, so we score the connection, the operator, and the quality of what it exposes, verified where possible against a live MCP handshake.
Half the score is about the endpoint itself: endpoint security 40% and transport and reachability 10%. The other half is the shared core, scored the same way here as on a packaged server: schema quality and AI usability 20%, stability and change management 15%, tool coverage 10% and capabilities 5%. A clean, fully readable endpoint can reach 100.
Transport & reachability (10%)
Can we actually reach and speak MCP to the declared endpoint, and over which transport?
This is its own category. Until July 2026 transport modernity was scored inside capabilities, which made that category impossible to apply to a packaged server: a package always runs over stdio, and that says nothing about the package. Transport is a fact about how an endpoint is reached, so it now sits with endpoint security on the remote-only side, and capabilities became part of the shared core.
| Passing | Needs a fix |
|---|---|
| A live MCP handshake completes over the declared transport | We couldn’t connect; the TLS certificate failed verification; the endpoint redirected instead of answering directly; it answered but didn’t complete an MCP handshake; it returned an HTTP error; no usable transport is declared; or only stdio is declared, which can’t run as a live remote endpoint → transport |
An endpoint that requires authentication we don’t hold can’t have its transport verified; it scores 0 and counts against the score. Claim the server and verify ownership to lift it: a fixable gap, not a permanent fail.
Endpoint security (40%)
The transport and operator-accountability signals, checked against the relevant standards: TLS 1.2 or higher, HSTS (RFC 6797), and OAuth protected-resource metadata (RFC 9728).
| Area | Passing | Needs a fix |
|---|---|---|
| TLS | The certificate is valid, in date, and uses a strong key | A weak key (partial credit), a protocol below TLS 1.2, an expired certificate, a hostname mismatch, an untrusted chain, or MCP served over plain HTTP → TLS |
| HTTPS | HTTPS is enforced, with no plaintext access path | The endpoint is reachable over plaintext HTTP → HTTPS |
| HSTS | The Strict-Transport-Security header is present | The header is absent → HSTS |
| Authorization | Authorisation is enforced and advertised via RFC 9728 metadata, whether on connect or on tool calls | A challenge with no discoverable route to a token, open access to a tool marked destructive, open access with only non-destructive tools (partial credit), or open access with tools that never declare whether they’re destructive → authentication |
| DNSSEC | The domain’s records validate against the full chain to the root | DNSSEC is absent, or signatures are present but fail validation → DNSSEC |
Capabilities (5%)
Does the server speak a current slice of the protocol? This category was rebuilt, then narrowed again when transport moved out of it: it now scores protocol-version recency and a UI-hint bonus, and nothing else. Both are read straight from the handshake, which is why this category applies unchanged to packaged servers too.
| Signal | Passing | Needs a fix |
|---|---|---|
| Spec version | A current or still-supported MCP spec version. We read it from server/discover where the server offers it, and fall back to the initialize handshake for pre-2026-07-28 servers | An outdated spec version, or one newer than any we recognise (unverifiable) → protocol version |
| UI hint | UI / widget rendering support is advertised | - |
The UI hint is a pure bonus and not a trust or security signal, just a “cared-for” nicety: present raises the score, absent emits no signal at all, so a headless server is never docked for it. Signals that used to live here (transport modernity, primitive coverage, sampling/roots, structured output, auth support) are no longer scored here: transport moved to its own category above, and the rest were removed, because a declared primitive is a claim not a capability, sampling and roots are client capabilities a server shouldn’t advertise, and auth and structured output are each scored once elsewhere (endpoint security and tool coverage) rather than double-counted.
Schema quality & AI usability (20%)
How well an agent can actually understand and use the tools.
| Signal | Passing | Needs a fix |
|---|---|---|
| Descriptions | A high share of prompts and resources carry a non-trivial description | Low coverage → schema quality |
| Examples | Tools include usage examples | No tool includes an example → schema quality |
| Clarity & footprint | Clear, AI-judged instruction quality, and lean tool/resource definitions | Definitions over the context-window budget → schema quality |
The description measurement here covers prompts and resources only. Tool and parameter descriptions are scored in Tool coverage, not counted twice. The second half of the clarity row guards the schema’s context-window budget: every tool and resource definition is loaded into the model’s context on each request, so we estimate the tokens those definitions use against a per-item budget. At or under budget scores full marks, and only genuine overspend decays the score.
An empty schema (no tools, prompts, or resources, so nothing to assess) scores as a fail, not inconclusive: a content-free server never gets credit for a “leanest possible” schema it never actually wrote. When we couldn’t read the schema at all, by contrast (the endpoint was unreachable, or it requires authentication we don’t hold), the checks are genuinely inconclusive: nothing could be assessed either way.
Tool coverage (10%)
Deterministic checks on the tool definitions themselves, computed directly from the captured schema (no AI judgement, unlike the clarity check in schema quality).
| Signal | Passing | Needs a fix |
|---|---|---|
| Descriptions | A high share of tools carry a non-trivial description | Low coverage → tool coverage |
| Parameter docs | A high share of tool parameters carry a description | Undocumented params → tool coverage |
| Output schema | Structured output schemas are declared (credit-only) | - |
Tool and parameter descriptions are scored here and only here (schema quality
covers prompts and resources), so no measurement is charged to two categories. The
old naming-consistency signal was removed. Output schema is credit-only:
declaring one raises the score and not declaring one never lowers it (outputSchema
is optional). Parameter docs and output schema are each omitted rather than
counted against a server that has no parameters or no output schema, so a small or
output-less server is never penalised for a gap that isn’t a defect. When we
couldn’t read the tools at all (the endpoint was unreachable, or it requires
authentication we don’t hold) the category is inconclusive and scores 0 until we
can.
Stability & change management (15%)
Does the surface stay stable so agents don’t break?
This category is also scored on packaged servers, where it compares the versions we have captured rather than a live schema. See the package rubric for how that differs.
| Passing | Needs a fix |
|---|---|
| No destabilising schema changes in the last 30 days | Schema churn: tool removals, breaking changes, or a dropped auth requirement → stability |
Churn covers tool removals, breaking input/output changes, and a dropped
authorization requirement between snapshots (a server that stops enforcing auth
is a breaking security regression). Adding auth is an improvement and is never
penalised. Credit ramps linearly over the observed window rather than waiting for
a full 30 days: score = clamp(observedDays / 30 − penalty) × 100, so a clean
young server earns partial credit from its first observed day and full marks once
30 days of steady history accrue. Destabilising changes subtract from whatever
credit has accrued, which means a young server can never outscore its observation
window. A server with no scan history at all still can’t be verified and scores 0
until its first snapshots land.