# `Anubis.Server.Notifier`

Sends notifications and server-initiated requests back to the client that
owns `frame`.

Every callback receives a `Anubis.Server.Frame`, and every frame carries
the pid of the Session serving it. These helpers use that pid, so they
work from **any** process: the Session itself, an application process, or
a task spawned inside a tool callback. That last case is why they exist.
`Anubis.Server.send_tools_list_changed/0` and its siblings use
`send(self(), ...)`, which is a no-op outside the Session process.

    defmodule MyApp.Tools.Reindex do
      use Anubis.Server.Component, type: :tool

      @impl true
      def execute(%{"job" => job}, frame) do
        MyApp.Reindex.run(job, fn step ->
          Notifier.progress(frame, step.token, step.done, total: step.total)
        end)

        {:reply, Response.tool("queued"), frame}
      end
    end

Notifications the client may have subscribed to are dropped by the
session when it should not receive them (see
`send_resource_updated/3`), exactly like their `Anubis.Server`
counterparts.

See `Anubis.Server.Context` for `session_pid` and `request_meta`, the two
fields these helpers read off the frame.

# `frame`

```elixir
@type frame() :: Anubis.Server.Frame.t()
```

A frame handed to a server callback.

# `elicitation_request`

```elixir
@spec elicitation_request(frame(), String.t(), map(), keyword()) ::
  :ok | {:error, term()}
```

Sends an `elicitation/create` request.

Asks the user for structured input. `requested_schema` is validated
before anything goes on the wire, and the session rejects the request if
the client did not declare the `elicitation` capability. The response
arrives at the server's `handle_elicitation/3` callback.

Per the MCP specification, servers MUST NOT use elicitation to request
sensitive information (credentials, payment details, anything the user
would not type in front of a stranger).

# `log_message`

```elixir
@spec log_message(frame(), Logger.level(), String.t(), map() | nil) :: :ok
```

Sends `notifications/log/message`. Requires the client to declare the `:logging` capability.

# `notify`

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

Sends an arbitrary notification to the client.

Every helper below is a wrapper over this. Use it directly for
notifications Anubis has no typed helper for.

    Notifier.notify(frame, "notifications/resources/updated", %{"uri" => uri})

# `progress`

```elixir
@spec progress(frame(), String.t() | non_neg_integer(), number(), keyword()) :: :ok
```

Sends `notifications/progress`.

The token normally comes from the request's own `_meta`:

    Notifier.progress(frame, frame.context.request_meta["progressToken"], 50, total: 100)

# `prompts_list_changed`

```elixir
@spec prompts_list_changed(frame()) :: :ok
```

Sends `notifications/prompts/list_changed`.

# `resource_updated`

```elixir
@spec resource_updated(frame(), String.t(), DateTime.t() | nil) :: :ok
```

Sends `notifications/resources/updated` for one resource.

Subscription-gated: the session drops it unless the client previously
sent `resources/subscribe` for this URI.

# `resources_list_changed`

```elixir
@spec resources_list_changed(frame()) :: :ok
```

Sends `notifications/resources/list_changed`.

# `roots_request`

```elixir
@spec roots_request(frame(), keyword()) :: :ok
```

Sends a `roots/list` request.

The response arrives at the server's `handle_roots/3` callback.

# `sampling_request`

```elixir
@spec sampling_request(frame(), [map()], keyword()) :: :ok
```

Sends a `sampling/createMessage` request.

The response arrives at the server's `handle_sampling/3` callback.

# `task_status`

```elixir
@spec task_status(frame(), String.t()) :: :ok
```

Sends a `notifications/tasks/status` carrying the current state of a task.

Looked up in the server's task store. Per spec (2025-11-25) receivers MAY
send these; requestors MUST NOT rely on them.

# `tools_list_changed`

```elixir
@spec tools_list_changed(frame()) :: :ok
```

Sends `notifications/tools/list_changed`.

---

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