Streamable HTTP transport (JSON-RPC 2.0 over POST), one-class-per-tool/resource/prompt API mirroring RequestHandler, boot-time-precompiled schema/list payloads for a zero-alloc hot path, and optional OAuth2 protection built on flash-ext-oidc (lazy-loaded, RFC 8707 audience binding, RFC 9728 Protected Resource Metadata). Registers the module in the root and flash-extensions POMs and adds the ext-mcp commit scope to AGENTS.md. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2.9 KiB
Transport
flash-ext-mcp implements the Streamable HTTP transport from the MCP specification
(revision 2025-11-25). stdio is out of scope — Flash5 is an HTTP framework, and a
subprocess-stdio transport doesn't fit its model.
What this revision implements
- A single
POST {rootPath}endpoint (default/mcp) accepting one JSON-RPC 2.0 message per request and responding with a plain JSON object — the "standard JSON object response" mode the specification allows as an alternative to opening a Server-Sent Events stream per request. Originheader validation (DNS-rebinding protection), configurable viaMcpConfig.allowedOrigins(...).- Full JSON-RPC lifecycle:
initialize,notifications/initialized(and any othernotifications/*/id-less message — answered with a bare202 Accepted, no body, per JSON-RPC's notification semantics),ping,tools/list,tools/call,resources/list,resources/read,prompts/list,prompts/get.
What this revision deliberately does not implement
- No
Mcp-Session-Id/ session state. The specification says a server "MAY assign a session ID at initialization time" — it is optional, not mandatory. This server is stateless: everyPOSTis handled independently, with no server-side session store.initializedoes not need to precede other calls for the server to function (there's no session to be "not initialized" yet), which is a looser contract than a session-aware server would enforce — acceptable for a static, boot-time-defined tool/resource/prompt catalog. - No Server-Sent Events stream.
GET {rootPath}(used by session-aware servers to open a standing SSE stream for server-initiated pushes) is not registered — MCP clients that only speak the request/response half of Streamable HTTP work unaffected; clients that require a standing SSE connection are not supported by this revision.
Both are real, intentional scope cuts for a first version — not just to keep the surface area
small: a static, precompiled tool catalog (see tools-resources-prompts.md) has no
listChanged events to push and no long-running server-initiated messages to stream, so the
stateful half of the transport buys little for the common case this extension targets. Sessions
and SSE are natural extension points if a future revision needs server push (e.g. dynamic tool
registration, elicitation, or sampling requests initiated by the server).
Why POST, not the new QUERY HTTP method
Flash5's core recently gained HttpMethod.QUERY (safe, idempotent, carries a body — a good
semantic fit for JSON-RPC-over-HTTP in general). It is not used here: the MCP Streamable
HTTP specification mandates POST for the client-to-server message path. Real MCP clients send
POST; using QUERY instead would break interoperability with every existing client for a
semantic nicety this extension doesn't need standalone.