Serves a Sake.Server over standard input and output, for a client that
launches the server as a subprocess:
Sake.Stdio.run(MyApp.MCP)run/2 blocks until standard input closes. In a supervision tree, start
it as a child instead, after Sake:
{Sake.Stdio, server: MyApp.MCP}From a Mix project, mix sake.stdio MyApp.MCP does the same.
Options: server: (the child's, required), scope: (the host's
principal: a value, or a function of no arguments called for every
request; default nil), secret: (binary or {m, f, a}; default the
Sake configuration, else a random secret for the life of the process),
reraise: (re-raise tool exceptions, for tests), grace: (ms that
requests still running when standard input closes get to finish,
default 2 000), halt: (the child's only: stop the VM once standard
input closes, default true), input: and output: (IO devices,
default standard input and output).
The server speaks both eras on the one connection. A request whose
_meta names the modern revision is served statelessly; an initialize
request opens the connection's legacy session, and requests without a
protocol version in _meta then belong to it. Each request runs in its
own process, so responses can arrive out of order;
notifications/cancelled stops a request and suppresses its response.
There is no authorization on stdio: the client that launched the server
already holds its credentials, and the server takes its own from its
environment. Pass the principal as scope:.
Standard output carries MCP messages only. While serving it, Sake moves
the default Logger handler to standard error and runs every request
with standard error as its group leader, so IO.puts/1 in a tool cannot
break the stream.
Summary
Functions
@spec log_to_stderr() :: :ok
Moves the default Logger handler from standard output to standard
error. run/2 and the child do this when they serve standard output; a
release that logs while it boots should also configure it:
config :logger, :default_handler, config: [type: :standard_error]
Serves server until standard input (or input:) closes.