# `ConduitMcp.Protocol`
[🔗](https://github.com/nyo16/conduit_mcp/blob/v0.10.1/lib/conduit_mcp/protocol.ex#L1)

JSON-RPC 2.0 message construction and MCP protocol version negotiation.

ConduitMCP targets MCP spec **2025-11-25** as the primary version and
also accepts clients on **2025-06-18** for backward compatibility.
`protocol_version/0` returns the preferred version; `negotiate_version/1`
resolves a client's requested version to one the server supports.

## Building responses

Helpers `success_response/2`, `error_response/3,4`, and `notification/2`
produce the right wire shape — string-keyed maps with `"jsonrpc"`,
`"id"`, and either `"result"` or `"error"`. `validate_request/1`
performs lightweight shape checking on incoming messages.

## Error codes

Standard JSON-RPC 2.0 codes and MCP-specific codes are exposed as
delegating functions to `ConduitMcp.Errors`:

- `parse_error/0`         → -32700
- `invalid_request/0`     → -32600
- `method_not_found/0`    → -32601
- `invalid_params/0`      → -32602
- `internal_error/0`      → -32603
- `server_error/0`        → -32000 (generic server-defined)
- `resource_not_found/0`  → -32002
- `task_not_ready/0`      → -32004 (`tasks/result` before completion)
- `request_cancelled/0`   → -32800 (`notifications/cancelled`)

Use these instead of hardcoded integers so error code constants stay
in one place.

## Examples

    iex> ConduitMcp.Protocol.success_response(1, %{"value" => 42})
    %{"jsonrpc" => "2.0", "id" => 1, "result" => %{"value" => 42}}

    iex> ConduitMcp.Protocol.error_response(1, -32601, "no such method")
    %{"jsonrpc" => "2.0", "id" => 1, "error" => %{"code" => -32601, "message" => "no such method"}}

# `error_object`

```elixir
@type error_object() :: %{code: integer(), message: String.t(), data: any() | nil}
```

# `error_response`

```elixir
@type error_response() :: %{
  jsonrpc: String.t(),
  id: json_rpc_id(),
  error: error_object()
}
```

# `json_rpc_id`

```elixir
@type json_rpc_id() :: String.t() | integer()
```

# `method`

```elixir
@type method() :: String.t()
```

# `notification`

```elixir
@type notification() :: %{jsonrpc: String.t(), method: method(), params: map() | nil}
```

# `request`

```elixir
@type request() :: %{
  jsonrpc: String.t(),
  id: json_rpc_id(),
  method: method(),
  params: map() | nil
}
```

# `response`

```elixir
@type response() :: success_response() | error_response()
```

# `success_response`

```elixir
@type success_response() :: %{jsonrpc: String.t(), id: json_rpc_id(), result: any()}
```

# `error_response`

Creates an error response.

# `internal_error`

# `invalid_params`

# `invalid_request`

# `method_not_found`

# `methods`

Core MCP methods as defined in the specification.

# `negotiate_version`

Returns the best matching protocol version for the given client version.
Returns `nil` if no compatible version is found.

# `notification`

Creates a notification message.

# `parse_error`

# `protocol_version`

# `request_cancelled`

# `resource_not_found`

# `success_response`

Creates a success response.

# `supported_versions`

# `task_not_ready`

# `valid_notification?`

Validates if a message is a valid JSON-RPC 2.0 notification.

# `valid_request?`

Validates if a message is a valid JSON-RPC 2.0 request.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
