# `AttestoMCP.Server.API`
[🔗](https://github.com/XukuLLC/attesto_mcp_server/blob/v2.8.0/lib/attesto_mcp_server.ex#L1)

Stable host-facing facade for `AttestoMCP.Server`.

Registration is performed before serving traffic. Definitions use JSON-style
string keys for schemas and wire values. Handler callbacks receive a
primitive-specific input plus an authorization context and return
`{:ok, result}`, `{:error, reason}`, or the modern
`{:input_required, requests}` MRTR form.

The facade intentionally exposes no task profile in this release. Calls that
would enable modern or legacy Tasks return the dated method-not-found result.

Two-arity handler callbacks use `handler.(input, context)`; one-arity handlers
receive only `input`, and MFA handlers follow the same input/context order. A
tool's input is its arguments map. A prompt receives
`%{name: name, arguments: arguments}`. A resource receives
`%{uri: uri, params: template_params}`, and a completion receives
`%{ref: ref, argument: argument, value: value, context: context}`. These
envelopes use atom keys for their declared fields; a resource MRTR retry also
carries its string-keyed input-response entries at the top level. Nested MCP
values retain their JSON string keys by default. The server-wide
`tool_argument_keys: :atoms` opt-in converts only literal, schema-declared
property keys that already exist as atoms; it never creates atoms from
schemas or client input. The callback context contains the
complete authenticated principal, tenant, scopes, transport, negotiated
version, request ID, `trace_context`, progress callback, and an optional
stable `:principal_binding` supplied by the transport. The HTTP Plug always
supplies that field, defaulting it to the complete principal when no binding
callback is configured. It also supplies the Attesto assigns (`:attesto_mcp_claims`,
`:attesto_mcp_scopes`, `:attesto_mcp_sender`, `:attesto_mcp_principal`, and
`:attesto_context`) when the Plug boundary is used. The context also exposes
the supervised server's `:max_json_bytes`, `:output_canonicalization`, and
`:tool_argument_keys` values, and `:request_meta`, an immutable snapshot of
the request's untrusted `params["_meta"]` object (see
`AttestoMCP.Server.RequestMeta`). `AttestoMCP.Server.Result.tool_from_context/2,3`
consumes the first two automatically; low-level constructors can still use
them as explicit options. A successful callback
returns `{:ok, result}`, an application failure returns `{:error, reason}`,
and an interactive callback returns `{:input_required, request_map}` with
typed MRTR request entries. An HTTP `context_builder` contributes only the
nested `:host_context` map. Use `AttestoMCP.Server.Result.error/2` when an
error message and stable code are intentionally safe to disclose.
`:instructions_provider` and `:tool_presentation` customize server guidance
and visible tool descriptors for the current caller
(`AttestoMCP.Server.Presentation`); `:cache_policy` selects cache hints by
operation and definition (`AttestoMCP.Server.CachePolicy`); `:server_icons`
adds icons to the server's implementation identity; and
`export_schema_dialect: true` makes the default JSON Schema 2020-12 dialect
explicit in exported tool schemas without changing validation.
For interactive workflows with `mode: "url"`, `AttestoMCP.Server.API` provides
staged, single-use, subject-bound approval records via `stage_url_elicitation/5`,
`resolve_url_elicitation/3`, and `consume_url_elicitation/3`.

# `cache_scope`

```elixir
@type cache_scope() :: :private | :public | String.t()
```

A cache scope; string values are restricted to `"private"` or `"public"`.

# `content_item`

```elixir
@type content_item() :: map()
```

A text, image, audio, resource-link, or embedded-resource item.

# `definition`

```elixir
@type definition() :: map() | keyword()
```

A registered primitive definition with JSON-compatible fields. `required_scopes` is the primary all-of clause and `alternative_scope_sets` supplies bounded alternative all-of clauses.

# `handler_context`

```elixir
@type handler_context() :: map()
```

Authorization and transport context passed to handlers.

# `handler_return`

```elixir
@type handler_return() ::
  {:ok, term()}
  | {:error, term()}
  | {:input_required, %{optional(String.t()) =&gt; map()}}
```

A normal, failed, or interactive handler return.

# `host_callback`

```elixir
@type host_callback() :: function() | {module(), atom()} | {module(), atom(), list()}
```

A host callback: a function, `{module, function}`, or `{module, function, prefix_args}`.

# `icon`

```elixir
@type icon() :: %{optional(atom() | String.t()) =&gt; String.t() | [String.t()]}
```

An MCP icon. `src` is an absolute HTTP/HTTPS URL or a Base64 `data:` URI with an
`image/*` media type; `mimeType` (or `mime_type`), `sizes` (`"WxH"` or
`"any"`), and `theme` (`"light"` or `"dark"`) are optional.

# `modern_result`

```elixir
@type modern_result() :: map()
```

A modern result carrying resultType and protocol metadata.

# `mrtr_payload`

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

