Os Supervisor Mcp

TCP MCP server for supervising child BEAM OS instances. Each child runs a Mix project from a given path, spawned via Port.open and connected through Erlang distribution for remote evaluation.

Installation

Add os_sup_mcp to your list of dependencies in mix.exs:

def deps do
  [
    {:os_sup_mcp, "~> 0.1.0"}
  ]
end

Architecture

OsSupMcp.Application
  └── Supervisor (rest_for_one)
        ├── OsSupMcp.Node.Manager        (GenServer, ETS registry)
        ├── OsSupMcp.Node.WorkerSupervisor (DynamicSupervisor)
        │     ├── Worker (child1) -- wraps Port
        │     ├── Worker (child2)
        │     └── ...
        └── OsSupMcp.MCP.Server          (TCP listener, port 9100)

Workers use restart: :transient — if a child BEAM crashes, the DynamicSupervisor automatically restarts it with the same config. Clean stops don't trigger restart.

MCP Tools

Tool Params Description
status(none) List all managed nodes: name, connected, OS PID, uptime
startname, path, args? Start a child node from a Mix project directory
stopname Stop a running child node
restartname Stop + start with same config
evalname, code Evaluate Elixir expression on a child node via :erpc

Usage

# Start the server
cd os_sup_mcp
mix deps.get
mix run --no-halt

The MCP server listens on TCP port 9100 (configurable in config/config.exs).

Manual testing with socat

# Initialize
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' | socat - TCP:localhost:9100

# List tools
echo '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' | socat - TCP:localhost:9100

# Start a child node
echo '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"start","arguments":{"name":"myapp","path":"/path/to/mix/project"}}}' | socat - TCP:localhost:9100

# Eval on child
echo '{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"eval","arguments":{"name":"myapp","code":"1 + 1"}}}' | socat - TCP:localhost:9100

# Stop child
echo '{"jsonrpc":"2.0","id":5,"method":"tools/call","params":{"name":"stop","arguments":{"name":"myapp"}}}' | socat - TCP:localhost:9100

Claude Code MCP integration

Add to your MCP config:

{
  "mcpServers": {
    "os_sup_mcp": {
      "type": "stdio",
      "command": "socat",
      "args": ["STDIO", "TCP:localhost:9100"]
    }
  }
}

Configuration

# config/config.exs
config :os_sup_mcp,
  mcp_port: 9100

Programmatic API

OsSupMcp.start_node("myapp", "/path/to/project")
OsSupMcp.eval_on_node("myapp", "Enum.sum(1..10)")
OsSupMcp.list_nodes()
OsSupMcp.restart_node("myapp")
OsSupMcp.stop_node("myapp")

License

MIT — see LICENSE for details.