AttestoMCP.Server.API (attesto_mcp_server v0.14.0)

Copy Markdown View Source

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. The callback context contains the authenticated principal, tenant, scopes, transport, negotiated version, request ID, trace_context, progress callback, and 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 value for matching public content and result constructor 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.

Summary

Types

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

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

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.

Authorization and transport context passed to handlers.

A normal, failed, or interactive handler return.

A modern result carrying resultType and protocol metadata.

Interactive request-state and input-response payloads.

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

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

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

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

A text or Base64 resource content entry.

One conjunctive scope clause used by a primitive definition.

A supervised server pid or a registered server name.

A supported server startup option and its value.

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

Modern subscription category/resource filters.

A normalized tool result with content and optional structured output.

Functions

Cancels a request owned by a principal.

Cancels a modern subscription.

Cancels a modern subscription owned by the given sink process.

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

Closes a modern subscription.

Closes a modern subscription owned by the given sink process.

Deletes a legacy session and its owned streams.

Dispatches one decoded request through the shared protocol core.

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

Creates a principal/tenant-bound legacy session.

Returns normalized startup options used by Plug and stdio adapters.

Queues a filtered modern notification and publishes its legacy event.

Registers one primitive of a supported type.

Atomically registers a bounded primitive batch with coalesced invalidations.

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

Registers a prompt definition, including required and optional arguments.

Registers a static resource definition.

Registers a URI-template resource definition.

Registers a tool definition and publishes a modern catalog invalidation.

Atomically replaces the complete primitive catalog from one bounded batch.

Returns the registered primitive snapshot.

Starts the supervised, transport-neutral MCP server.

Returns bounded public counters for active work and transport state.

Types

cache_scope()

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

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

content_item()

@type content_item() :: map()

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

definition()

@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()

@type handler_context() :: map()

Authorization and transport context passed to handlers.

handler_return()

@type handler_return() ::
  {:ok, term()}
  | {:error, term()}
  | {:input_required, %{optional(String.t()) => map()}}

A normal, failed, or interactive handler return.

modern_result()

@type modern_result() :: map()

A modern result carrying resultType and protocol metadata.

mrtr_payload()

@type mrtr_payload() :: %{optional(String.t()) => term()}

Interactive request-state and input-response payloads.

prompt_message()

@type prompt_message() :: map()

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

publish_option()

@type publish_option() :: {:authorize, (map() -> boolean())}

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

registration()

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

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

request()

@type request() :: map()

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

resource_content()

@type resource_content() :: map()

A text or Base64 resource content entry.

scope_set()

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

One conjunctive scope clause used by a primitive definition.

server()

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

A supervised server pid or a registered server name.

server_option()

@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_json_bytes, pos_integer()}
  | {: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()}
  | {: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()}
  | {:initialize_callback, (map(), map() -> :ok | {:error, term()})}
  | {:instructions, String.t()}
  | {:server_name, String.t()}
  | {:server_version, String.t()}
  | {:capabilities, map()}
  | {:modern_tasks, false}
  | {:legacy_tasks, false}

A supported server startup option and its value.

server_opts()

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

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

subscription_filter()

@type subscription_filter() :: %{optional(String.t()) => boolean() | [String.t()]}

Modern subscription category/resource filters.

tool_result()

@type tool_result() :: map()

A normalized tool result with content and optional structured output.

Functions

cancel_request(server, principal, request_id)

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

Cancels a request owned by a principal.

cancel_subscription(server, id)

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

Cancels a modern subscription.

cancel_subscription(server, id, owner)

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

Cancels a modern subscription owned by the given sink process.

child_spec(opts \\ [])

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

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

close_subscription(server, id)

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

Closes a modern subscription.

close_subscription(server, id, owner)

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

Closes a modern subscription owned by the given sink process.

delete_session(server, id)

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

Deletes a legacy session and its owned streams.

dispatch(server, request, context \\ %{}, opts \\ [])

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

Dispatches one decoded request through the shared protocol core.

get_session(server, id, principal, tenant \\ nil)

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

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

new_session(server, principal, tenant \\ nil, opts \\ [])

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

Creates a principal/tenant-bound legacy session.

options(server)

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

Returns normalized startup options used by Plug and stdio adapters.

publish(server, notification, opts \\ [])

@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(server, type, identity, definition)

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

Registers one primitive of a supported type.

register_all(server, registrations)

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

Atomically registers a bounded primitive batch with coalesced invalidations.

register_completion(server, name, definition)

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

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

register_prompt(server, name, definition)

@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(server, uri, definition)

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

Registers a static resource definition.

register_resource_template(server, template, definition)

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

Registers a URI-template resource definition.

register_tool(server, name, definition)

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

Registers a tool definition and publishes a modern catalog invalidation.

replace_catalog(server, registrations)

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

Atomically replaces the complete primitive catalog from one bounded batch.

snapshot(server)

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

Returns the registered primitive snapshot.

start_link(opts \\ [])

@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(server)

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

Returns bounded public counters for active work and transport state.