Validates and casts decoded JSON-RPC messages into the GenMCP.MCP.V2607
struct vocabulary.
The transport decodes an incoming HTTP body into a plain map, then hands that
map to validate_request/1 before any dispatch happens. The validator checks
the message against the JSON Schema of the method it names, and on success
returns the matching protocol struct (for example a
GenMCP.MCP.V2607.CallToolRequest) together with whether the message is a
request or a notification. A message whose method is not recognized, or whose
body does not conform to the schema, is rejected before it reaches a handler.
The set of recognized methods is the request and notification surface of the
2026-07-28 protocol that the library currently serves. The full JSON Schema
root is assembled once at compile time, so validation at runtime is a lookup
by method followed by a single JSV.validate/3 call.
This module is used internally by GenMCP.Transport.StreamableHTTP. The single
public entry point is validate_request/1.
Summary
Functions
Validates a decoded JSON-RPC message and casts it to its protocol struct.
Functions
Validates a decoded JSON-RPC message and casts it to its protocol struct.
The argument is the full message map as decoded from the request body, carrying
at least a "method" key, and usually "jsonrpc", "id", and "params". The
method selects the schema to validate against, and the rest of the map is the
body that gets validated and cast.
On success the call returns {:ok, kind, cast}:
kindis:requestor:notification, telling the caller how to treat the message.castis the validatedGenMCP.MCP.V2607struct, with its fields already coerced (atom keys, decodedbyteformats, nested structs).
Two errors are possible:
{:error, {:unknown_method, method}}when no schema is registered for the method. This is checked before the body, so a map carrying only a"method"is enough to trigger it.{:error, {:invalid_body, jsv_error}}when the method is known but the body fails schema validation. Thejsv_erroris aJSV.ValidationErrorwhose message explains which property did not conform.
Examples
A tools/list request validates and casts to a
GenMCP.MCP.V2607.ListToolsRequest. The body is what a client sends, with the
protocol version and client info travelling in _meta as the protocol
requires (the cast struct is omitted here because it is deeply nested):
iex> GenMCP.Validator.validate_request(%{
...> "jsonrpc" => "2.0",
...> "id" => 1,
...> "method" => "tools/list",
...> "params" => %{
...> "_meta" => %{
...> "io.modelcontextprotocol/protocolVersion" => "2026-07-28",
...> "io.modelcontextprotocol/clientCapabilities" => %{},
...> "io.modelcontextprotocol/clientInfo" => %{
...> "name" => "my-client",
...> "version" => "1.0.0"
...> }
...> }
...> }
...> })
{:ok, :request,
%GenMCP.MCP.V2607.ListToolsRequest{
id: 1,
params: %GenMCP.MCP.V2607.PaginatedRequestParams{
_meta: %GenMCP.MCP.V2607.RequestMetaObject{
"io.modelcontextprotocol/clientCapabilities": %GenMCP.MCP.V2607.ClientCapabilities{
elicitation: nil,
experimental: nil,
extensions: nil,
roots: nil,
sampling: nil
},
"io.modelcontextprotocol/clientInfo": %GenMCP.MCP.V2607.Implementation{
description: nil,
icons: nil,
name: "my-client",
title: nil,
version: "1.0.0",
websiteUrl: nil
},
"io.modelcontextprotocol/logLevel": nil,
"io.modelcontextprotocol/protocolVersion": "2026-07-28",
progressToken: nil
},
cursor: nil
}
}}An unrecognized method is rejected before its body is even looked at:
iex> GenMCP.Validator.validate_request(%{"method" => "bogus/method"})
{:error, {:unknown_method, "bogus/method"}}