BeamScope MCP
Provides tools for introspection and interaction with running Elixir/BEAM applications, including evaluating code, retrieving logs, inspecting processes, ETS tables, supervision trees, and more.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@BeamScope MCP show me the latest error logs"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
BeamScope MCP
A robust MCP (Model Context Protocol) server for Elixir applications. BeamScope gives AI coding agents access to your running BEAM application through a resilient TCP architecture that survives app restarts.
Why BeamScope?
BeamScope was built to solve a fundamental problem with HTTP-based MCP servers like TideWave: when your Elixir app restarts, the connection dies and doesn't reconnect.
This is particularly painful during development when you're:
Running
mix compileafter making changesRestarting your app to pick up config changes
Experiencing crashes that trigger supervisor restarts
BeamScope uses a standalone TCP architecture where a TypeScript bridge maintains the connection to your AI agent and automatically reconnects when the Elixir app comes back up.
Traditional HTTP-based MCP (TideWave):
┌─────────────┐ HTTP ┌──────────────────────┐
│ AI Agent │ ──────────────► │ Phoenix Endpoint │ ← Dies when app restarts
└─────────────┘ │ (Plug-based MCP) │
└──────────────────────┘
BeamScope Architecture:
┌─────────────┐ stdio ┌───────────────────┐ TCP ┌─────────────────┐
│ AI Agent │ ─────────────► │ TypeScript │ ──────────► │ Elixir │
│ │ │ Bridge │ reconnects │ GenServer │
└─────────────┘ │ (stays running) │ on restart │ (BeamScope) │
└───────────────────┘ └─────────────────┘Related MCP server: harness-fe
Design Philosophy
Generic Elixir/BEAM, Not Framework-Specific
BeamScope works with any Elixir application, not just Phoenix. The tools are useful across the entire Elixir ecosystem:
project_eval— Evaluate code in your running applicationget_logs— Retrieve application logs with filteringget_docs— Access local documentation for modules and functions
We intentionally excluded framework-specific tools (Ecto, Ash, Phoenix) to keep BeamScope portable and focused on what every BEAM app has in common.
No Default Ports — Fail Loudly
BeamScope has no default port anywhere in the stack. If the port isn't configured, the app crashes at startup with a clear error message telling you exactly what to add to your config.
This prevents the maddening situation where your Elixir app is listening on one port and the MCP bridge is trying to connect on another. Every port must be explicitly configured in both places.
Installation
BeamScope MCP has two components: an Elixir library (TCP server + tools) and a TypeScript bridge (MCP protocol). Both run locally — clone the repo first, then reference it as a path dependency.
1. Clone the repo
cd ~/your/projects # or wherever you keep local deps
git clone https://github.com/JediLuke/BeamScope-MCP.git beam_scope_mcp2. Add to your Elixir project
Reference the cloned repo as a path dependency:
# mix.exs
def deps do
[
{:beam_scope_mcp, path: "../beam_scope_mcp", only: :dev}
]
endAdjust the path to wherever you cloned it relative to your project.
mix deps.get3. Configure the port (required)
# config/config.exs (or config/dev.exs)
config :beam_scope_mcp,
port: 9995,
app_name: "MyApp"Optionally allow env var override:
# config/runtime.exs
if port = System.get_env("BEAM_SCOPE_MCP_PORT") do
config :beam_scope_mcp, port: String.to_integer(port)
end4. Build the TypeScript bridge
cd /path/to/beam_scope_mcp
npm install
npm run build5. Configure your AI coding agent
Add BeamScope to your project's .mcp.json:
{
"mcpServers": {
"beam-scope-mcp": {
"type": "stdio",
"command": "node",
"args": ["/absolute/path/to/beam_scope_mcp/dist/index.js"],
"env": { "BEAM_SCOPE_MCP_PORT": "9995" }
}
}
}Important: The BEAM_SCOPE_MCP_PORT env var must match the port in your Elixir config. If it's missing, the TypeScript bridge will exit immediately with an error.
Available Tools (20)
Connection
Tool | Description |
| Establish TCP connection. Port pre-configured via env var. |
| Check current connection status. |
Core
Tool | Description |
| Application logs with tail/grep/level filtering. |
| Evaluate Elixir code in the running app with timeout. |
| Local documentation for modules/functions via |
Compilation
Tool | Description |
| Recompile the project from within the BEAM. Returns errors/warnings. |
| Hot-reload a single module from its source file. Fastest feedback loop. |
| Force recompile dependencies. Args required (e.g. |
System & Process Introspection
Tool | Description |
| Memory, schedulers, process counts, uptime, IO stats. |
| Filterable/sortable process listing (by name, memory, queue size). |
| Detailed info: function, memory, links, monitors, stacktrace. |
| Internal state of GenServers via |
| Process dictionary metadata (Logger metadata, flags, etc.). |
Application & OTP
Tool | Description |
| Runtime application config (what the BEAM has loaded, not files on disk). |
| Recursive OTP supervision tree walk. App name required. |
ETS
Tool | Description |
| All ETS tables with size, memory, type, protection, owner. |
| Read ETS table contents with row limits and truncation. |
Code Intelligence
Tool | Description |
| Find all callers of a module or function via |
Tracing
Tool | Description |
| Trace function calls on a module. Writes to file in |
| Emergency stop for any running trace. Safe to call even if no trace is running. |
Running Multiple Applications
Each application uses a different port:
# App 1: config/config.exs
config :beam_scope_mcp, port: 9995
# App 2: config/config.exs
config :beam_scope_mcp, port: 9994Each app's .mcp.json passes the matching port via BEAM_SCOPE_MCP_PORT.
Architecture
beam_scope_mcp/
├── lib/
│ ├── beam_scope_mcp.ex # Public API
│ └── beam_scope_mcp/
│ ├── application.ex # OTP Application (fail-loudly port config)
│ ├── server.ex # TCP GenServer + command dispatch
│ ├── log_capture.ex # Logger handler + circular buffer
│ └── tools/
│ ├── logs.ex # get_logs
│ ├── eval.ex # project_eval
│ ├── docs.ex # get_docs
│ ├── recompile.ex # recompile, reload_module, recompile_deps
│ ├── system_stats.ex # get_system_stats
│ ├── processes.ex # list_processes, get_process_info/state/dictionary
│ ├── app_config.ex # get_app_config
│ ├── supervision_tree.ex # get_supervision_tree
│ ├── ets.ex # list_ets_tables, inspect_ets_table
│ ├── xref.ex # xref_callers
│ └── trace.ex # trace_calls, stop_trace (writes to /tmp/beam_scope_traces/)
├── src/
│ ├── index.ts # MCP server entry point
│ ├── connection.ts # TCP connection (requires BEAM_SCOPE_MCP_PORT env var)
│ └── tools.ts # Tool definitions and handlers
└── dist/ # Compiled TypeScript (gitignored)Tool Selection Eval
Tool descriptions are optimized so LLMs select the correct tool for each task. See EVAL.md for 18 test scenarios and results (17/18 pass on Claude Opus 4.6).
Migrating from TideWave
See MIGRATION_FROM_TIDEWAVE.md for a step-by-step guide.
License
MIT
Available Tools
20 toolsconnect_beam_scope_mcpA
Connect to the BeamScope MCP server running in your Elixir application. The TCP port is pre-configured via BEAM_SCOPE_MCP_PORT env var. Do NOT guess the port. If connection fails, look up the correct port in the Elixir config: check config/runtime.exs, config/dev.exs, or config/config.exs in the current project for config :beam_scope_mcp, port: <number>. Then check .mcp.json to ensure the BEAM_SCOPE_MCP_PORT env var matches. This must be called before using other BeamScope tools (get_logs, project_eval, etc.).
Inputs: no named parameters.
get_app_configA
Get runtime application configuration — what the BEAM actually has loaded (not what's in the config files on disk). Includes runtime.exs overrides, env var substitutions, and dynamic Application.put_env changes.
WHEN TO USE: You need to check config values (ports, feature flags, module settings) as the running app sees them. NOT FOR: System health metrics (use get_system_stats). Process-level inspection (use get_process_info/state).
Inputs: app (required), key.
get_beam_scope_mcp_statusA
Check if connected to an Elixir app and get server details. The port is configured via BEAM_SCOPE_MCP_PORT env var — if not set, check your .mcp.json env config.
Inputs: no named parameters.
get_docsA
Get @moduledoc/@doc documentation for an Elixir module or function. Reads from compiled .beam files (local, no network).
WHEN TO USE: You need to understand what a function does, its parameters, or how to use a module. NOT FOR: Finding what calls a function (use xref_callers). Evaluating code (use project_eval).
Examples: "GenServer", "String.split", "String.split/2", "c:GenServer.handle_call/3" (prefix c: for callbacks).
Inputs: reference (required).
get_logsA
Your primary debugging tool. Retrieve application logs from the running Elixir app — errors, warnings, crash reports, and application output. This is the ONLY source of log data; no other tool provides it.
WHEN TO USE: First step when diagnosing any problem. Check logs before drawing conclusions from other tools. NOT FOR: System resource usage (use get_system_stats). Process-level details (use get_process_info).
Use grep to filter (e.g. "error", "warning", "timeout") and level to filter by severity. Logs are in a circular buffer so old entries may be discarded.
Inputs: tail (required), grep, level.
get_process_dictionaryA
Read the process dictionary — hidden metadata stored outside the main state. Contains OTP internals like $ancestors, $initial_call, plus any custom entries (Logger metadata, step context, flags).
WHEN TO USE: You need metadata that isn't in the GenServer state — OTP ancestry, custom flags, or debugging context. NOT FOR: The process's main data (use get_process_state). Process vitals like memory/stacktrace (use get_process_info).
Inputs: pid (required).
get_process_infoA
Get metadata ABOUT a process: what function it's running, memory usage, message queue length, links, monitors, stacktrace.
WHEN TO USE: You want to know what a process IS and what it's DOING — its identity and vital signs. NOT FOR: The data the process is holding (use get_process_state). Metadata in the process dictionary (use get_process_dictionary). Use list_processes first to find PIDs/names if you don't know them.
Inputs: pid (required).
get_process_stateA
Get the DATA a GenServer is holding — its internal state (the value in the GenServer's loop).
WHEN TO USE: You want to see the actual data/state inside a process — what it's storing, its current values. NOT FOR: Process metadata like memory/links/stacktrace (use get_process_info). Process dictionary entries (use get_process_dictionary). Note: may timeout if the process is busy or doesn't support :sys messages.
Inputs: pid (required), timeout.
get_supervision_treeA
Get the OTP supervision tree for an application. Recursively walks supervisors showing the full hierarchy of processes with PIDs, types, and child counts.
You MUST specify the app name. Use get_app_config or project_eval with Application.started_applications() to find app names if unsure.
Inputs: app (required), depth.
get_system_statsA
Get BEAM runtime health: memory usage, scheduler count, process/port/atom counts, uptime, IO throughput.
WHEN TO USE: You want a system-level health snapshot — is memory growing? How many processes are running? How long has the app been up? NOT FOR: Application configuration (use get_app_config). Individual process details (use get_process_info). Checking for errors (use get_logs — system stats don't show errors).
Inputs: no named parameters.
inspect_ets_tableA
Read the contents of an ETS table. Returns rows from the table, limited to avoid massive output.
Use list_ets_tables first to find table names, then inspect specific tables.
Inputs: table (required), limit.
list_ets_tablesA
List all ETS tables with metadata: name, row count, memory, type, protection, owner. Sorted by memory descending.
WHEN TO USE: Discover what ETS tables exist, find tables using the most memory. NEXT STEP: Use inspect_ets_table with the table name to read its contents.
Inputs: no named parameters.
list_processesA
List running BEAM processes — find them by name, sort by memory or queue size. Returns summary info for each process.
WHEN TO USE: You need to discover what processes exist, find a specific process by name, or identify processes using the most memory/having the largest queues. NEXT STEP: Once you have a PID or name, use get_process_info, get_process_state, or get_process_dictionary for details.
Inputs: limit, sort_by, name_filter, min_message_queue.
project_evalA
Evaluate Elixir code in the context of the running application. This is the general-purpose escape hatch — use it when no specific tool exists for what you need.
PREFER specific tools over project_eval when they exist:
Need logs? Use get_logs, not project_eval with Logger
Need process info? Use get_process_info/get_process_state, not project_eval with Process.info
Need to recompile? Use recompile or reload_module
Need ETS data? Use list_ets_tables/inspect_ets_table
Need docs? Use get_docs
Need callers? Use xref_callers
Use project_eval for one-off operations that don't have a dedicated tool. The code runs with full access to your application's modules, dependencies, and runtime state.
Inputs: code (required), timeout.
recompileA
Recompile the entire project from within the running BEAM. Returns errors/warnings.
WHEN TO USE: After changing multiple files, or when you're not sure what changed. This is equivalent to mix compile. NOT FOR: Single file changes (use reload_module instead — much faster). Dependencies (use recompile_deps instead).
Inputs: no named parameters.
recompile_depsA
Force recompile Elixir dependencies (not the project itself).
WHEN TO USE: When a local path dependency's source has changed, or to force-rebuild a specific dep. You MUST specify the args parameter. NOT FOR: Project code (use recompile or reload_module).
Inputs: args (required).
reload_moduleA
Hot-reload a single module from its source file. Fastest possible feedback loop — change one file, reload it, test immediately.
WHEN TO USE: After changing a single .ex file. No full recompile needed. NOT FOR: Multiple file changes (use recompile). Dependencies (use recompile_deps).
Inputs: file (required).
stop_traceA
Abort a running trace early. You do not normally need to call this — traces auto-stop when they hit their max_calls or max_seconds limit and clean up after themselves. This is only useful if you want to cancel a trace before it finishes on its own. Safe to call even if no trace is running.
Inputs: no named parameters.
trace_callsA
Start tracing function calls on a module. This tool does NOT return the trace results directly — it writes them to a file and returns the file path.
WORKFLOW:
Call this tool → you get back a file path (e.g. /tmp/beam_scope_traces/MyModule_20260323_221503.log)
Wait a few seconds for the trace to collect events
Read the file using your normal file reading tools (Read tool) to see the trace results
The trace auto-stops when it hits max_calls or max_seconds — you do NOT need to call stop_trace
WHY A FILE: Traces collect events over time and can be large. Writing to a file lets you read just the parts you need (head, tail, grep for patterns).
The file contains timestamped entries like: [22:15:03.001] #1 #PID<0.599.0> MyModule.my_function("arg1", 42)
All parameters except function are REQUIRED. max_calls capped at 200, max_seconds capped at 30.
Inputs: module (required), max_calls (required), max_seconds (required), function.
xref_callersA
Find all callers of a module or function across the project — "what depends on this?"
WHEN TO USE: Impact analysis before refactoring. "What breaks if I change this function?" "Who calls this module?" NOT FOR: Understanding what a function does (use get_docs). Seeing runtime call flow (use trace_calls).
Inputs: reference (required).
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 20 tools
Every tool has a clearly distinct purpose with explicit 'WHEN TO USE' and 'NOT FOR' guidance. Overlapping concepts like process info/state/dictionary are precisely differentiated, and project_eval is positioned as a fallback with clear directives to prefer specific tools.
Tool names are mostly lowercase snake_case and follow a verb-first pattern like get_*, list_*, inspect_*, recompile, reload, trace_calls, stop_trace. Minor deviations include xref_callers and project_eval, which are less conventional in order but still readable and consistent in style.
20 tools is within the heavy range (16-25) and might feel overwhelming. However, the server covers a broad domain (logs, processes, ETS, supervision, tracing, compilation, docs, eval), so the count is defensible. Still, it is on the higher end and could benefit from consolidation.
The toolset provides comprehensive coverage for debugging a running BEAM application: connection, logs, system stats, process introspection, ETS inspection, supervision tree, app config, compilation, tracing, docs, xref, and a general eval fallback. No critical dead ends exist; gaps can be filled via project_eval.
Maintenance
Related MCP Connectors
AI-native programming language and toolchain for accountable, verifiable agent-driven development.
Context and control for any AI. Agent identity, scoped access, and proof across tools.
AI Agent with Architectural Memory. Impact analysis (free), tests and code from the graph (pro).
AI agent observability for production traces, natural-language insights, and improvement loops.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceLiveTap connects live data streams (MQTT, WebSocket, file tailing) to AI coding agents, enabling real-time monitoring and alerting through natural language.9 npm9MIT
- AlicenseNot gradedqualityAmaintenanceA source-aware MCP server that connects AI agents to browser and server runtimes, enabling real-time debugging, monitoring, and automatic fixes via WebSocket or HTTP.2MIT

Tidewave Railsofficial
AlicenseNot gradedqualityCmaintenanceBetter agentic Rails development, runtime-level tools for your agent to talk to your running app.475Apache 2.0
Tidewave Phoenixofficial
AlicenseNot gradedqualityBmaintenanceBetter agentic Elixir Phoenix development, runtime-level tools for your agent to talk to your running app.861Apache 2.0