AttestoMCP.Server.Plug (attesto_mcp_server v2.8.0)

Copy Markdown View Source

Plug-compatible Streamable HTTP boundary for modern and legacy MCP.

Every protected MCP leg authenticates through AttestoMCP.Plug.ProtectResource before package-owned request decoding or registry dispatch. A host parser placed earlier in the endpoint runs before this Plug and must apply its own input limit. Metadata discovery is the one intentionally public route defined by RFC 9728. Hosts may select request-scoped tool streams with stream_tools or stream_all_tools; both options are validated during init/1.

:auth accepts either a keyword list or a zero-arity remote callback/MFA returning one. Resolver-backed authentication is evaluated for every applicable MCP or metadata request, so runtime authorization configuration is not captured by router compilation. The trusted resolver may supply the canonical resource or origin at runtime; it is checked against the configured Plug path and reused for metadata and audience verification. A resolver may not replace the boundary's canonical assign keys, and failures fail the request closed.

A host may keep that canonical resource pinned for RFC 9728 metadata while accepting tokens for an explicit set of alternate gateway identifiers by supplying Attesto core's :trusted_audiences inside :auth. The list replaces the single-resource audience policy, so it must include the canonical resource when direct clients should remain accepted.

:principal_binding may derive a bounded stable identity from the complete authenticated principal without replacing the value handlers receive. :client_ip may derive the canonical IPv4 or IPv6 tuple used by both authenticated and failed-authentication rate-limit buckets. It accepts a one-argument function or MFA receiving the Plug.Conn; when omitted, conn.remote_ip is used verbatim. Explicit callback failures and non-IP returns fail closed and emit neutral client_ip/exception telemetry. :authorize is a separate mount-level business-policy callback. It receives the authenticated base context once per protected HTTP leg; only literal true permits the request, and denial is a neutral 403 before POST body reading or protocol dispatch.

Summary

Types

Supported Plug boundary options.

Per-method opt-ins to definition-based HTTP authorization.

An explicit definition-based authorization mode for one MCP method.

Functions

Authenticates and serves one HTTP request through the MCP boundary.

Initializes a Plug state for an already-supervised server and pinned auth boundary.

Types

auth_options_resolver()

@type auth_options_resolver() ::
  (-> keyword()) | {module(), atom()} | {module(), atom(), [term()]}

Supported Plug boundary options.

plug_option()

@type plug_option() ::
  {:server, pid() | atom()}
  | {:path, String.t()}
  | {:auth, keyword() | auth_options_resolver()}
  | {:scope_map, map()}
  | {:scope_policy, scope_policy()}
  | {:default_scopes, [String.t()]}
  | {:scopes_supported, [String.t()]}
  | {:context_builder,
     (Plug.Conn.t() -> map())
     | {module(), atom()}
     | {module(), atom(), [term()]}}
  | {:principal_binding,
     (term() -> term()) | {module(), atom()} | {module(), atom(), [term()]}}
  | {:client_ip,
     (Plug.Conn.t() -> :inet.ip_address())
     | {module(), atom()}
     | {module(), atom(), [term()]}}
  | {:authorize,
     (map() -> boolean()) | {module(), atom()} | {module(), atom(), [term()]}}
  | {:subscription_scopes, [String.t()]}
  | {:max_body_bytes, pos_integer()}
  | {:max_message_bytes, pos_integer()}
  | {:allow_http, boolean()}
  | {:allow_dynamic_origin, boolean()}
  | {:origin, String.t()}
  | {:base_url, String.t()}
  | {:resource, String.t()}
  | {:resource_audience, String.t()}
  | {:stream_keepalive_ms, pos_integer()}
  | {:legacy_keepalive_ms, pos_integer()}
  | {:subscription_timeout, pos_integer()}
  | {:stream_queue_size, pos_integer()}
  | {:subscription_queue_size, pos_integer()}
  | {:max_queue, pos_integer()}
  | {:stream_all_tools, boolean()}
  | {:stream_tools, [String.t()]}

scope_policy()

@type scope_policy() :: %{optional(String.t()) => scope_policy_mode()}

Per-method opt-ins to definition-based HTTP authorization.

scope_policy_mode()

@type scope_policy_mode() :: :visible_definitions | :selected_definition

An explicit definition-based authorization mode for one MCP method.

Functions

call(conn, state)

@spec call(Plug.Conn.t(), map()) :: Plug.Conn.t()

Authenticates and serves one HTTP request through the MCP boundary.

init(opts)

@spec init([plug_option()]) :: map()

Initializes a Plug state for an already-supervised server and pinned auth boundary.