Noizu.MCP.Ctx (Noizu MCP v0.1.3)

Copy Markdown View Source

Per-request handler context.

Every server handler receives a %Noizu.MCP.Ctx{} carrying session identity, the negotiated protocol version, client info/capabilities, and assigns. Use it to report progress, emit MCP log messages, and check for cooperative cancellation.

Handlers do not return an updated context — handler invocations run concurrently per session. assign/3 is local to the current invocation; use put_session/3 to persist a value into the session's assigns for subsequent requests.

Summary

Functions

Put a value in this invocation's local assigns.

True when the client cancelled the current request.

Emit a debug MCP log message. See log/4.

Ask the user (via the client) for structured input (elicitation/create).

Emit a error MCP log message. See log/4.

Extract the %Ctx{} previously stashed in a Noizu.Context record's options.

Emit a info MCP log message. See log/4.

Ask the client for its filesystem roots (roots/list).

Emit an MCP notifications/message log entry to the client, filtered by the level the client set via logging/setLevel. data may be any JSON-serializable term. Options: :logger (a logical logger name).

Persist a value into the session's assigns so subsequent requests in this session observe it. Serialized through the session process (atomic), but last-write-wins across concurrently running handlers.

Report progress for the current request. Silently no-ops when the client did not send a progressToken. Options: :total, :message.

Ask the client to sample an LLM completion (sampling/createMessage).

Build a Noizu.Context record from this MCP context, stashing the full %Ctx{} under the :mcp_ctx option key. Pass an optional caller ref to override the default :system identity.

Emit a warning MCP log message. See log/4.

Types

t()

@type t() :: %Noizu.MCP.Ctx{
  assigns: map(),
  cancel_flag: :atomics.atomics_ref() | nil,
  client_capabilities: map(),
  client_info: Noizu.MCP.Types.Implementation.t() | nil,
  progress_token: term() | nil,
  protocol_version: String.t() | nil,
  request_id: Noizu.MCP.JsonRpc.id() | nil,
  server: module(),
  session: pid() | nil,
  session_id: String.t() | nil,
  transport: atom()
}

Functions

assign(ctx, key, value)

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

Put a value in this invocation's local assigns.

cancelled?(ctx)

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

True when the client cancelled the current request.

By default the runtime kills the handler task on cancellation, so most handlers never need this; poll it from handlers that must clean up external state at a safe point.

debug(ctx, data, opts \\ [])

@spec debug(t(), term(), keyword()) :: :ok

Emit a debug MCP log message. See log/4.

elicit(ctx, message, requested_schema, opts \\ [])

@spec elicit(t(), String.t(), map(), keyword()) ::
  {:ok, {:accept, map()} | :decline | :cancel} | {:error, term()}

Ask the user (via the client) for structured input (elicitation/create).

requested_schema is a flat-object JSON Schema map (string keys). Returns {:ok, {:accept, content}}, {:ok, :decline}, or {:ok, :cancel}.

{:ok, {:accept, %{"confirm" => true}}} =
  Noizu.MCP.Ctx.elicit(ctx, "Really delete 14 rows?", %{
    "type" => "object",
    "properties" => %{"confirm" => %{"type" => "boolean"}},
    "required" => ["confirm"]
  })

error(ctx, data, opts \\ [])

@spec error(t(), term(), keyword()) :: :ok

Emit a error MCP log message. See log/4.

from_context(context)

@spec from_context(
  {:context, caller :: term(), ts :: term(), token :: term(), reason :: term(),
   roles :: term(), options :: term()}
) :: {:ok, t()} | {:error, {:no_option, :mcp_ctx}}

Extract the %Ctx{} previously stashed in a Noizu.Context record's options.

info(ctx, data, opts \\ [])

@spec info(t(), term(), keyword()) :: :ok

Emit a info MCP log message. See log/4.

list_roots(ctx, opts \\ [])

@spec list_roots(
  t(),
  keyword()
) :: {:ok, [Noizu.MCP.Types.Root.t()]} | {:error, term()}

Ask the client for its filesystem roots (roots/list).

log(ctx, level, data, opts \\ [])

@spec log(t(), atom(), term(), keyword()) :: :ok

Emit an MCP notifications/message log entry to the client, filtered by the level the client set via logging/setLevel. data may be any JSON-serializable term. Options: :logger (a logical logger name).

put_session(ctx, key, value)

@spec put_session(t(), atom(), term()) :: :ok

Persist a value into the session's assigns so subsequent requests in this session observe it. Serialized through the session process (atomic), but last-write-wins across concurrently running handlers.

report_progress(ctx, progress, opts \\ [])

@spec report_progress(t(), number(), keyword()) :: :ok

Report progress for the current request. Silently no-ops when the client did not send a progressToken. Options: :total, :message.

sample(ctx, params, opts \\ [])

@spec sample(t(), map(), keyword()) :: {:ok, map()} | {:error, term()}

Ask the client to sample an LLM completion (sampling/createMessage).

params is the wire-format map: "messages", "maxTokens", and optionally "systemPrompt", "modelPreferences", "tools"/"toolChoice" (2025-11-25). Blocks the calling handler task only. Options: :timeout (default 60s).

{:ok, %{"content" => %{"text" => text}}} =
  Noizu.MCP.Ctx.sample(ctx, %{
    "messages" => [
      %{"role" => "user", "content" => %{"type" => "text", "text" => "Summarize: ..."}}
    ],
    "maxTokens" => 500
  })

to_context(ctx, caller \\ nil)

@spec to_context(t(), term()) ::
  {:context, caller :: term(), ts :: term(), token :: term(), reason :: term(),
   roles :: term(), options :: term()}

Build a Noizu.Context record from this MCP context, stashing the full %Ctx{} under the :mcp_ctx option key. Pass an optional caller ref to override the default :system identity.

warning(ctx, data, opts \\ [])

@spec warning(t(), term(), keyword()) :: :ok

Emit a warning MCP log message. See log/4.