# `Snodo.Roots`
[🔗](https://github.com/joshrotenberg/snodo/blob/v0.4.1/lib/snodo/roots.ex#L1)

Builds and validates embedded `roots/list` requests for MRTR.

SEP-2577 deprecates server-initiated roots listing in MCP 2026-07-28. The
method is still defined by the protocol schema and scored by the official
conformance runner, so a 2026-07-28 handler may return one as an input
request through `Snodo.Result.input_required/1`, next to elicitation.

`list/0` returns a bare input request, without a JSON-RPC envelope. Use
`response/3` on a retried request to read only the named `ListRootsResult`.
The dialect refuses the request with `-32021` when the client has not
declared `roots`. Each root URI must start with `file://`, as the 2026-07-28
schema requires. The client chooses which roots to reveal, and a root is a
claim about the client's file system, not an access grant: check every path
an application derives from one against its own authorization.

# `request`

```elixir
@type request() :: %{required(String.t()) =&gt; term()}
```

# `response_result`

```elixir
@type response_result() :: :missing | {:ok, map()} | {:error, Snodo.Error.t()}
```

# `list`

```elixir
@spec list() :: request()
```

Builds a roots input request.

# `response`

```elixir
@spec response(Snodo.Context.t() | map(), String.t(), request()) :: response_result()
```

Reads and validates the named response, ignoring unrelated response IDs.

A valid response is a `ListRootsResult`: a `"roots"` list whose entries
carry a `file://` `"uri"` and an optional `"name"`. Invalid responses return
a generic invalid-params error without the submitted data. Additional JSON
fields are preserved and ignored. This helper does not authenticate content
or trust client-echoed request state.

# `supported?`

```elixir
@spec supported?(term(), term()) :: boolean()
```

Checks the request against this request's client capabilities.

# `valid_response?`

```elixir
@spec valid_response?(term()) :: boolean()
```

Checks that `response` is a `ListRootsResult`.

That is a `"roots"` list, possibly empty, whose entries carry a `file://`
`"uri"` and an optional `"name"`. Additional JSON fields are allowed.
`Snodo.Client` applies it to what a roots handler returns.

# `validate_request`

```elixir
@spec validate_request(term()) :: :ok | {:error, String.t()}
```

Validates one bare roots input request.

The schema makes `params` optional; when present it may carry only `_meta`,
itself an object.

---

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