Summary
AIP-1 §7.1 normatively defines the transport field (streamable_http, sse, stdio) and the not_implemented array, with the example /mcp/sse listed as a probed-but-not-served variant a streamable_http server should declare. AIP-1 does not mention the historical bare /sse path (no /mcp prefix).
Empirically observed against the AIGEN reference server: a recurring research scanner that self-identifies via PTR zl-amsc-nl-gr1-wk102a.internet-census.org (Zenlayer AS21859, NL) probes bare GET /sse — not /mcp/sse — on every visit. AIGEN returns 404 22B and the client abandons the lifecycle. Pattern: 3 sessions / 11 distinct IPs across the 185.226.197.0/24 worker pool, 2 visit windows 5 days apart (2026-05-24T06:46Z + 2026-05-29T10:38Z + 10:49Z), 22 hits total. Per session: dual-flow Chrome browser to / (cookie warm-up) → python-httpx/0.28.1 POST /mcp init+202+tools/list (succeeds, 41564B tools/list body) → bare GET /sse 404 → session ends. Different /24 worker per visit window.
Why this matters for the spec
Pre-streamable_http MCP clients (and research scanners that index the long-tail of MCP-1.0 endpoints) probe /sse at the root, not under /mcp. AIP-1 §7.1's example not_implemented: ["sse", "stdio"] is about transport names, and the array of probed-but-not-served paths (/mcp/sse, /messages/) is mentioned in §7.1 prose but not codified normatively as a separate field. The result: a conformant /.well-known/oabp.json declaring transport: streamable_http does not communicate to a legacy-SSE-probing client that /sse at the document root is also unserved.
For an OABP implementation that supports only streamable_http, the catalogue of paths a client might probe and not find includes at minimum:
/mcp/sse (Streamable HTTP path's SSE variant, MCP 0.2-era convention)
/sse (root-level SSE, MCP 0.1-era convention — observed in production)
/messages/ (MCP message-bus variant)
/v1/messages (some forks)
A normative path-level enumeration would let scanners self-correct without hitting 404.
Proposal
Extend §7.1 with a separate transport_paths block adjacent to transport and not_implemented:
"mcp": {
"transport": "streamable_http",
"url": "https://example.org/mcp",
"not_implemented": ["sse", "stdio"],
"transport_paths": {
"served": ["/mcp"],
"not_served": ["/mcp/sse", "/sse", "/messages/", "/v1/messages"]
}
}
Where:
transport_paths.served lists the canonical endpoint(s) actually serving the declared transport.
transport_paths.not_served lists root- or subpath-level variants a probing client may hit, which the server explicitly does not serve. Items SHOULD respond with structured 404 per §7.2 ({"error":"not_implemented","canonical_endpoint":"...", "supported_transports":[...]}) rather than bare 404.
Rationale: the existing not_implemented array describes transport names (which AIP-1 enumerates as streamable_http | sse | stdio); transport_paths.not_served describes URL paths a client may probe, which is a different axis. The two are not redundant: a server that supports sse transport-name on /mcp/sse may still need to declare it does not serve bare /sse.
Falsifiable counter-watch
If no other client besides the 185.226.197.0/24 scanner probes bare /sse against AIGEN in the next 60 days (2026-05-29 → 2026-07-28), this proposal can be closed as low-impact (single-actor noise). If 2+ additional distinct ASNs probe bare /sse in that window, the case for transport_paths.not_served strengthens.
Reference data
- 24-May 2026 06:46:15Z burst:
185.226.197.37/38/39/40 from /24, Referer http://207.148.107.2/ (which is AIGEN's external test IP — so the scanner seeded itself by crawling the public IP), 8 hits
- 29-May 2026 10:38:10Z burst:
185.226.197.22/23/25, no Referer, 7 hits
- 29-May 2026 10:49:38Z burst:
185.226.197.17/18/19, no Referer, 5 hits
- PTR for
185.226.197.22: zl-amsc-nl-gr1-wk102a.internet-census.org (Zenlayer Inc / AS21859 / Lelystad NL)
- Per-session method: Chrome
GET / warm-up → python-httpx/0.28.1 POST /mcp init (200 1188B) → POST /mcp 202 0B → POST /mcp tools/list 200 41564B → GET /sse 404 22B → favicon by Chrome IP → end
Implementation cost in reference impl
/.well-known/oabp.json regeneration: add 4 lines under the mcp block.
- Optional: route alias
/sse → structured 404 per §7.2. ~5 lines nginx, no backend.
If the consensus is to keep §7.1 minimal and not normalise transport_paths, an alternative is a non-normative §7.1 example showing the not_implemented array including path-level variants (["sse", "stdio", "/sse", "/messages/"]) — but that overloads the field's meaning and is harder to validate.
Summary
AIP-1 §7.1 normatively defines the
transportfield (streamable_http,sse,stdio) and thenot_implementedarray, with the example/mcp/sselisted as a probed-but-not-served variant astreamable_httpserver should declare. AIP-1 does not mention the historical bare/ssepath (no/mcpprefix).Empirically observed against the AIGEN reference server: a recurring research scanner that self-identifies via PTR
zl-amsc-nl-gr1-wk102a.internet-census.org(Zenlayer AS21859, NL) probes bareGET /sse— not/mcp/sse— on every visit. AIGEN returns404 22Band the client abandons the lifecycle. Pattern: 3 sessions / 11 distinct IPs across the185.226.197.0/24worker pool, 2 visit windows 5 days apart (2026-05-24T06:46Z + 2026-05-29T10:38Z + 10:49Z), 22 hits total. Per session: dual-flow Chrome browser to/(cookie warm-up) →python-httpx/0.28.1POST /mcpinit+202+tools/list (succeeds, 41564Btools/listbody) → bareGET /sse404 → session ends. Different/24worker per visit window.Why this matters for the spec
Pre-
streamable_httpMCP clients (and research scanners that index the long-tail of MCP-1.0 endpoints) probe/sseat the root, not under/mcp. AIP-1 §7.1's examplenot_implemented: ["sse", "stdio"]is about transport names, and the array of probed-but-not-served paths (/mcp/sse,/messages/) is mentioned in §7.1 prose but not codified normatively as a separate field. The result: a conformant/.well-known/oabp.jsondeclaringtransport: streamable_httpdoes not communicate to a legacy-SSE-probing client that/sseat the document root is also unserved.For an OABP implementation that supports only
streamable_http, the catalogue of paths a client might probe and not find includes at minimum:/mcp/sse(Streamable HTTP path's SSE variant, MCP 0.2-era convention)/sse(root-level SSE, MCP 0.1-era convention — observed in production)/messages/(MCP message-bus variant)/v1/messages(some forks)A normative path-level enumeration would let scanners self-correct without hitting 404.
Proposal
Extend §7.1 with a separate
transport_pathsblock adjacent totransportandnot_implemented:Where:
transport_paths.servedlists the canonical endpoint(s) actually serving the declaredtransport.transport_paths.not_servedlists root- or subpath-level variants a probing client may hit, which the server explicitly does not serve. Items SHOULD respond with structured 404 per §7.2 ({"error":"not_implemented","canonical_endpoint":"...", "supported_transports":[...]}) rather than bare 404.Rationale: the existing
not_implementedarray describes transport names (which AIP-1 enumerates asstreamable_http | sse | stdio);transport_paths.not_serveddescribes URL paths a client may probe, which is a different axis. The two are not redundant: a server that supportsssetransport-name on/mcp/ssemay still need to declare it does not serve bare/sse.Falsifiable counter-watch
If no other client besides the
185.226.197.0/24scanner probes bare/sseagainst AIGEN in the next 60 days (2026-05-29 → 2026-07-28), this proposal can be closed as low-impact (single-actor noise). If 2+ additional distinct ASNs probe bare/ssein that window, the case fortransport_paths.not_servedstrengthens.Reference data
185.226.197.37/38/39/40from/24, Refererhttp://207.148.107.2/(which is AIGEN's external test IP — so the scanner seeded itself by crawling the public IP), 8 hits185.226.197.22/23/25, no Referer, 7 hits185.226.197.17/18/19, no Referer, 5 hits185.226.197.22:zl-amsc-nl-gr1-wk102a.internet-census.org(Zenlayer Inc / AS21859 / Lelystad NL)GET /warm-up →python-httpx/0.28.1 POST /mcpinit (200 1188B) →POST /mcp 202 0B→POST /mcp tools/list 200 41564B→GET /sse 404 22B→ favicon by Chrome IP → endImplementation cost in reference impl
/.well-known/oabp.jsonregeneration: add 4 lines under themcpblock./sse→ structured 404 per §7.2. ~5 lines nginx, no backend.If the consensus is to keep §7.1 minimal and not normalise
transport_paths, an alternative is a non-normative §7.1 example showing thenot_implementedarray including path-level variants (["sse", "stdio", "/sse", "/messages/"]) — but that overloads the field's meaning and is harder to validate.