Interactive request-state and input-response payloads.

# `prompt_message`

```elixir
@type prompt_message() :: map()
```

A prompt message with a user or assistant role and content item.

# `publish_option`

```elixir
@type publish_option() :: {:authorize, (map() -&gt; boolean())}
```

A per-publication authorization callback applied to every matching subscriber.

# `registration`

```elixir
@type registration() :: {atom(), String.t(), map() | keyword()}
```

One primitive registration accepted by the atomic batch and startup APIs.

# `request`

```elixir
@type request() :: map()
```

A decoded JSON-RPC request, notification, or response.

# `resource_content`

```elixir
@type resource_content() :: map()
```

A text or Base64 resource content entry.

# `scope_set`

```elixir
@type scope_set() :: [String.t()]
```

One conjunctive scope clause used by a primitive definition.

# `server`

```elixir
@type server() :: pid() | atom()
```

A supervised server pid or a registered server name.

# `server_option`

```elixir
@type server_option() ::
  {:name, atom()}
  | {:protocol_versions, [String.t()]}
  | {:max_concurrency, pos_integer()}
  | {:per_principal_concurrency, pos_integer()}
  | {:request_timeout, non_neg_integer()}
  | {:max_request_timeout, pos_integer()}
  | {:client_request_timeout, pos_integer()}
  | {:legacy_initialized_grace_ms, non_neg_integer()}
  | {:session_idle_timeout, pos_integer()}
  | {:session_absolute_timeout, pos_integer()}
  | {:max_sessions_per_principal, pos_integer()}
  | {:max_legacy_streams_per_session, pos_integer()}
  | {:max_json_bytes, pos_integer()}
  | {:output_canonicalization, :strict | :json | :jason}
  | {:tool_argument_keys, :strings | :atoms}
  | {:max_body_bytes, pos_integer()}
  | {:max_message_bytes, pos_integer()}
  | {:max_queue, pos_integer()}
  | {:stream_keepalive_ms, non_neg_integer()}
  | {:legacy_keepalive_ms, non_neg_integer()}
  | {:stream_queue_size, pos_integer()}
  | {:subscription_queue_size, pos_integer()}
  | {:rate_limits, map()}
  | {:cursor_secret, binary()}
  | {:cursor_ttl, pos_integer()}
  | {:request_state_secret, binary()}
  | {:request_state_instance, binary()}
  | {:request_state_store, pid()}
  | {:clustered, boolean()}
  | {:request_state_ttl, pos_integer()}
  | {:scope_map, map()}
  | {:default_scopes, [String.t()]}
  | {:registrations, [registration()]}
  | {:session_store, AttestoMCP.Server.SessionStore.adapter()}
  | {:session_namespace, String.t()}
  | {:session_clustered, boolean()}
  | {:url_elicitation_store, AttestoMCP.Server.UrlElicitationStore.adapter()}
  | {:url_elicitation_max_entries, pos_integer()}
  | {:url_elicitation_max_bytes, pos_integer()}
  | {:telemetry_metadata, map()}
  | {:exception_reporter, term()}
  | {:handler_task_init, term()}
  | {:subscription_timeout, pos_integer()}
  | {:page_size, pos_integer()}
  | {:cache_ttl_ms, non_neg_integer()}
  | {:cache_scope, cache_scope()}
  | {:allow_public_cache, boolean()}
  | {:cache_policy, keyword() | map()}
  | {:max_request_meta_bytes, pos_integer()}
  | {:initialize_callback, (map(), map() -&gt; :ok | {:error, term()})}
  | {:instructions, String.t()}
  | {:instructions_provider, host_callback()}
  | {:tool_presentation, host_callback()}
  | {:server_name, String.t()}
  | {:server_version, String.t()}
  | {:server_icons, [icon()]}
  | {:export_schema_dialect, boolean()}
  | {:capabilities, map()}
  | {:modern_tasks, false}
  | {:legacy_tasks, false}
```

A supported server startup option and its value.

# `server_opts`

```elixir
@type server_opts() :: [server_option()]
```

Keyword options accepted by `start_link/1`; task flags are disabled in this release.

# `subscription_filter`

```elixir
@type subscription_filter() :: %{optional(String.t()) =&gt; boolean() | [String.t()]}
```

Modern subscription category/resource filters.

# `tool_result`

```elixir
@type tool_result() :: map()
```

A normalized tool result with content and optional structured output.

# `active_session_ids`

```elixir
@spec active_session_ids(
  server(),
  keyword()
) ::
  {:ok, %{session_ids: [String.t()], next_cursor: String.t() | nil}}
  | {:error, :invalid_options | :session_store_unavailable | :unsupported}
```

Returns one bounded page of active legacy session IDs for operator tooling.

# `cancel_request`

```elixir
@spec cancel_request(server(), term(), term()) :: :ok | {:error, term()}
```

Cancels a request owned by the supplied principal binding.

