# `Anubis.Transport.Behaviour`

Defines the behaviour that all transport implementations must follow.

Two kinds of callbacks:

  * **Process callbacks** (`start_link/1`, `send_message/3`, `shutdown/1`) —
    the GenServer-oriented I/O contract, required.
  * **Functional callbacks** (`transport_init/1`, `parse/2`, `encode/2`,
    `extract_metadata/2`) — pure message framing used when the transport
    owns a parse state (newline-delimited JSON, SSE chunks, HTTP bodies).
    Optional; the client checks `function_exported?/3` before using them.

# `message`

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

The JSON-RPC message encoded

# `raw_message`

```elixir
@type raw_message() :: binary()
```

# `reason`

```elixir
@type reason() :: term() | Anubis.MCP.Error.t()
```

# `t`

```elixir
@type t() :: GenServer.server()
```

# `transport_state`

```elixir
@type transport_state() :: term()
```

# `encode`
*optional* 

```elixir
@callback encode(message :: map(), transport_state()) ::
  {:ok, raw_message(), transport_state()} | {:error, term()}
```

Encode an MCP message map for this transport's wire format.

Returns the encoded binary ready to be sent.

# `extract_metadata`
*optional* 

```elixir
@callback extract_metadata(raw_input :: term(), transport_state()) :: map()
```

Extract transport-specific metadata from raw input.

For HTTP, this extracts session_id from headers, request context, etc.
For STDIO, this returns basic process metadata.

# `parse`
*optional* 

```elixir
@callback parse(raw_message() | map(), transport_state()) ::
  {:ok, [map()], transport_state()} | {:error, term()}
```

Parse raw input into decoded MCP message(s).

For STDIO, raw input is newline-delimited JSON.
For HTTP, raw input is a JSON body string or already-parsed map.
For SSE, raw input is SSE event data.

# `send_message`

```elixir
@callback send_message(t(), message(), [opt]) :: :ok | {:error, reason()}
when opt: {:timeout, pos_integer()} | {:session_id, String.t()}
```

# `shutdown`

```elixir
@callback shutdown(t()) :: :ok | {:error, reason()}
```

# `start_link`

```elixir
@callback start_link(keyword()) :: GenServer.on_start()
```

# `supported_protocol_versions`

```elixir
@callback supported_protocol_versions() :: [String.t()] | :all
```

Returns the list of MCP protocol versions supported by this transport.

## Examples

    iex> MyTransport.supported_protocol_versions()
    ["2025-03-26", "2025-06-18"]

# `transport_init`
*optional* 

```elixir
@callback transport_init(keyword()) :: {:ok, transport_state()} | {:error, term()}
```

Initialize transport-specific state (parse options, configure connection).

---

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