Wymcp.Plugs.Dispatch (Wymcp v0.1.1)

View Source

The method surface of both eras: routes a validated message to the module that answers it. The last plug in Wymcp.Plugs.Pipeline.

Three branches, in clause order. A JSON-RPC response — a client's answer to a server-initiated request — is delivered to the session that minted its id. A modern-classified message takes the modern lane. Everything else takes the legacy lane.

The modern lane

server/discover, tools/list and tools/call — the whole modern method surface. An unknown modern method answers HTTP 404 plus -32601: the spec's MUST, and deliberately distinguishable from a legacy HTTP+SSE server's 404. Wymcp.Response.send_json/2 preserves a previously-set status, which is why one method module serves both eras' unknown-method bodies while only this lane sets 404.

A modern notification never reaches a method: the modern core defines no client→server notification over HTTP, and JSON-RPC forbids an error response to a notification — so it is answered 202 and dropped, whatever its body. That is also why Wymcp.Plugs.Validate lets it through unvalidated.

The legacy lane

initialize, notifications/initialized, ping, tools/list, tools/call, logging/setLevel and notifications/cancelled. Anything else falls through to the same unknown-method module with no status override, so it answers -32601 in a 200 envelope.

The tool list this plug passes on is the router's compile-time :tools option: Wymcp.Router copies its init options into conn.assigns[:wymcp], and this plug reads them from there. That list is a starting point, not the effective one — each method module resolves the effective list itself. On the legacy lane the tools/list and tools/call modules re-read the session's registered tools, so a runtime Wymcp.Session.register_tool/2 wins there; the modern lane is stateless, has no session to consult, and serves the compile-time list as passed.