# beamdev A BEAM development tool for coding agents: a Model Context Protocol (MCP) server that connects to Erlang/BEAM nodes over the Erlang distribution protocol and runs code on them. Introspection, tracing and debugging are not tools here — they are functions the node already has, and `eval` reaches all of them. > **Development tool.** Code runs unsandboxed, with the full authority of the target node. > The cookie is the only boundary. ## Install ```bash cargo build --release # binary at target/release/beamdev nix build # or via the flake ``` ## Use Start a node, then point an MCP client at the binary: ```json { "mcpServers": { "erlang": { "command": "/path/to/beamdev", "args": ["--node", "myapp@localhost", "--mode", "elixir"] } } } ``` `--mode` sets how terms are rendered: `erlang` (default), `elixir`, `gleam`, or `lfe`. `--log-level` takes the usual five. Both are fixed at startup. `--node` is required and names the one node this server works against, for its whole life. The cookie comes from `--cookie-file` (default `.erlang.cookie`, relative to the working directory the client launches the server in); an unreadable cookie is fatal. Nothing is exposed to the caller for connecting or disconnecting, so an agent has no reason to go looking for a cookie. The node itself need not be up. The server connects in the background and retries with backoff, and a tool call that finds the link down retries immediately rather than waiting out the timer, so restarting the node mid-session is unremarkable. A reconnect is logged on the node, which puts a marker in `get_logs`: everything before it — buffered events, loaded modules, process state — belongs to the previous incarnation. Working against several nodes means running several servers. Reaching another node in an existing cluster does not: `rpc:call/4` from the connected one already gets there. ## Tools | Tool | Description | |------|-------------| | `list_nodes` | Report the node and whether the connection to it is up | | `eval` | Evaluate Erlang or Elixir source, bounded by `timeout_ms` (default 15s) | | `load_module` | Compile module source on the node and load it | | `get_logs` | Read what the node has logged since we connected, filtered by level and regex | Nothing needs installing on the target: the tools drive the node's own scanner, parser, evaluator and compiler. The first `eval` loads one small runner module, which bounds each evaluation in time and memory and kills it on overrun. `get_logs` needs a second module. A node's log stream does not cross the distribution link, so connecting installs a `logger` handler that buffers the last 1000 formatted events on the node. Only events logged after the connection are captured, and only those the node's primary logger level already lets through. Reports are rendered by the node's own `inspect` where it has Elixir, so `redact: true` and hand-written `Inspect` implementations apply. ``` eval(code: "erlang:process_info(whereis(user), [memory]).") load_module(source: "-module(h).\n-export([n/0]).\nn() -> node().") get_logs(level: "warning", grep: "timeout", tail: 20) ``` Erlang source passed to `eval` must end with a period; Elixir must not. When Elixir code raises, the exception is rendered on the node with `Exception.format/3`, so the `Inspect` protocol applies and a struct's redacted fields stay redacted. Erlang has no equivalent: an Erlang exception's reason is rendered here, term for term, including anything it happens to be carrying. ## Development ```bash cargo fmt && cargo clippy --all-targets --all-features -- -D warnings && cargo test ``` The integration tests start and stop their own BEAM nodes, so they need `erl` and `elixir` on PATH -- `nix develop` provides both. ## License This project is licensed under the Apache License, Version 2.0 — see the [LICENSE](LICENSE) file for details. ## Acknowledgements - [erl_dist](https://github.com/beamform/erl_dist) - Erlang distribution protocol client - [rmcp](https://github.com/modelcontextprotocol/rmcp) - Model Context Protocol server framework - [Model Context Protocol](https://modelcontextprotocol.io/) - Protocol specification