Electron UI automation MCP server with Playwright-style primitives
npm install electron-ui-mcp> ⚠️ WARNING: This project is under active development and not ready for production use.
>
> APIs, tool names, and configuration formats may change without notice.
Electron UI automation MCP server with Playwright-style primitives.
This package provides a Model Context Protocol (MCP) server that enables AI assistants to automate Electron desktop applications using a familiar Playwright-like API.
- Electron-focused tool naming - Uses electron_ for renderer tools and main_ for main process tools
- Auto-detection - Automatically finds Electron entry points when run from a project root
- Lazy initialization - App launches automatically on first tool call
- Lifecycle guards - State machine ensures tools only run when app is ready
- Snapshot-based element addressing - ARIA tree snapshots with element refs (e0, e1, etc.)
- Annotated screenshots - Overlay ref labels on screenshots for visual debugging
- Dev and packaged app support - Works with both development builds and packaged executables
- Session-scoped app override - Tools accept an optional app field to override entry/path detection
No installation required - use npx directly:
``bash`
claude mcp add electron-ui-mcp -- npx electron-ui-mcp --dev .vite/build/main.js --cwd /path/to/your-electron-app
`bash`
codex mcp add electron-ui-mcp -- npx electron-ui-mcp --dev .vite/build/main.js --cwd /path/to/your-electron-app
`bash`
gemini mcp add electron-ui-mcp -- npx electron-ui-mcp --dev .vite/build/main.js --cwd /path/to/your-electron-app
`bashDev mode - launch from main.js entry
electron-ui-mcp --dev .vite/build/main.js --cwd /path/to/app
$3
`
Options:
--dev Launch dev mode with main.js entry (auto-detects if omitted)
--packaged Launch packaged app executable
--cwd Working directory
--user-data-dir Custom userData directory
--no-isolated Disable isolated userData (default: enabled)
--dev-server Dev server URL for renderer
--e2e Enable E2E mode
--timeout Launch timeout (default: 60000)
--config Path to config file
`Configuration
$3
Add to your Claude Desktop config (
~/.claude.json):`json
{
"mcpServers": {
"electron": {
"command": "npx",
"args": ["electron-ui-mcp", "--dev", ".vite/build/main.js"],
"cwd": "/path/to/your-electron-app"
}
}
}
`$3
Codex stores MCP config in
~/.codex/config.toml:`toml
[mcp_servers.electron]
command = "npx"
args = ["electron-ui-mcp", "--dev", ".vite/build/main.js", "--cwd", "/path/to/your-electron-app"]
`$3
Gemini stores MCP config in
~/.gemini/settings.json:`json
{
"mcpServers": {
"electron": {
"command": "npx",
"args": ["electron-ui-mcp", "--dev", ".vite/build/main.js", "--cwd", "/path/to/your-electron-app"]
}
}
}
`$3
Create
electron-ui-mcp.json in your project root:`json
{
"mode": "dev",
"appPath": ".vite/build/main.js",
"rendererUrl": "http://localhost:5173",
"isolated": true,
"e2e": true,
"timeout": 60000
}
`$3
| Variable | Description |
|----------|-------------|
|
ELECTRON_APP_PATH | Path to executable or main.js |
| ELECTRON_CWD | Working directory |
| ELECTRON_USER_DATA_DIR | Custom userData directory |
| ELECTRON_RENDERER_URL | Dev server URL for renderer |
| E2E | Enable E2E mode (sets E2E=1) |
| ELECTRON_LAUNCH_TIMEOUT | Launch timeout in ms |
| ELECTRON_MODE | dev or packaged |Auto-Detection
When run from an Electron project root without explicit
--dev or --packaged flags, the MCP server automatically detects the entry point by checking (in order):1.
.vite/build/main.js (Electron Forge + Vite)
2. dist/main.js
3. dist/main/index.js (Electron Builder)
4. out/main.js
5. out/main/index.js
6. build/main.js
7. package.json#main (if it exists on disk)The server validates that
package.json contains an Electron dependency before attempting auto-detection.$3
All renderer tools accept an optional
app field to override detection for the current session (until another override is provided):`json
{
"name": "electron_snapshot",
"arguments": {
"app": {
"path": "/path/to/my-electron-app",
"entry": "out/main/index.js",
"isolated": true,
"e2e": true
}
}
}
`| Field | Description |
|-------|-------------|
|
path | App root directory (defaults to CWD) |
| entry | Explicit entry point (relative to path) |
| devServer | Dev server URL for renderer |
| isolated | Use isolated userData (default: true) |
| e2e | Enable E2E mode |Available Tools
$3
| Tool | Description |
|------|-------------|
|
electron_navigate | Navigate to URL |
| electron_navigate_back | Go back in history |
| electron_snapshot | Capture accessibility tree with refs |
| electron_screenshot | Take screenshot (with optional ref annotations) |
| electron_click | Click element by ref |
| electron_type | Type into element |
| electron_press_key | Press keyboard key |
| electron_fill_form | Fill multiple form fields |
| electron_select_option | Select dropdown option |
| electron_hover | Hover over element |
| electron_drag | Drag and drop |
| electron_file_upload | Upload files |
| electron_handle_dialog | Handle JS dialogs |
| electron_wait_for | Wait for condition |
| electron_evaluate | Execute JS in renderer |
| electron_windows | List/select windows |
| electron_resize | Resize window |
| electron_close | Close application |
| electron_console | Get console log |
| electron_network | Get network log |$3
| Tool | Description |
|------|-------------|
|
main_evaluate | Execute JS in main process |
| main_app_info | Get app metadata |How It Works
$3
The
electron_snapshot tool captures an accessibility tree of the current page:`
- [e0] heading "Welcome" [level 1]
- [e1] button "Sign In"
- [e2] textbox "Email"
- [e3] textbox "Password"
- [e4] button "Submit"
`Use these refs with interaction tools:
`json
{
"name": "electron_click",
"arguments": {
"element": "Submit button",
"ref": "e4"
}
}
`Important: Refs are invalidated when a new snapshot is taken or when switching between windows. Always take a fresh snapshot before interacting with elements.
$3
Use
electron_screenshot with annotate: true to overlay ref labels on the screenshot:`json
{
"name": "electron_screenshot",
"arguments": {
"annotate": true
}
}
`This draws red highlight boxes and ref labels (e0, e1, etc.) at each element's position, making it easy to visually identify which ref corresponds to which UI element.
Note: If no snapshot has been taken yet,
annotate: true will automatically capture one, which generates new refs. This can invalidate refs from a previous snapshot.`
┌─────────────────────────────────┐
│ e0 │
│ ┌───────────────────────────┐ │
│ │ Welcome to App │ │
│ └───────────────────────────┘ │
│ │
│ e1 e2 │
│ ┌──────┐ ┌─────────────────┐ │
│ │Email │ │_________________│ │
│ └──────┘ └─────────────────┘ │
│ │
│ e3 │
│ ┌────────┐ │
│ │ Submit │ │
│ └────────┘ │
└─────────────────────────────────┘
`If no snapshot has been taken yet, one will be captured automatically before annotating.
$3
The server manages these states:
-
idle - Not launched
- launching - Starting up
- ready - App running, ready for tools
- error - Launch failed
- closed - App was closedTools automatically launch the app if needed (lazy initialization).
Programmatic Usage
Install as a dependency:
`bash
npm install electron-ui-mcp
`Then use in your code:
`typescript
import { createServer, resolveConfig } from 'electron-ui-mcp';const config = resolveConfig({
dev: '.vite/build/main.js',
isolated: true,
});
const server = createServer(config);
`Security Considerations
$3
The
main_evaluate tool executes arbitrary JavaScript in the Electron main process. This is intentionally powerful for automation but should only be used in trusted environments. The main process has full Node.js and system access.$3
By default, all environment variables from the host process are passed to the launched Electron app. This can unintentionally expose secrets if the app logs or exposes environment variables. Prefer a sanitized environment or set specific variables via the config. Isolation is enabled by default; use
--no-isolated only if you need real user data.$3
The
electron_file_upload` tool can read arbitrary local files. This is expected behavior for automation but worth noting when exposing this server to untrusted callers.- Node.js >= 18
- Electron >= 28 (peer dependency)
- Playwright >= 1.50
MIT