An open API service indexing awesome lists of open source software.

https://github.com/amafjarkasi/electron-mcp-server

MCP server for debugging Electron apps via Chrome DevTools Protocol. Start/attach processes, capture screenshots, read console errors & network logs, inspect DOM, evaluate JS, and automate UI โ€” built for Cursor and other MCP clients.
https://github.com/amafjarkasi/electron-mcp-server

ai-agents automation cdp chrome-devtools-protocol cursor debugging desktop-apps devtools electron mcp model-context-protocol typescript

Last synced: 12 days ago
JSON representation

MCP server for debugging Electron apps via Chrome DevTools Protocol. Start/attach processes, capture screenshots, read console errors & network logs, inspect DOM, evaluate JS, and automate UI โ€” built for Cursor and other MCP clients.

Awesome Lists containing this project

README

          


Electron Debug MCP

โšก Electron Debug MCP


Debug Electron apps from Cursor & Claude with real DevTools superpowers.

Model Context Protocol server ยท Chrome DevTools Protocol ยท start / attach / screenshot / console / DOM / UI automation / tracing


Quick Start
36 Tools
Examples
Cursor Ready
ISC


MCP
CDP
Electron
TS
Node
version
tests

---

## ๐ŸŒŸ Overview

**Electron Debug MCP** is a local MCP server that gives AI coding agents **eyes, hands, and Chrome DevTools** inside your Electron app.

Instead of guessing from source alone, the agent can:

| ๐ŸŽฏ Goal | ๐Ÿ› ๏ธ How |
| --- | --- |
| Boot your app under a debugger | `start_app` with `--remote-debugging-port` |
| Hook an app you already launched | `attach` ยท `attach_by_pid` ยท `find_apps` ยท `discover_apps` |
| See the UI | `screenshot` / `save_screenshot` (full page or **element clip** via `selector`) |
| Read renderer failures | `get_console_messages` (`level: "error"`) + exceptions |
| Stream console live | `set_console_live` โ†’ MCP log notifications |
| Inspect markup | `get_dom` / `query_selector` |
| Run JS in the page | `evaluate` |
| Run JS in **main** | `start_app({ inspectMain: true })` โ†’ `evaluate_main` |
| Cookies & web storage | `get_cookies` / `set_cookie` ยท `get_storage` / `set_storage` |
| Watch network | `get_network_log` |
| Drive the UI | `wait_for` โ†’ `type_text` / `press_key` โ†’ `click` โ†’ `navigate` |
| Perf deep-dive | `start_tracing` โ†’ reproduce โ†’ `stop_tracing` (open in `chrome://tracing`) |
| One-shot health check | `diagnose` |
| Full DevTools power | `cdp_command` (`Domain.method`) |

It speaks **MCP over stdio** (Cursor / Claude Desktop friendly), bridges to **Chrome DevTools Protocol**, buffers console + network on monitored page targets, and keeps **stdout clean** (all server logs go to **stderr**).

### ๐Ÿ‘ค Who itโ€™s for

- ๐Ÿง‘โ€๐Ÿ’ป **Cursor / Claude users** pair-programming on Electron desktop apps
- ๐Ÿ› **Maintainers** tired of โ€œwhite screen / silent exceptionโ€ bugs agents canโ€™t see
- ๐Ÿงฐ **Tooling authors** who need a stdio MCP โ†” CDP bridge for Electron/Chromium

### ๐Ÿ’ฌ Example things you can ask the agent

> โ€œStart `D:/apps/my-app` on port 9222 and tell me if the renderer threw on boot.โ€
> โ€œFind my running Electron app, attach by PID, screenshot `#sidebar`, and dump localStorage.โ€
> โ€œType into `#email`, press Enter, wait for Welcome, then list console errors.โ€
> โ€œStart a CDP trace, click through settings, stop tracing, and save the JSON.โ€
> โ€œDiagnose why this Electron window is blank.โ€

### ๐Ÿ“Š At a glance

