MCP — INBOUND: serve a toolkit as an MCP server (SPEC §7C).
The inbound mirror of the A2A serve (§7B). Where A2A advertises the
toolkit's skills and fulfils a Task through the whole client loop, MCP
advertises the toolkit's unified tools (every source) and dispatches
each tools/call straight to Tool.execute. The calling MCP client is
the LLM host, so there is no client, no Task, and no TaskStore — just
tools/list + tools/call over the toolkit registry.
Transport: streamable-HTTP, mounted at POST /mcp on the
Toolnexus.Serve server alongside the A2A routes (stateless — no session).
Deferred per §7C: stdio, resources, prompts, sampling.
Summary
Functions
The tools the MCP profile exposes: every toolkit tool, filtered to the
profile's tools list when set (unknown names in the filter are ignored,
never an error).
Handle one streamable-HTTP MCP request (/mcp). Stateless: each POST is a
self-contained JSON-RPC exchange; notifications are accepted with 202.
Non-POST methods answer 405 (like the JS SDK's stateless transport).
Functions
@spec exposed_tools([Toolnexus.Tool.t()], map() | nil) :: [Toolnexus.Tool.t()]
The tools the MCP profile exposes: every toolkit tool, filtered to the
profile's tools list when set (unknown names in the filter are ignored,
never an error).
@spec handle_http( Plug.Conn.t(), [Toolnexus.Tool.t()], map() | nil, (map() -> any()) | nil ) :: Plug.Conn.t()
Handle one streamable-HTTP MCP request (/mcp). Stateless: each POST is a
self-contained JSON-RPC exchange; notifications are accepted with 202.
Non-POST methods answer 405 (like the JS SDK's stateless transport).