Skip to main content
Glama
iamvinitk
by iamvinitk
README.md
# @iamvinitk/electron-mcp

MCP server for interacting with and debugging an Electron app.
Spawns (or attaches to) an Electron process with the Chrome
DevTools Protocol on the renderer and the Node inspector on the
main process, then exposes ~20 tools for driving / inspecting both
sides.

Works with any Electron or Electron Forge project.

## Install

Run it on demand with `npx` (no install needed):

```sh
npx -y @iamvinitk/electron-mcp
```

…or install the `electron-mcp` binary globally:

```sh
npm i -g @iamvinitk/electron-mcp
electron-mcp
```

## Use it from an MCP client

The server speaks MCP over stdio — point any MCP client at it.  For a
typical `mcpServers` config:

```json
{
  "mcpServers": {
    "electron": {
      "command": "npx",
      "args": ["-y", "@iamvinitk/electron-mcp"]
    }
  }
}
```

(To run from a local clone instead, `npm install && npm run build`, then
point your client's `command`/`args` at `node /path/to/build/index.js`.)

## Tools

### Lifecycle

| Tool | Purpose |
|---|---|
| `launch_via_npm` | Spawn via `npm run <script>` (electron-forge dev). |
| `launch_app` | Spawn the `electron` binary directly (for packaged/test builds). |
| `attach_app` | Register an already-running Electron instance. |
| `stop_app` | Close CDP clients, kill spawned process, drop the session. |
| `list_apps` | Snapshot every active session (pid, ports, status, uptime). |
| `ping_inspector` | Zero-cost sanity check that the Node inspector is reachable. |

### Window automation

| Tool | Purpose |
|---|---|
| `list_windows` | Enumerate renderer CDP targets.  Skips `devtools://` pages. |
| `evaluate` | Run JS in the renderer via `Runtime.evaluate`. |
| `navigate` | Page-navigate the renderer. |
| `screenshot` | Capture a PNG/JPEG via `Page.captureScreenshot`. |

### Logs & network

| Tool | Purpose |
|---|---|
| `get_main_logs` | Read captured stdout/stderr from the spawned process. |
| `get_console_messages` | Read renderer `console.*` output and exceptions. |
| `get_network_requests` | Read renderer fetch/XHR activity (e.g. the app's API calls). |
| `clear_logs` | Wipe one or more ring buffers — useful before recording. |

### IPC

| Tool | Purpose |
|---|---|
| `list_electron_api_methods` | `Object.keys(window.electronAPI)`. |
| `invoke_electron_api` | Call any preload-exposed IPC method directly. |
| `enable_ipc_logging` | Inject a proxy that captures every IPC call the renderer makes. |
| `get_ipc_log` | Drain + read the captured IPC events. |

### Main-process state

| Tool | Purpose |
|---|---|
| `get_app_paths` | `app.getPath(...)`, `app.isPackaged`, `process.resourcesPath`, versions. |
| `read_user_data_file` | Path-traversal-guarded read under `app.getPath('userData')`. |

### Resources

| URI | Purpose |
|---|---|
| `electron://sessions` | JSON list of every tracked session. |
| `electron://session/{id}` | Detailed snapshot of one session (windows, recent logs, buffer sizes). |

## Typical debug flow

```
1. launch_via_npm             →   id=electron-abcd1234
2. list_windows  id=...       →   pick the target id
3. evaluate     id=... expr=… →   probe renderer state
4. invoke_electron_api        →   test an IPC handler
5. get_main_logs / get_console_messages / get_network_requests
6. stop_app                   →   tear down
```

## How it works

- **Launch modes.**  `launch_app` invokes the `electron` binary with
  `--remote-debugging-port=<N> --inspect=<N+?> <appPath>`.
  `launch_via_npm` wraps `npm run <script>` and smuggles
  `--inspect-electron` through forge's flag plumbing (double `--`
  separators), because forge only exposes main-process inspection
  that way.

- **Two debug channels.**  Electron renderers are Chromium pages, so
  they speak CDP on `--remote-debugging-port`.  The main process is
  Node, which speaks the (near-identical) Node inspector protocol on
  `--inspect`.  Both use `chrome-remote-interface`; we keep per-session
  client caches so repeated tool calls don't reconnect.

- **Log capture.**  Main-process stdout/stderr flow into a ring
  buffer on spawn.  Renderer console, exceptions, and network events
  flow into separate ring buffers via CDP event subscribers set up
  the first time each target's client opens.  `enable_ipc_logging`
  installs a `Proxy` over `window.electronAPI` so every IPC call the
  renderer makes (regardless of origin) is observable; re-injected
  on `Page.frameNavigated`.

- **Stdin stays open.**  Electron-forge's `start` command interprets
  an EOF on its stdin as "the user left the interactive REPL" and
  shuts down the child Electron.  We hold stdin open (never write to
  it) so forge keeps running as long as we want.

## Limitations

- **Packaged builds.**  If the app's Electron Forge config disables the
  `EnableNodeCliInspectArguments` fuse, that blocks `--inspect` at the
  fuse layer in packaged builds.  Window automation and
  renderer-side tools still work against a packaged build if you pass
  `--remote-debugging-port`, but main-process tools (`get_app_paths`,
  `read_user_data_file`) need a non-fused dev build.

- **Single-process model.**  One MCP server → any number of tracked
  sessions.  Sessions don't persist across MCP restarts; restart the
  MCP server to refresh.

- **macOS stdin quirk.**  Some terminal emulators (rare) block SIGINT
  delivery through `npm`'s stdin pipe.  If `stop_app` leaves a zombie
  forge process, `pkill -f electron-forge` is the backup.

## Development

```sh
npm run watch         # tsc --watch
npm run typecheck     # tsc --noEmit
```

There are no unit tests in this package.  Verification is
end-to-end against a running Electron app.

TDQS

A4.2/5.0

Scored across 20 tools

Disambiguation5/5

Each tool targets a distinct aspect of Electron debugging (launching, attaching, logging, inspection, etc.), with clear boundaries even among similar logging tools. No two tools appear to overlap in purpose.

Naming Consistency5/5

All tool names use lowercase snake_case with a consistent verb_noun pattern (e.g., list_windows, get_app_paths, launch_app). There is no mixing of conventions, making the set predictable.

Tool Count4/5

20 tools is on the higher side, but each tool serves a specific need for a complex domain. Some tools like clear_logs and get_main_logs could arguably be combined, but the count is still reasonable.

Completeness5/5

The tools cover the full lifecycle of debugging an Electron app: launch/attach, inspect (renderer and main process), capture logs (console, IPC, network), navigate, screenshot, and stop. No obvious gaps for common tasks.

Maintenance

ActivityInactive
ResponsivenessNo issues