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.
- Host: GitHub
- URL: https://github.com/amafjarkasi/electron-mcp-server
- Owner: amafjarkasi
- License: isc
- Created: 2025-04-06T07:17:51.000Z (over 1 year ago)
- Default Branch: master
- Last Pushed: 2026-07-26T03:23:34.000Z (15 days ago)
- Last Synced: 2026-07-26T05:07:13.123Z (14 days ago)
- Topics: ai-agents, automation, cdp, chrome-devtools-protocol, cursor, debugging, desktop-apps, devtools, electron, mcp, model-context-protocol, typescript
- Language: JavaScript
- Size: 908 KB
- Stars: 78
- Watchers: 2
- Forks: 21
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
- awesome-mcp-servers - **electron-mcp-server** - ๐ A powerful MCP server for debugging Electron applications with deep Chrome DevTools Protocol integration. Control, monitor, and debug Electron apps through a standardized API. `typescript` `mcp` `server` `api` `npm install amafjarkasi/electron-mcp-server` (๐ Web Development)
README
โก 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
---
## ๐ 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
---

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