| Aspect | Details |
| :--- | :--- |
| ๐Ÿ”Œ **Transport** | MCP **stdio** JSON-RPC |
| ๐Ÿงฌ **Debug bridge** | Chrome DevTools Protocol (Runtime ยท Page ยท Network ยท Debugger ยท Input ยท Log ยท Tracing) |
| ๐Ÿš€ **App control** | Spawn Electron **or** attach by port / PID / process scan |
| ๐Ÿ“ฆ **Surface area** | **36 tools** ยท **6 resources** ยท **3 prompts** ยท logging + resource list-changed |
| ๐Ÿ–ฅ๏ธ **Platforms** | Windows ยท macOS ยท Linux (CI: Xvfb + no-sandbox) |
| ๐Ÿ“ฆ **Requires** | Node **โ‰ฅ 18**, npm, one-time Electron binary download |
| ๐Ÿ›ก๏ธ **Safety** | Optional `ELECTRON_MCP_ALLOWED_ROOTS` (app paths) ยท `ELECTRON_MCP_OUTPUT_ROOTS` (screenshot/trace output, plus built-in blocklist of sensitive locations); attach sessions detach-only on stop |
| โœ… **Verify** | `npm test` โ†’ unit + full MCPโ†”Electron smoke |

### โœ… Status

- ๐ŸŸข Ready for local agent-driven Electron debugging
- ๐ŸŸข E2E smoke: start โ†’ UI/automation โ†’ storage/cookies โ†’ tracing โ†’ find/attach-by-pid โ†’ stop
- ๐ŸŸข Windows binary repair: `scripts/fix-electron.cmd` when npm blocks postinstall
- ๐ŸŸข v1.5.0 โ€” element screenshots, cookies/storage, tracing, attach-by-pid
- ๐ŸŸข Built on TypeScript 7 (native Go compiler) โ€” ~10x faster builds

---

## ๐Ÿ“– Table of contents

