Wymcp. Plugs. Dispatch
(Wymcp v0.4.0)
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 mount module's mount tools —
its :tools option — together with the definitions Wymcp.Router.init/1
built for them, which are tools/list's alone: tools/call is handed the
tool list and nothing else. Wymcp.Router copies its init options into
conn.assigns[:wymcp], and this plug reads both 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 mount list as passed. A tool
registered on a live session has no stored definition — no registration
moment saw it — so tools/list builds that one itself: a legacy-only
path, since only the legacy lane resolves its tools through a session, and
it goes with the era branch at the decommission.