Anubis. MCP. Error
(anubis_mcp v2.2.0)
Copy Markdown
Fluent API for building MCP protocol errors.
This module provides a semantic interface for creating errors that comply with the MCP specification and JSON-RPC 2.0 error standards.
Error Categories
- Protocol Errors: Standard JSON-RPC errors (parse, invalid request, etc.)
- Transport Errors: Connection and communication issues
- Resource Errors: MCP-specific resource handling errors
- Execution Errors: Tool and operation execution failures
Error code ranges
MCP partitions the JSON-RPC implementation-defined range: -32000 to
-32019 holds codes allocated before the policy existed (such as -32002
for a missing resource, and the generic -32000 used by transport and
execution errors), while -32020 to -32099 is reserved for codes the
specification defines.
Examples
# Protocol errors
Anubis.MCP.Error.protocol(:parse_error)
Anubis.MCP.Error.protocol(:method_not_found, %{method: "unknown"})
# Transport errors
Anubis.MCP.Error.transport(:connection_refused)
Anubis.MCP.Error.transport(:timeout, %{elapsed_ms: 30000})
# Resource errors
Anubis.MCP.Error.resource(:not_found, %{uri: "file:///missing.txt"})
# Reserved errors whose payload the specification pins down
Anubis.MCP.Error.unsupported_protocol_version("1900-01-01", ["2026-07-28"])
Anubis.MCP.Error.missing_required_client_capability(%{"elicitation" => %{}})
Anubis.MCP.Error.url_elicitation_required([%{"mode" => "url", "elicitationId" => "1", "url" => "https://example.com", "message" => "Authorize"}])
# Execution errors with custom messages
Anubis.MCP.Error.execution("Database connection failed", %{retries: 3})
# Converting from JSON-RPC
Anubis.MCP.Error.from_json_rpc(%{"code" => -32700, "message" => "Parse error"})
Summary
Functions
Creates an execution error with a custom message.
Creates an error from a JSON-RPC error object.
Creates a MissingRequiredClientCapability error for a request that needs a
capability the client did not declare.
Creates a protocol-level error.
Creates a resource-specific error.
Creates a resource-not-found error for a protocol era.
Encodes the error as a JSON-RPC error response.
Creates a transport-level error.
Creates an UnsupportedProtocolVersion error for a version this peer does
not implement.
Creates a URLElicitationRequiredError for a request that cannot proceed
until the user completes an out-of-band interaction.
Wraps an arbitrary failure reason as an encodable MCP error.
Types
Functions
Creates an execution error with a custom message.
Used for tool execution failures and domain-specific errors.
Examples
iex> Anubis.MCP.Error.execution("Database connection failed")
%Anubis.MCP.Error{code: -32000, reason: :execution_error, message: "Database connection failed", data: %{}}
iex> Anubis.MCP.Error.execution("API rate limit exceeded", %{retry_after: 60})
%Anubis.MCP.Error{code: -32000, reason: :execution_error, message: "API rate limit exceeded", data: %{retry_after: 60}}
Creates an error from a JSON-RPC error object.
Examples
iex> Anubis.MCP.Error.from_json_rpc(%{"code" => -32700, "message" => "Parse error"})
%Anubis.MCP.Error{code: -32700, reason: :parse_error, message: "Parse error", data: %{}}
iex> Anubis.MCP.Error.from_json_rpc(%{"code" => -32002, "message" => "Not found", "data" => %{"uri" => "/file"}})
%Anubis.MCP.Error{code: -32002, reason: :resource_not_found, message: "Not found", data: %{"uri" => "/file"}}
Creates a MissingRequiredClientCapability error for a request that needs a
capability the client did not declare.
capabilities is a ClientCapabilities map — the capabilities required to
process the request, not a list of their names.
Examples
iex> Anubis.MCP.Error.missing_required_client_capability(%{"elicitation" => %{}})
%Anubis.MCP.Error{code: -32021, reason: :missing_required_client_capability, message: "Missing required client capability", data: %{requiredCapabilities: %{"elicitation" => %{}}}}
Creates a protocol-level error.
These are standard JSON-RPC errors that occur during message parsing and validation.
Supported Reasons
:parse_error- Invalid JSON was received:invalid_request- The JSON is not a valid Request object:method_not_found- The method does not exist:invalid_params- Invalid method parameters:internal_error- Internal JSON-RPC error:header_mismatch- Transport headers disagree with the request body:missing_required_client_capability- The request needs a capability the client did not declare:unsupported_protocol_version- The requested protocol version is not implemented
Examples
iex> Anubis.MCP.Error.protocol(:parse_error)
%Anubis.MCP.Error{code: -32700, reason: :parse_error, message: "Parse error", data: %{}}
iex> Anubis.MCP.Error.protocol(:method_not_found, %{method: "foo"})
%Anubis.MCP.Error{code: -32601, reason: :method_not_found, message: "Method not found", data: %{method: "foo"}}
iex> Anubis.MCP.Error.protocol(:unsupported_protocol_version, %{supported: ["2026-07-28"], requested: "1900-01-01"})
%Anubis.MCP.Error{code: -32022, reason: :unsupported_protocol_version, message: "Unsupported protocol version", data: %{supported: ["2026-07-28"], requested: "1900-01-01"}}
Creates a resource-specific error.
Used for MCP resource operations.
Examples
iex> Anubis.MCP.Error.resource(:not_found, %{uri: "file:///missing.txt"})
%Anubis.MCP.Error{code: -32002, reason: :resource_not_found, message: "Resource not found", data: %{uri: "file:///missing.txt"}}
@spec resource_not_found(map(), Anubis.Protocol.Behaviour.era()) :: t()
Creates a resource-not-found error for a protocol era.
Revision 2026-07-28 reallocates this condition from the MCP-specific
-32002 to the JSON-RPC -32602, and reserves -32002 so it is never
reused. Legacy eras keep the code they shipped with. Only the code differs:
the reason stays :resource_not_found in every era, so code that matches on
it, such as the resource-template fallback, treats both eras alike.
Examples
iex> Anubis.MCP.Error.resource_not_found(%{uri: "file:///missing.txt"}, :legacy).code
-32002
iex> Anubis.MCP.Error.resource_not_found(%{uri: "file:///missing.txt"}, :stateless).code
-32602
Encodes the error as a JSON-RPC error response.
Examples
iex> error = Anubis.MCP.Error.protocol(:parse_error)
iex> {:ok, encoded} = Anubis.MCP.Error.to_json_rpc(error, "req-123")
iex> String.contains?(encoded, "Parse error")
true
Creates a transport-level error.
Used for network, connection, and communication failures.
Examples
iex> Anubis.MCP.Error.transport(:connection_refused)
%Anubis.MCP.Error{code: -32000, reason: :connection_refused, message: "Connection Refused", data: %{}}
iex> Anubis.MCP.Error.transport(:timeout, %{elapsed_ms: 5000})
%Anubis.MCP.Error{code: -32000, reason: :timeout, message: "Timeout", data: %{elapsed_ms: 5000}}
Creates an UnsupportedProtocolVersion error for a version this peer does
not implement.
The specification requires the data payload to carry both the versions
this peer supports and the version that was requested, so prefer this over
protocol/2 to build the payload for you.
Raises when supported holds anything other than version strings — a guard
cannot express that, and a non-string entry would serialize a payload the
specification does not allow.
Examples
iex> Anubis.MCP.Error.unsupported_protocol_version("1900-01-01", ["2026-07-28"])
%Anubis.MCP.Error{code: -32022, reason: :unsupported_protocol_version, message: "Unsupported protocol version", data: %{supported: ["2026-07-28"], requested: "1900-01-01"}}
Creates a URLElicitationRequiredError for a request that cannot proceed
until the user completes an out-of-band interaction.
elicitations is a list of URL-mode elicitation/create params, each with
at least mode, elicitationId, url and message. The specification
requires every entry to be URL mode, so a form-mode entry raises.
Examples
iex> Anubis.MCP.Error.url_elicitation_required([
...> %{
...> "mode" => "url",
...> "elicitationId" => "550e8400",
...> "url" => "https://example.com/authorize",
...> "message" => "Authorization is required"
...> }
...> ])
%Anubis.MCP.Error{code: -32042, reason: :url_elicitation_required, message: "URL elicitation required", data: %{"elicitations" => [%{"mode" => "url", "elicitationId" => "550e8400", "url" => "https://example.com/authorize", "message" => "Authorization is required"}]}}
Wraps an arbitrary failure reason as an encodable MCP error.
Passes through existing %Error{} values (including those returned from
init/2). Other terms are converted to an internal error with a string
message safe for JSON encoding.
Examples
iex> error = Anubis.MCP.Error.protocol(:invalid_params, %{message: "bad input"})
iex> Anubis.MCP.Error.wrap_reason(error)
%Anubis.MCP.Error{code: -32602, reason: :invalid_params, message: "Invalid params", data: %{message: "bad input"}}
iex> wrapped = Anubis.MCP.Error.wrap_reason({:init_failed, %{code: "unauthorized"}})
iex> wrapped.reason
:internal_error
iex> wrapped.data.message
"init_failed: %{code: \"unauthorized\"}"