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.
os_sup_mcp gives AI coding agents a true live REPL on running Elixir/BEAM nodes.
Instead of writing "dead code" that needs endless edit-restart-test cycles, agents can instantly:
- Evaluate snippets with full access to live processes, ETS tables, supervisors, and runtime state
- Debug complex issues (race conditions, GenServers, distributed systems) on real data
- Iterate in seconds, hot-patch logic, and experiment safely on isolated nodes
In short: turns agents from code writers into agents that can think, debug, and solve problems like senior Elixir engineers — no mocks, no restarts.
Add os_sup_mcp to your list of dependencies in mix.exs:
def deps do
[
{:os_sup_mcp, "~> 0.1.0"}
]
endOsSupMcp.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.
| Tool | Params | Description |
|---|---|---|
status |
(none) | List all managed nodes: name, connected, OS PID, uptime |
start |
name, path, args? |
Start a child node from a Mix project directory |
stop |
name |
Stop a running child node |
restart |
name |
Stop + start with same config |
eval |
name, code |
Evaluate Elixir expression on a child node via :erpc |
# Start the server
cd os_sup_mcp
mix deps.get
mix run --no-haltThe MCP server listens on TCP port 9100 (configurable in config/config.exs).
# 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:9100Add to your MCP config:
{
"mcpServers": {
"os_sup_mcp": {
"type": "stdio",
"command": "socat",
"args": ["STDIO", "TCP:localhost:9100"]
}
}
}# config/config.exs
config :os_sup_mcp,
mcp_port: 9100OsSupMcp.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")MIT — see LICENSE for details.