# `Urchin.Context`
[🔗](https://github.com/urth-inc/urchin/blob/v0.4.0/lib/urchin/context.ex#L1)

The request context handed to every server handler.

Besides carrying the negotiated session metadata and the user state from
`c:Urchin.Server.init/1`, the context exposes the side-effecting capabilities a
handler may use while processing a request:

  * progress and log notifications related to the in-flight request
  * server-initiated requests to the client: sampling, elicitation, roots
  * a best-effort cancellation check

Notifications and server-initiated requests are emitted on the stream that carries
the originating request, as required by the transport spec.

# `t`

```elixir
@type t() :: %Urchin.Context{
  assigns: map(),
  auth: Urchin.Auth.Claims.t() | nil,
  cancelled_ref: reference() | nil,
  client_capabilities: map() | nil,
  client_info: map() | nil,
  expose_internal_errors: boolean(),
  initialized: boolean(),
  min_log_level: String.t(),
  owner: pid() | nil,
  params: map(),
  progress_token: String.t() | number() | nil,
  protocol_version: String.t() | nil,
  request_id: Urchin.JSONRPC.id() | nil,
  session: pid() | nil,
  state: term(),
  uri: String.t() | nil
}
```

# `assign`

```elixir
@spec assign(t(), atom(), term()) :: t()
```

Stores a value in the context assigns.

# `auth`

```elixir
@spec auth(t()) :: Urchin.Auth.Claims.t() | nil
```

Returns the validated OAuth claims for the originating request, or `nil`.

Populated only when the transport is configured with `:auth` (or an upstream
`Urchin.Auth.Plug` ran). Handlers use it for per-tool authorization:

    if Urchin.Auth.Claims.has_scope?(Urchin.Context.auth(ctx), "files:write") do
      # ...
    end

# `cancelled?`

```elixir
@spec cancelled?(t()) :: boolean()
```

Returns true if the originating request has been cancelled by the client.

Cancellation also terminates the handler process, so this is a cooperative,
best-effort check for long-running loops.

# `create_message`

```elixir
@spec create_message(t(), map(), timeout()) ::
  {:ok, map()} | {:error, Urchin.Error.t()}
```

Issues a `sampling/createMessage` request to the client and waits for the result.

Returns `{:ok, result_map}` or `{:error, Urchin.Error.t()}`. Returns an error without
contacting the client when it did not advertise the `sampling` capability.

# `elicit`

```elixir
@spec elicit(t(), map(), timeout()) :: {:ok, map()} | {:error, Urchin.Error.t()}
```

Issues an `elicitation/create` request to the client and waits for the result.

Returns `{:ok, result_map}` or `{:error, Urchin.Error.t()}`. Returns an error without
contacting the client when it did not advertise the `elicitation` capability.

# `list_roots`

```elixir
@spec list_roots(t(), timeout()) :: {:ok, map()} | {:error, Urchin.Error.t()}
```

Issues a `roots/list` request to the client and waits for the result.

Returns `{:ok, %{"roots" => [...]}}` or `{:error, Urchin.Error.t()}`. Returns an error
without contacting the client when it did not advertise the `roots` capability.

# `log`

```elixir
@spec log(t(), String.t(), term(), keyword()) :: :ok
```

Sends a `notifications/message` log entry to the client.

Messages below the level requested by the client via `logging/setLevel` are
dropped. `level` is one of ["debug", "info", "notice", "warning", "error", "critical", "alert", "emergency"].

## Options
  * `:logger` - optional logger name

# `log_levels`

```elixir
@spec log_levels() :: [String.t()]
```

Returns the valid MCP log levels, in increasing severity order.

# `notify`

```elixir
@spec notify(t(), String.t(), map() | nil) :: :ok
```

Sends an arbitrary JSON-RPC notification on the originating request stream.

# `progress`

```elixir
@spec progress(t(), number(), keyword()) :: :ok
```

Sends a progress notification for the originating request.

No-op when the client did not supply a `progressToken` for the request.

## Options
  * `:total` - total units of work, if known
  * `:message` - human-readable progress message

# `request`

```elixir
@spec request(t(), String.t(), map() | nil, timeout()) ::
  {:ok, map()} | {:error, Urchin.Error.t()}
```

Issues an arbitrary server-to-client request and blocks until the client responds.

The request is written to the originating request's stream; the matching response,
delivered on a later client POST, is correlated by the session.

# `state`

```elixir
@spec state(t()) :: term()
```

Returns the user state established by `c:Urchin.Server.init/1`.

---

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