When the transport configures `:principal_binding`, pass the derived binding
rather than the complete loaded principal. Otherwise pass the principal used
when the request started.

# `cancel_subscription`

```elixir
@spec cancel_subscription(server(), term()) :: :ok | {:error, term()}
```

Cancels a modern subscription.

# `cancel_subscription`

```elixir
@spec cancel_subscription(server(), term(), pid()) :: :ok | {:error, term()}
```

Cancels a modern subscription owned by the given sink process.

# `child_spec`

```elixir
@spec child_spec(server_opts()) :: Supervisor.child_spec()
```

Returns a supervision child spec keyed by the optional registered server name.

# `close_subscription`

```elixir
@spec close_subscription(server(), term()) :: :ok | {:error, term()}
```

Closes a modern subscription.

# `close_subscription`

```elixir
@spec close_subscription(server(), term(), pid()) :: :ok | {:error, term()}
```

Closes a modern subscription owned by the given sink process.

# `consume_url_elicitation`

```elixir
@spec consume_url_elicitation(server(), String.t(), term()) ::
  {:ok, %{action: String.t(), fields: map(), expires_at_ms: non_neg_integer()}}
  | {:error, :not_found | :foreign | :consumed | :expired | :store_unavailable}
```

Atomically consumes a staged URL elicitation record upon confirmation.

# `delete_session`

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

Deletes a legacy session and its owned streams.

# `dispatch`

```elixir
@spec dispatch(server(), request(), handler_context(), keyword()) :: term()
```

Dispatches one decoded request through the shared protocol core.

# `get_session`

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

Looks up a session only for its principal binding and tenant.

# `new_session`

```elixir
@spec new_session(server(), term(), term(), keyword()) ::
  {:ok, struct()} | {:error, term()}
```

Creates a principal-binding/tenant-bound legacy session.

# `options`

```elixir
@spec options(server()) :: keyword()
```

Returns normalized startup options used by Plug and stdio adapters.

# `publish`

```elixir
@spec publish(server(), map(), [publish_option()]) :: :ok | {:error, term()}
```

Queues a filtered modern notification and publishes its legacy event.

An optional `:authorize` callback is combined with each stream's captured
delivery authorization for both modern and legacy subscribers. Only a
literal `true` permits delivery; callback failures suppress it. Its context
keeps `required_scopes` as the primary all-of clause and adds
`required_scope_sets` with every accepted clause.

# `register`

```elixir
@spec register(server(), atom(), String.t(), definition()) :: :ok | {:error, term()}
```

Registers one primitive of a supported type.

# `register_all`

```elixir
@spec register_all(server(), [registration()]) :: :ok | {:error, term()}
```

Atomically registers a bounded primitive batch with coalesced invalidations.

# `register_completion`

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

Registers a completion handler tied to an explicit prompt/template reference.

# `register_prompt`

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

Registers a prompt definition, including required and optional arguments.

The handler input is `%{name: name, arguments: arguments}`. A definition may
match an argument directly when it declares that argument as required, for
example:

    handler: fn %{arguments: %{"topic" => topic}}, _context ->
      {:ok, [%{"role" => "user", "content" => %{"type" => "text", "text" => topic}}]}
    end

Use `Map.get(arguments, "topic")` instead when the argument is optional.

# `register_resource`

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

Registers a static resource definition.

# `register_resource_template`

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

Registers a URI-template resource definition.

# `register_tool`

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

Registers a tool definition and publishes a modern catalog invalidation.

# `replace_catalog`

```elixir
@spec replace_catalog(server(), [registration()]) :: :ok | {:error, term()}
```

Atomically replaces the complete primitive catalog from one bounded batch.

# `resolve_url_elicitation`

```elixir
@spec resolve_url_elicitation(server(), String.t(), term()) ::
  {:ok, %{action: String.t(), fields: map(), expires_at_ms: non_neg_integer()}}
  | {:error, :not_found | :foreign | :consumed | :expired | :store_unavailable}
```

Resolves a staged URL elicitation record for the host's approval page.

# `snapshot`

```elixir
@spec snapshot(server()) :: map()
```

Returns the registered primitive snapshot.

# `stage_url_elicitation`

```elixir
@spec stage_url_elicitation(server(), map(), String.t(), map(), keyword()) ::
  {:ok, %{id: String.t(), expires_at_ms: non_neg_integer()}} | {:error, term()}
```

Stages a URL elicitation record before returning a mode: "url" input request.

# `start_link`

```elixir
@spec start_link(server_opts()) :: GenServer.on_start()
```

Starts the supervised, transport-neutral MCP server.

    iex> {:ok, server} = AttestoMCP.Server.API.start_link([])
    iex> is_pid(server)
    true
    iex> GenServer.stop(server)
    :ok

# `stats`

```elixir
@spec stats(server()) :: map()
```

Returns bounded public counters for active work and transport state.

---

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