Pennyforge Studio · 2026-10-06 · cohort n=78 · $0 · reproducible (probe script + raw JSON available on request, 16-second wall)
Last week we published a compatibility probe of 78 public MCP endpoints: the servers in the registry's first alphabetical slice that answered an initialize. This run we stopped measuring "does it answer" and started measuring something else: what does a stranger with zero credentials get — and does the server follow the spec revision it claims to speak? Same cohort, same day window, new questions.
The headline table
| measure | result |
|---|---|
endpoints that answer initialize anonymously (no credentials, no headers) |
76/78 (97%) |
| endpoints that then expose their FULL tool inventory to that stranger | 74/78 (95%) |
| tools a stranger with zero credentials can see | 793 — 100% carry a description string |
| endpoints that gate anything at the protocol level | 2 — both with NO WWW-Authenticate header
|
endpoints that ever send a WWW-Authenticate header (the OAuth 2.1 + RFC 9728 discovery the 2026-07-28 revision standardizes when authorization is on) |
0/78 |
| endpoints on the 2026-07-28 revision | 7/78 (9%) — unchanged across our three dated points |
endpoints that still issue Mcp-Session-Id headers — a header the 2026-07-28 revision removed from the spec entirely (SEP-2567) |
9/78 (12%) |
Two concrete dated bugs
1. A 401 you cannot discover. agentxray.ai/api/mcp: initialize is wide open; tools/list returns 401 {"detail":"invalid or missing MCP token"} with no WWW-Authenticate header. A conforming client following the spec's own discovery chain (401 → resource_metadata per RFC 9728 → authorization-server metadata per RFC 8414/OIDC) has nothing to latch onto: the credential scheme is a private convention. The spec even shows the 401 shape this server skipped:
WWW-Authenticate: Bearer resource_metadata="https://mcp.example.com/.well-known/oauth-protected-resource"
2. A revision-mix interop wall. 7/78 endpoints (9%) accept the legacy handshake but reject a standard tools/list with HTTP 400: -32602 "Missing required _meta field: io.modelcontextprotocol/clientCapabilities". The twist is that this is the new spec's fault line: the 2026-07-28 revision makes every request carry protocolVersion + clientCapabilities in _meta (SEP-2575 — the initialize handshake is gone; the protocol is now stateless and version rides per-request). So one of these seven, ad.getle/leads, negotiates 2026-07-28 and is actually conformant — it is our legacy-form request that is wrong. The other six negotiate 2025-11-25 while already enforcing the new request shape: partial migration — the exact interop mess a versioned spec exists to prevent. Nine percent of the cohort is only reachable through the new request shape, and six of those nine are mid-migration.
The exposure surface, by size
74 endpoints expose their full tool list to an anonymous stranger: median 5 tools; 25 expose 10 or more. The largest: 184 tools (borealhost), 65 (bitroad), 35 (betslipdoctor), 35 (getle), 23 (betterpost). Every one of the 793 tools carries a description — the string an LLM client reads and trusts when deciding what to call. In the tool-poisoning terms that security people now use: 793 third-party-authored descriptions, readable and callable by anyone, on infrastructure with no protocol-level identity.
What the 2026-07-28 spec actually says (fetched first-hand for this post)
-
Stateless by construction: the
initialize/notifications/initializedhandshake is removed; every request carriesprotocolVersion+clientCapabilitiesin_meta;Mcp-Session-Idis gone from Streamable HTTP (SEP-2575, SEP-2567). Version mismatch →UnsupportedProtocolVersionError.server/discoveris MUST — the designated way to advertise supported versions. - Roots, Sampling, Logging are deprecated (SEP-2577) but "remain fully functional during the deprecation window"; Tasks moved out of core into an official extension (SEP-2663).
-
Authorization is optional per implementation — but when supported: OAuth 2.1, RFC 9728 Protected Resource Metadata is MUST for servers and for client discovery, RFC 8707
resourceindicator is MUST, and the anti-token-passthrough rule is explicit: "MCP servers MUST NOT accept or transit any other tokens." RFC 7591 dynamic client registration is deprecated in favor of Client ID Metadata Documents. - The NSA weighed in. "Model Context Protocol (MCP): Security Design Considerations for AI-Driven Automation" (U/OO/6030316-26, May 2026, 17 pages) opens with: "MCP's rapid proliferation has outpaced the development of its security model." It names arbitrary-code-execution (CWE-77/78/94/95) as the class that "easily arise in MCP environments."
-
Two CVEs make it concrete. CVE-2025-6514: OS command injection in
mcp-remotevia a craftedauthorization_endpointURL — 9.6 CRITICAL. CVE-2025-49596: the MCP Inspector's proxy ran unauthenticated (RCE, fixed in 0.14.1) — 9.4 CRITICAL. Both verified against cve.org for this post.
The honest counterweight: the scanner space is not empty. Snyk, Cisco and Tencent all maintain MCP security scanners, all pushed within the last week. What none of them are is a dated, reproducible, neutral cohort table — the "who's checking your ID, and which revision is actually deployed" index. This post is that table; the script makes it re-runnable by anyone.
Version mix — stable at the third dated point
| negotiated revision | 2026-10-05 | 2026-10-06 |
|---|---|---|
| 2026-07-28 | 7 | 7 |
| 2025-11-25 | 41 | 41 |
| 2025-06-18 | 20 | 20 |
| older | 8 | 8 |
Ten weeks after the 2026-07-28 revision — with its handshake, its session header and its ping all removed — this cohort is 9% on it. The revision's own backward-compatibility machinery (per-request version negotiation, server/discover) is only partially deployed even on the servers that adopted it.
Method, labels, caveats
All wire measurements are first-hand: a 16-second probe (anonymous initialize in legacy and modern form, tools/list with session + negotiated version, header capture; 8 workers). "Anonymous" = no auth header, standard user-agent; we sent credentials no one should recognize. The 2 endpoints that never initialized (one HTTP 530, one 200-with-non-RPC) are marked unresolved, not failed. Because the spec makes authorization optional per implementation, "0/78 use OAuth discovery" is a statement about this cohort's deployed state — the two bare-401 servers are the closest thing to a violation (they gate without any discoverable mechanism). Spec, NSA and CVE claims are cited to the primary sources above and were all fetched for this post.
Next dated point: the registry's c–d slice — same script, new cohort, doubled table — lands around mid-October, timed just after AGNTCon/MCPCon (10-22/23).
Part of our dated MCP probe series. The script, the raw JSON and the previous posts are linked above / available on request. Pennyforge is a one-person studio; this was all measured from our own machine this week at $0 in API costs.
Top comments (0)