- [Overview](#-overview)
- [Why this exists](#-why-this-exists)
- [Feature tour](#-feature-tour)
- [60-second quick start](#-60-second-quick-start)
- [Cursor & Claude Desktop setup](#-cursor--claude-desktop-setup)
- [How it works](#-how-it-works)
- [Complete tools cheatsheet](#-complete-tools-cheatsheet)
- [Tools reference (all options)](#-tools-reference-all-options)
- [Resources](#-resources-read-only)
- [Prompts](#-prompts)
- [Usage examples](#-usage-examples)
- [Configuration](#-configuration)
- [npm scripts](#-npm-scripts)
- [Testing](#-testing)
- [Project layout](#-project-layout)
- [Security](#-security)
- [Troubleshooting](#-troubleshooting)
- [Contributing](#-contributing)
- [License](#-license)

---

## โœจ Why this exists

Electron bugs are often **invisible** to coding agents:

| ๐Ÿ˜ฃ Pain | ๐Ÿ™ˆ What agents usually see | ๐Ÿ‘๏ธ What this server adds |
| --- | --- | --- |
| Blank / white window | Source files only | Live **screenshot** + DOM (+ element clip) |
| Silent renderer crash | Nothing | **Console + exception** buffer (+ live stream) |
| Failed API calls | Guesswork | **Network** event log |
| Wrong route / URL | Unknown | **page_info** / `evaluate` |
| UI not responding | Can't interact | **click** / **type_text** / **press_key** / **wait_for** |
| Auth / state bugs | Blind | **cookies** + **localStorage/sessionStorage** |
| Perf jank | Guesswork | **CDP tracing** export |
| App already running | Manual port hunt | **find_apps** / **attach_by_pid** |
| Need DevTools power | Manual only | Full **cdp_command** escape hatch |

---

## ๐Ÿš€ Feature tour

### ๐Ÿ”Œ Lifecycle
- โ–ถ๏ธ `start_app` โ€” launch with remote debugging (+ optional `inspectMain`)
- ๐Ÿ”— `attach` โ€” connect to an existing debug port
- ๐Ÿ†” `attach_by_pid` โ€” resolve port from process argv
- ๐Ÿงญ `find_apps` โ€” list Electron PIDs + debug ports
- ๐Ÿ”Ž `discover_apps` โ€” scan local CDP ports
- โน๏ธ `stop_app` โ€” kill owned / detach attached
- ๐Ÿ“‹ `list_apps` โ€” sessions, ports, buffer counts
- ๐Ÿฉบ `diagnose` โ€” port health + recent errors

### ๐Ÿ” Inspection
- ๐Ÿ“ธ `screenshot` / ๐Ÿ’พ `save_screenshot` โ€” full page or **selector clip**
- ๐ŸŒณ `get_dom` / `query_selector`
- ๐Ÿงฎ `evaluate` / `evaluate_main`
- ๐Ÿช `get_cookies` / `set_cookie`
- ๐Ÿ—„๏ธ `get_storage` / `set_storage`
- ๐Ÿงพ `get_console_messages` โ€” log/warn/error/exceptions
- ๐ŸŒ `get_network_log` โ€” request/response/fail
- ๐Ÿ“œ `get_logs` โ€” Electron stdout/stderr
- ๐ŸŽฏ `list_targets` / `page_info`

### ๐Ÿ–ฑ๏ธ Interaction
- ๐Ÿงญ `navigate` + load wait
- โณ `wait_for` โ€” selector / hidden / enabled / count / text / URL / console
- ๐Ÿ–ฑ๏ธ `click` left/right/middle
- โŒจ๏ธ `type_text` (+ clear / Enter) ยท `press_key` (+ modifiers)
- ๐Ÿ”„ `reload` ยท โธ๏ธ `pause` ยท โ–ถ๏ธ `resume`
- ๐Ÿงน `clear_buffers`

### ๐Ÿง  Agent UX & power
- ๐Ÿ“ MCP handshake **instructions**
- ๐Ÿ’ฌ Prompts: blank window ยท exceptions ยท UI smoke
- ๐Ÿท๏ธ Target roles: page / worker / browser / main
- ๐Ÿ”” `set_console_live` + resource list-changed
- ๐Ÿ“ˆ `start_tracing` / `stop_tracing`
- ๐Ÿ›ก๏ธ stderr-only diagnostics (stdio-safe)
- ๐Ÿงฐ `cdp_command` for any DevTools method

## โšก 60-second quick start

```bash
git clone https://github.com/amafjarkasi/electron-mcp-server.git
cd electron-mcp-server
npm install
npm run ensure-electron
npm run build
npm test
```

### ๐ŸชŸ Windows binary missing?

If npm warns about `allowScripts` / Electron postinstall:

```bat
.\scripts\fix-electron.cmd
```

That reinstalls Electron, extracts `electron.exe` with system `tar`, then runs tests.

---

## ๐Ÿ–ฅ๏ธ Cursor & Claude Desktop setup

### Cursor

1. `npm run build`
2. Open **Cursor โ†’ MCP settings**
3. Add (use your absolute path):

**Windows**

```json
{
"mcpServers": {
"electron-debug": {
"command": "node",
"args": ["C:/Users/you/code/electron-mcp-server/build/index.js"]
}
}
}
```

**macOS / Linux**

```json
{
"mcpServers": {
"electron-debug": {
"command": "node",
"args": ["/Users/you/code/electron-mcp-server/build/index.js"],
"env": {
"ELECTRON_MCP_NO_SANDBOX": "1"
}
}
}
}
```

4. Restart Cursor
5. Confirm tools: `start_app`, `attach`, `find_apps`, `screenshot`, `get_console_messages`, `click`, `start_tracing`, โ€ฆ

๐Ÿ“„ Template: [`examples/cursor-mcp.json`](./examples/cursor-mcp.json)

### Claude Desktop

Same `mcpServers` block in `claude_desktop_config.json`, pointing at `build/index.js`. Edit the file at:

- **macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json`
- **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`
- **Linux:** `~/.config/Claude/claude_desktop_config.json`

๐Ÿ“„ Template: [`examples/claude-desktop-config.json`](./examples/claude-desktop-config.json)

> โš ๏ธ **Donโ€™t** run `node build/index.js` in a normal terminal for daily use โ€” it waits on stdio for an MCP client. Let Cursor/Claude spawn it.

---

## ๐Ÿงฉ How it works

```text
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Cursor / Claude / MCP โ”‚
โ”‚ client (agent) โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ”‚ stdio JSON-RPC
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Electron Debug MCP โ”‚
โ”‚ ๐Ÿ› ๏ธ tools (36) โ”‚
โ”‚ ๐Ÿ“ก resources โ”‚
โ”‚ ๐Ÿ’ฌ prompts โ”‚
โ”‚ ๐Ÿ“ฃ logging / list-changedโ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ”‚ spawn / attach / PID resolve
โ”‚ CDP WebSocket
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ Electron application โ”‚
โ”‚ --remote-debugging-port โ”‚
โ”‚ RuntimeยทPageยทNetworkยทโ€ฆ โ”‚
โ”‚ optional --inspect (main)โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
```

After `start_app` / `attach` / `attach_by_pid`, page targets get **Runtime / Log / Network / Page** enabled so console + network events keep buffering between tool calls.

**Finding a running app**

1. `find_apps` โ€” OS process scan (Electron PIDs + `--remote-debugging-port` from argv)
2. `discover_apps` โ€” HTTP probe of local CDP ports (`/json/version`, `/json/list`)
3. `attach` / `attach_by_pid` โ€” open a managed session (detach-only on `stop_app`)

---

## ๐Ÿ—‚๏ธ Complete tools cheatsheet

| Category | Tools |
| --- | --- |
| ๐Ÿš€ Lifecycle | `start_app` ยท `attach` ยท `attach_by_pid` ยท `find_apps` ยท `discover_apps` ยท `stop_app` ยท `list_apps` ยท `diagnose` |
| ๐Ÿ” Inspect | `screenshot` ยท `save_screenshot` ยท `get_dom` ยท `query_selector` ยท `evaluate` ยท `evaluate_main` ยท `get_cookies` ยท `set_cookie` ยท `get_storage` ยท `set_storage` ยท `get_console_messages` ยท `get_network_log` ยท `get_logs` ยท `list_targets` ยท `page_info` |
| ๐Ÿ–ฑ๏ธ Interact | `navigate` ยท `wait_for` ยท `click` ยท `type_text` ยท `press_key` ยท `reload` ยท `pause` ยท `resume` ยท `clear_buffers` ยท `set_console_live` |
| ๐Ÿงฐ Power | `start_tracing` ยท `stop_tracing` ยท `cdp_command` |

---

## ๐Ÿ› ๏ธ Tools reference (all options)

All APIs below are MCP **tools**. Schemas match the live Zod definitions in `src/index.ts`.

### ๐Ÿš€ Lifecycle

#### `start_app`
Launch Electron with remote debugging.

| Param | Type | Req | Default | Description |
| --- | --- | --- | --- | --- |
| `appPath` | string | โœ… | โ€” | App directory or main script |
| `debugPort` | int `1024โ€“65535` | โŒ | random `9222โ€“9999` | CDP port |
| `extraArgs` | string[] | โŒ | `[]` | Extra CLI flags |
| `inspectMain` | bool | โŒ | `false` | Pass `--inspect=0` so main appears as a node target for `evaluate_main` |

**Auto flags:** `--remote-debugging-port`, `--enable-logging`, `--disable-gpu`, and `--no-sandbox` when `ELECTRON_MCP_NO_SANDBOX=1` / `CI=true` / no `DISPLAY`.

**Returns:** `id`, `pid`, `debugPort`, `targets`, `attached: false`, โ€ฆ

---

#### `attach`

| Param | Type | Req | Description |
| --- | --- | --- | --- |
| `debugPort` | int | โœ… | Existing DevTools port |
| `name` | string | โŒ | Friendly session name |

`stop_app` on attached sessions **detaches only** (does not kill the external app).

---

#### `attach_by_pid`

Attach by OS process id. Resolves `--remote-debugging-port` from the process command line (Linux/macOS/`ps`, Windows PowerShell). Falls back to listening sockets owned by the PID on Linux when needed.

| Param | Type | Req | Description |
| --- | --- | --- | --- |
| `pid` | int | โœ… | Electron **main** process id |
| `name` | string | โŒ | Friendly session name |

**Tip:** Prefer the main process PID from `find_apps` (helpers with `--type=renderer` / `gpu-process` are filtered unless they expose a debug port).

---

#### `find_apps`

List running Electron-like processes.

**Returns:** `{ apps: [{ pid, command, debugPort?, inspectPort?, likelyElectron }], count }`

Use this when you launched the app yourself and donโ€™t remember the port.

---

#### `discover_apps`

| Param | Type | Default |
| --- | --- | --- |
| `startPort` | int | `9222` |
| `endPort` | int | `9235` |

HTTP-probes each port for Chromium/Electron DevTools (`/json/version` + `/json/list`).

---

#### `stop_app` โ€” `{ processId }`
#### `list_apps` โ€” no params
#### `diagnose` โ€” optional `{ processId }` (omit = all sessions)

`diagnose` reports port reachability, target role counts, recent console errors, and monitoring state.

---

### ๐Ÿ” Inspection

#### `screenshot` / `save_screenshot`

| Param | Type | Default | Description |
| --- | --- | --- | --- |
| `processId` | string โœ… | โ€” | Session id |
| `targetId` | string | first page | CDP page target |
| `format` | `png` \| `jpeg` | `png` | Image format |
| `quality` | int `0โ€“100` | โ€” | JPEG only |
| `selector` | string | โ€” | **Element clip** โ€” capture only that nodeโ€™s bounding box |
| `path` | string โœ… (`save_screenshot`) | โ€” | File path to write |

`screenshot` returns MCP **image** content (+ JSON meta including `clip` when used).
`save_screenshot` writes bytes to disk and returns `{ path, bytes, mimeType, clip? }`.

---

#### `get_dom` โ€” `{ processId, selector?, targetId? }`
#### `query_selector` โ€” `{ processId, selector, targetId?, limit?=20 }`

#### `evaluate`

| Param | Type | Default |
| --- | --- | --- |
| `processId` | string โœ… | โ€” |
| `expression` | string โœ… | โ€” |
| `targetId` | string | auto |
| `role` | `page` \| `worker` \| `browser` \| `other` | `page` |
| `returnByValue` | bool | `true` |

#### `evaluate_main`

Evaluate in the Electron **main/node** CDP target.

| Param | Type | Default |
| --- | --- | --- |
| `processId` | string โœ… | โ€” |
| `expression` | string โœ… | โ€” |
| `targetId` | string | auto-pick node/main |
| `returnByValue` | bool | `true` |

**Requires** a node-like target โ€” start with `inspectMain: true`, or pass an explicit `targetId` from `list_targets`.

---

#### `get_cookies`

| Param | Type | Description |
| --- | --- | --- |
| `processId` | string โœ… | โ€” |
| `urls` | string[] | Optional URL filter |
| `targetId` | string | Page target |

#### `set_cookie`

| Param | Type | Description |
| --- | --- | --- |
| `processId` | string โœ… | โ€” |
| `name` / `value` | string โœ… | Cookie pair |
| `url` / `domain` | string | One required (defaults `url` to `location.href` when possible) |
| `path` | string | Cookie path |
| `secure` / `httpOnly` | bool | Flags |
| `sameSite` | `Strict` \| `Lax` \| `None` | SameSite |
| `expires` | number | Unix seconds |
| `targetId` | string | Page target |

> Note: Chromium often rejects cookies on `file://` pages โ€” use an `http(s)` URL or pass an explicit `url`/`domain`.

---

#### `get_storage` / `set_storage`

| Param | Type | Default | Description |
| --- | --- | --- | --- |
| `processId` | string โœ… | โ€” | โ€” |
| `kind` | `localStorage` \| `sessionStorage` | `localStorage` | Store |
| `entries` | `Record` โœ… (`set`) | โ€” | Keys to write |
| `clear` | bool (`set`) | `false` | Clear store before write |
| `targetId` | string | โ€” | Page target |

---

#### `get_console_messages` โ€” `{ processId, tail?, level? }`
#### `get_network_log` โ€” `{ processId, tail? }`
#### `get_logs` โ€” `{ processId, tail? }`
#### `list_targets` โ€” `{ processId? }`
#### `page_info` โ€” `{ processId, targetId? }` โ†’ url / title / readyState / userAgent

Console capture includes `console.*`, CDP Log entries, and `Runtime.exceptionThrown`.

---

### ๐Ÿ–ฑ๏ธ Interaction & control

#### `navigate` โ€” `{ processId, url, targetId?, waitUntilLoad?=true, timeoutMs?=15000 }`

#### `wait_for`

Provide **at least one** condition:

| Param | Meaning |
| --- | --- |
| `selector` | Element must exist |
| `hidden` | Element absent or not visible |
| `enabled` | Element exists and is not disabled |
| `countSelector` + `minCount` | `querySelectorAll` length โ‰ฅ min |
| `text` | `document.body.innerText` includes |
| `urlIncludes` | `location.href` includes |
| `consoleIncludes` | Buffered console text includes |
| `timeoutMs` | Default `10000` (max `120000`) |
| `screenshotOnTimeout` | Save a PNG under the OS temp dir on failure |
| `targetId` | Page target |

#### `click` โ€” `{ processId, selector, targetId?, button?=left }`
#### `type_text` โ€” `{ processId, text, selector?, clear?, pressEnter?, targetId? }`

#### `press_key`

| Param | Type | Description |
| --- | --- | --- |
| `processId` | string โœ… | โ€” |
| `key` | string โœ… | e.g. `Enter`, `Escape`, `Tab`, `ArrowDown`, `a` |
| `selector` | string | Focus/click before keypress |
| `modifiers` | `Alt` \| `Control` \| `Meta` \| `Shift`[] | Chord modifiers |
| `repeat` | int `1โ€“50` | Repeat count |
| `targetId` | string | Page target |

#### `set_console_live` โ€” `{ enabled }`
Errors/asserts **always** emit MCP logs. When enabled, log/info/warn/debug also stream live.

#### `reload` โ€” `{ processId, targetId?, ignoreCache?=false }`
#### `pause` / `resume` โ€” `{ processId, targetId? }`
#### `clear_buffers` โ€” `{ processId, console?=true, network?=true, logs?=false }`

---

### ๐Ÿงฐ Power / tracing

#### `start_tracing`

| Param | Type | Description |
| --- | --- | --- |
| `processId` | string โœ… | โ€” |
| `categories` | string | Comma-separated CDP categories (default: timeline + v8 profiler set) |
| `targetId` | string | Page target |

Only one active trace per process session.

#### `stop_tracing`

| Param | Type | Description |
| --- | --- | --- |
| `processId` | string โœ… | โ€” |
| `path` | string | Output JSON path (default: OS temp dir) |

**Returns:** `{ path, eventCount, elapsedMs, targetId, โ€ฆ }`
Open the file in Chromeโ€™s `chrome://tracing` (or Perfetto UI).

#### `cdp_command` โ€” `{ processId, method:"Domain.method", targetId?, params? }`

Escape hatch for any DevTools method not wrapped above.

---

## ๐Ÿ“ก Resources (read-only)

| URI | MIME | Description |
| --- | --- | --- |
| `electron://info` | JSON | Managed processes overview |
| `electron://targets` | JSON | All CDP targets |
| `electron://process/{id}` | JSON | Process details + webContents + recent errors |
| `electron://logs/{id}` | text | stdout/stderr capture |
| `electron://console/{id}` | JSON | Buffered console / exceptions |
| `electron://cdp/{processId}/{targetId}` | JSON | Target metadata |

---

## ๐Ÿ’ฌ Prompts

| Prompt | Args | Use when |
| --- | --- | --- |
| `debug_blank_window` | `processId` | White/blank window |
| `find_renderer_exception` | `processId` | Hunting console/exceptions |
| `ui_smoke_check` | `processId`, `selector` | Wait โ†’ interact โ†’ verify |

---

## ๐Ÿ“š Usage examples

### 1๏ธโƒฃ Start app โ†’ read title

```json
// tool: start_app
{
"appPath": "D:/apps/my-electron-app",
"debugPort": 9222,
"extraArgs": ["--no-sandbox"]
}
```

```json
// tool: evaluate
{
"processId": "electron-1710000000000",
"expression": "document.title"
}
```

### 2๏ธโƒฃ Attach to a running app (port)

```bash
electron . --remote-debugging-port=9222
```

```json
// tool: attach
{ "debugPort": 9222, "name": "my-app" }
```

### 3๏ธโƒฃ Find by PID โ†’ attach

```json
// tool: find_apps
{}
```

```json
// tool: attach_by_pid
{ "pid": 43210, "name": "my-app" }
```

### 4๏ธโƒฃ Catch console errors (+ live stream)

```json
// tool: set_console_live
{ "enabled": true }
```

```json
// tool: get_console_messages
{
"processId": "electron-1710000000000",
"level": "error",
"tail": 50
}
```

Also: resource `electron://console/{processId}`

### 5๏ธโƒฃ Screenshot โ€” full page, file, or element

```json
// tool: screenshot
{ "processId": "electron-โ€ฆ", "format": "png" }
```

```json
// tool: save_screenshot
{
"processId": "electron-โ€ฆ",
"path": "D:/tmp/app.png",
"format": "png"
}
```

```json
// tool: save_screenshot (element clip)
{
"processId": "electron-โ€ฆ",
"path": "D:/tmp/sidebar.png",
"selector": "#sidebar"
}
```

### 6๏ธโƒฃ UI automation flow

```json
// wait_for
{ "processId": "electron-โ€ฆ", "selector": "#email", "timeoutMs": 8000 }
```

```json
// type_text
{
"processId": "electron-โ€ฆ",
"selector": "#email",
"text": "ada@example.com",
"clear": true
}
```

```json
// press_key
{ "processId": "electron-โ€ฆ", "key": "Enter" }
```

```json
// click
{ "processId": "electron-โ€ฆ", "selector": "button[type=submit]" }
```

```json
// wait_for (richer conditions)
{
"processId": "electron-โ€ฆ",
"text": "Welcome",
"timeoutMs": 8000,
"screenshotOnTimeout": true
}
```

```json
// wait_for enabled / count / hidden
{ "processId": "electron-โ€ฆ", "enabled": "#submit" }
```

```json
{
"processId": "electron-โ€ฆ",
"countSelector": ".row",
"minCount": 3
}
```

```json
{ "processId": "electron-โ€ฆ", "hidden": ".spinner" }
```

### 7๏ธโƒฃ Cookies & storage

```json
// set_storage
{
"processId": "electron-โ€ฆ",
"kind": "localStorage",
"clear": true,
"entries": { "theme": "dark", "onboardingDone": "1" }
}
```

```json
// get_storage
{ "processId": "electron-โ€ฆ", "kind": "localStorage" }
```

```json
// set_cookie
{
"processId": "electron-โ€ฆ",
"name": "session",
"value": "abc",
"url": "https://app.local/"
}
```

```json
// get_cookies
{ "processId": "electron-โ€ฆ", "urls": ["https://app.local/"] }
```

### 8๏ธโƒฃ Main-process evaluate

```json
// start_app with inspectMain
{
"appPath": "D:/apps/my-electron-app",
"debugPort": 9222,
"inspectMain": true
}
```

```json
// evaluate_main
{
"processId": "electron-โ€ฆ",
"expression": "process.versions.electron"
}
```

### 9๏ธโƒฃ Performance tracing

```json
// start_tracing
{ "processId": "electron-โ€ฆ" }
```

```text
โ€ฆreproduce the slow interaction (click / navigate / wait_for)โ€ฆ
```

```json
// stop_tracing
{
"processId": "electron-โ€ฆ",
"path": "D:/tmp/app-trace.json"
}
```

Open `app-trace.json` in `chrome://tracing`.

### ๐Ÿ”Ÿ Diagnose a sick session

```json
// tool: diagnose
{ "processId": "electron-1710000000000" }
```

### 1๏ธโƒฃ1๏ธโƒฃ Navigate + page info

```json
// navigate
{
"processId": "electron-โ€ฆ",
"url": "file:///path/to/renderer/settings.html",
"waitUntilLoad": true
}
```

```json
// page_info
{ "processId": "electron-โ€ฆ" }
```

### 1๏ธโƒฃ2๏ธโƒฃ Raw CDP escape hatch

```json
// cdp_command
{
"processId": "electron-โ€ฆ",
"method": "Page.captureScreenshot",
"params": { "format": "png", "fromSurface": true }
}
```

### 1๏ธโƒฃ3๏ธโƒฃ Recommended agent loop

```text
find_apps / discover_apps / start_app / attach / attach_by_pid
โ†’ diagnose
โ†’ set_console_live(true) # optional
โ†’ get_console_messages(level="error")
โ†’ screenshot / save_screenshot(selector?)
โ†’ wait_for (if UI)
โ†’ click / type_text / press_key / evaluate / get_dom
โ†’ get_storage / get_cookies # if state matters
โ†’ start_tracing โ€ฆ stop_tracing # if perf
โ†’ stop_app
```

---

## ๐Ÿ” Configuration

### Environment variables

| Variable | Purpose |
| --- | --- |
| `ELECTRON_PATH` | Force a specific Electron binary |
| `ELECTRON_MCP_NO_SANDBOX=1` | Always pass `--no-sandbox` |
| `ELECTRON_MCP_ALLOWED_ROOTS` | `;` / `\|` allowlist for `start_app` paths |
| `ELECTRON_MCP_OUTPUT_ROOTS` | `;` / `\|` allowlist for `save_screenshot` / `stop_tracing` output paths |
| `ELECTRON_MIRROR` | Download mirror for Electron zips |
| `ELECTRON_SKIP_BINARY_DOWNLOAD` | Cleared by `ensure-electron` so download still runs |
| `ELECTRON_CACHE` / `electron_config_cache` | Zip cache directory |
| `CI=true` | Enables no-sandbox auto flag |
| unset `DISPLAY` (Linux) | Enables no-sandbox auto flag |

### Path allowlist example

```powershell
$env:ELECTRON_MCP_ALLOWED_ROOTS="D:\apps;D:\GH"
```

---

## ๐Ÿ“œ npm scripts

| Script | Does |
| --- | --- |
| `npm run ensure-electron` | Download/repair Electron binary |
| `npm run fix-electron` | Alias of ensure-electron |
| `npm run build` | Compile TS โ†’ `build/` |
| `npm start` | Run MCP server (stdio) |
| `npm run dev` | build + start |
| `npm run typecheck` | `tsc --noEmit` |
| `npm test` | ensure + build + unit + smoke |
| `npm run test:unit` | Helper unit tests |
| `npm run test:smoke` | Full MCP e2e vs fixture app |
| `postinstall` | Runs ensure-electron |

**Windows helpers:** `scripts/fix-electron.cmd` ยท `scripts/fix-electron.ps1`

---

## ๐Ÿงช Testing

```bash
npm test
```

Smoke path (v1.5):

`initialize` โ†’ tool/prompt/resource lists โ†’ `start_app` โ†’ evaluate โ†’ console/network/DOM โ†’ page_info / type_text / click / wait_for / press_key โ†’ `save_screenshot` (+ **selector clip**) โ†’ **storage** / **cookies** โ†’ **start/stop_tracing** โ†’ **find_apps** / **attach_by_pid** โ†’ screenshot โ†’ diagnose โ†’ attach โ†’ discover โ†’ stop

CI: [`.github/workflows/ci.yml`](./.github/workflows/ci.yml) (Ubuntu + Xvfb).

---

## ๐Ÿ—‚๏ธ Project layout

```text
electron-mcp-server/
โ”œโ”€โ”€ assets/logo.svg ยท logo.png
โ”œโ”€โ”€ examples/cursor-mcp.json ยท claude-desktop-config.json
โ”œโ”€โ”€ fixtures/minimal-electron-app/
โ”œโ”€โ”€ scripts/ensure-electron.mjs ยท fix-electron.cmd ยท fix-electron.ps1
โ”œโ”€โ”€ src/index.ts ยท process-manager.ts ยท events.ts ยท log.ts
โ”œโ”€โ”€ src/types/chrome-remote-interface.d.ts
โ”œโ”€โ”€ test/mcp-smoke.mjs ยท unit-helpers.test.mjs
โ”œโ”€โ”€ .github/workflows/ci.yml
โ””โ”€โ”€ README.md ยท LICENSE ยท package.json ยท tsconfig.json
```

---

## ๐Ÿ›ก๏ธ Security

- Can launch local binaries, evaluate JS in app contexts, read page content, cookies, and storage โ€” treat as a **powerful local debugger**.
- Use `ELECTRON_MCP_ALLOWED_ROOTS` on shared machines.
- `save_screenshot` / `stop_tracing` reject writes to sensitive locations (`~/.ssh`, `/etc`, `/proc`, `/usr`, `C:\Windows`, `C:\Program Files`, โ€ฆ). Set `ELECTRON_MCP_OUTPUT_ROOTS` to further restrict output to specific directories.
- Donโ€™t expose stdio over an open network without auth.
- Only `attach` / `attach_by_pid` to apps you trust (remote debugging is powerful).
- In-memory console/network buffers and exported traces may contain secrets from the app under test.

---

## ๐Ÿงฏ Troubleshooting

| Symptom | Fix |
| --- | --- |
| `Electron failed to install correctly` | `.\scripts\fix-electron.cmd` / `npm run ensure-electron` |
| `path.txt` missing / `dist=locales` | Corrupt cache โ€” repair script clears + uses `tar` |
| `allowScripts` warning | Expected on newer npm โ€” run ensure/fix scripts |
| Hang + console title `Select โ€ฆ` | Windows QuickEdit โ€” press Esc; disable QuickEdit |
| Empty console buffer | Wait for page activity; monitoring starts on start/attach; try `set_console_live` |
| `wait_for` / `click` fails | Selector not ready โ€” wait first; screenshot to verify |
| Element screenshot hangs / times out | Headless/GPU quirks โ€” server retries without `fromSurface`; ensure selector is visible |
| `set_cookie` fails on `file://` | Pass an `http(s)` `url`/`domain` |
| `evaluate_main` โ€œNo main/node targetโ€ | Restart with `inspectMain: true` or pass `targetId` |
| `attach_by_pid` canโ€™t resolve port | App must be started with `--remote-debugging-port`; check `find_apps` |
| `start_app` path rejected | Outside `ELECTRON_MCP_ALLOWED_ROOTS` |
| `node build/index.js` โ€œdoes nothingโ€ | Waiting on MCP stdio โ€” use Cursor config |
| Port in use | Change `debugPort` or `discover_apps` / `find_apps` |
| Linux headless | `ELECTRON_MCP_NO_SANDBOX=1` + Xvfb |
| Tracing empty / fails | Call `start_tracing` before the slow path; only one active trace per session |

---

## ๐Ÿค Contributing

1. Fork + branch
2. `npm test`
3. PR with tool/behavior notes
4. Keep stdout MCP-clean (log to stderr only)

---

## ๐Ÿ“„ License

[ISC](./LICENSE) ยฉ Electron Debug MCP contributors

---


Electron Debug MCP

Built for agents that need eyes โ€” and hands โ€” inside Electron.