Current section
Files
Jump to
Current section
Files
lib/pi/mcp/server.ex
defmodule Pi.MCP.Server do
@moduledoc "Starts the embedded MCP server inside the project Mix context."
alias Pi.MCP.Router
def start!(args \\ System.argv()) do
port = parse_port(args)
Pi.LogCapture.install()
Process.flag(:trap_exit, true)
{actual_port, http_server} = start_http(port)
wait_until_accepting(actual_port)
IO.puts("PI_MCP_READY port=#{actual_port} server=#{http_server}")
receive do
:stop -> :ok
end
end
defp parse_port(["--port", port | _]), do: String.to_integer(port)
defp parse_port(_), do: 4041
defp start_http(port) do
{:ok, server} = Bandit.start_link(plug: Router, port: port, ip: :loopback)
actual_port = if port == 0, do: listener_port(server), else: port
{actual_port, :bandit}
end
defp listener_port(server) do
{:ok, {_, port}} = ThousandIsland.listener_info(server)
port
end
defp wait_until_accepting(port) do
Enum.reduce_while(1..50, nil, fn _, _ ->
case :gen_tcp.connect(~c"127.0.0.1", port, [], 100) do
{:ok, socket} ->
:gen_tcp.close(socket)
{:halt, :ok}
{:error, _} ->
Process.sleep(100)
{:cont, nil}
end
end)
end
end