Reads and validates config :mead, :mcp_server.
Pure: it starts nothing and reads no application environment itself; Mead.MCP.Server hands
it the settings. Without a :token the server is :disabled. Any other problem is an error
whose message names the setting and never contains the token or any other value.
The struct keeps a SHA-256 digest of the token, not the token, and its Inspect omits even
the digest, so the listener options that carry the struct leak nothing into a crash report or
:sys.get_status/1. Hashing both sides before comparing also gives secure_compare/2 two
binaries of equal length whatever the client sent.
Settings
:token- the bearer token clients must present (a non-empty string; required to enable the server).:port-0..65535; defaults to 4040. Tests use 0 and ask the listener for its port.:address- an IPv4 tuple; defaults to loopback{127, 0, 0, 1}.:allow_effect- whethertools: "effect"is honoured; defaults tofalse.:allowed_origins- exactOriginvalues accepted besides loopback; defaults to[].:maximum_connections- how many connections the listener serves at once, rounded up to a multiple of 10 from 10 on; a connection over the limit is closed after about a second without room. A positive integer; defaults to 250.:certfileand:keyfile- paths to a PEM certificate chain and its private key. Both together make the listener speak HTTPS (and WSS for the deck); either alone is an error; without them it speaks plain HTTP. The files are not read here, only the shape is checked, so a missing file stops the listener at boot with the TLS library's own message.
Summary
Functions
Reads only the listener settings (:port, :address, :allowed_origins,
:maximum_connections), which are valid with or without a token, so the shared listener can
start for the deck alone. The deck applies the same Origin rule as MCP.
Whether presented is the configured token, compared in constant time.
Types
@type t() :: %Mead.MCP.Server.Configuration{ address: :inet.ip4_address(), allow_effect: boolean(), allowed_origins: [String.t()], maximum_connections: pos_integer(), port: 0..65535, token_digest: binary() }
Functions
@spec listener(term()) :: {:ok, %{ port: 0..65535, address: :inet.ip4_address(), allowed_origins: [String.t()], maximum_connections: pos_integer(), tls: nil | [certfile: Path.t(), keyfile: Path.t()] }} | {:error, String.t()}
Reads only the listener settings (:port, :address, :allowed_origins,
:maximum_connections), which are valid with or without a token, so the shared listener can
start for the deck alone. The deck applies the same Origin rule as MCP.
Whether presented is the configured token, compared in constant time.