The JSON-RPC 2.0 envelope of the MCP transport: classifying a decoded request body and building and sending answers.
classify/1 takes conn.body_params as PhoenixKit.API.BodyGuard (or
Plug.Parsers) left it: a map, where a JSON array or scalar is wrapped as
%{"_json" => value}, and a request with no body at all is
%Plug.Conn.Unfetched{} or %{}. It returns:
{:request, id, method, params}: an object with"jsonrpc": "2.0", a stringmethodand anidthat is a string or an integer.paramsis whatever the client sent (nilwhen absent);{:notification, method}: the same without anid. Whatever the method: a notification gets no answer and must not run anything;:response: aresultorerrorwith anid, which a client sends back to a server request (this server sends none);{:invalid, id_or_nil, text}: everything else, among it a batch (MCP revision 2025-06-18 removed batching), a bare scalar, an empty object, a wrongjsonrpc, anull, float or booleanid. Theidis echoed when the message had a usable one.
It never raises.
Summary
Functions
202 Accepted with no body: the answer to a notification or a response.
Classifies a decoded request body, see the moduledoc.
The JSON-RPC error code of name (:parse_error, :invalid_request, :method_not_found, :invalid_params, :internal_error).
The error envelope. id is nil when the request had no usable id.
The success envelope.
Sends a JSON-RPC error with HTTP status and halts. name is one of the
atoms of code/1.
Sends body as JSON with status. Not halted.
Types
Functions
@spec accepted(Plug.Conn.t()) :: Plug.Conn.t()
202 Accepted with no body: the answer to a notification or a response.
Classifies a decoded request body, see the moduledoc.
The JSON-RPC error code of name (:parse_error, :invalid_request, :method_not_found, :invalid_params, :internal_error).
The error envelope. id is nil when the request had no usable id.
The success envelope.
@spec send_error(Plug.Conn.t(), pos_integer(), id() | nil, atom(), String.t()) :: Plug.Conn.t()
Sends a JSON-RPC error with HTTP status and halts. name is one of the
atoms of code/1.
@spec send_json(Plug.Conn.t(), pos_integer(), map()) :: Plug.Conn.t()
Sends body as JSON with status. Not halted.