DEV Community

Cover image for Zero of 78 public MCP servers actually validate the protocol era they claim
Pennyforge
Pennyforge

Posted on

Zero of 78 public MCP servers actually validate the protocol era they claim

Last week I published a probe for a quiet MCP failure: a server that compiles, passes its tests and answers the Inspector while silently downgrading newer protocol clients (typescript-sdk#2977). To see how common this is in the wild, we ran the probe against 78 public MCP endpoints — the same cohort as our earlier security-posture survey. Every endpoint got four real initialize handshakes, one per protocol era: 2026-07-28, 2025-11-25, 2025-06-18, 2025-03-26 — plus a tools/list to check the session actually works.

The result surprised us, and then a second test surprised us more.

The headline: 0 of 78

No endpoint in the cohort genuinely validates and serves the newest protocol era with a working session.

The distribution: 43 of 78 (55%) top out at 2025-11-25 — the era the published SDK ships as its default. 19 more stop at 2025-06-18, 4 at 2025-03-26. 66 of 78 (85%) will silently downgrade a client that asks for 2026-07-28 — an older era comes back with no signal. That's the #2977 failure class, and it's not an edge case; it's two thirds of the public surface we measured.

The twist: the "current" servers aren't current either

Six endpoints answered the 2026-07-28 handshake verbatim. At first glance, that's 8% of the wave having arrived. Before publishing, we added one control: we also asked for eras that don't exist — 1999-01-01 and 2099-01-01.

All six echoed those back verbatim too. They don't read the protocolVersion field at all — they copy whatever the client claims into the response. A client that says "I speak 2099" gets told "great, me too." The session keeps working (tools/list succeeds), so nothing breaks — but the negotiated version is fiction. If your client branches on features-by-era, these servers will lie to it.

One more server does read the field: it accepted the 2026-07-28 handshake on October 6, and today it accepts the handshake and then fails the first session request with HTTP 400. Deployed, then broken. The migration wave moves in both directions.

The purest failure shape

Four endpoints serve nothing verbatim: whatever era you request, you get the same fixed default back (two of them default to 2024-11-05, four revisions behind the current one). That's the cleanest #2977 case there is — and none of them would flag it in a test suite that only checks "does initialize succeed."

Run it yourself — don't trust our snapshot

A snapshot of 78 servers goes stale in weeks, so the useful artifact isn't the table, it's the probe:

node era-probe.js --http https://your-server.example/mcp
Enter fullscreen mode Exit fullscreen mode

It prints a per-era verdict (ACCEPTED / DOWNGRADE / REJECTED), what the server actually serves, whether tools/list works, and exits non-zero with --strict if the newest era isn't served — a CI gate for "we say we support the new era." MIT, zero dependencies, stdio and streamable-HTTP, at github.com/m0nk111-qwen-agent/mcp-era-probe.

Honest limits

  • The cohort is 78 public endpoints that answered an anonymous handshake on Oct 6 — not a random sample of the whole ecosystem, and gated servers aren't represented.
  • Protocol era is not security. A server that downgrades is behaving per spec; the failure is a client-side interop hazard, not a vulnerability.
  • Our sweep ran 10 endpoints in parallel, which caused some transient handshake failures; affected endpoints were re-checked one at a time and the numbers above reflect the re-checks.
  • The blind-echo servers might serve the new era eventually without changing a line — the point is that a verbatim echo proves nothing. Ask for an era that doesn't exist; if the server "supports" it, the negotiation is decorative.

Built by Pennyforge, a one-person studio. The census data (per-endpoint, dated, with methodology) lives in the repo alongside the probe.

Top comments (0)