# 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`:
```elixir
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 |
| `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` |
## Usage
```bash
# 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
```bash
# 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:
```json
{
"mcpServers": {
"os_sup_mcp": {
"type": "stdio",
"command": "socat",
"args": ["STDIO", "TCP:localhost:9100"]
}
}
}
```
## Configuration
```elixir
# config/config.exs
config :os_sup_mcp,
mcp_port: 9100
```
## Programmatic API
```elixir
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](LICENSE) for details.