electron-stagewright
Health Warn
- License — License: MIT
- Description — Repository has a description
- Active repo — Last push 0 days ago
- Low visibility — Only 5 GitHub stars
Code Fail
- eval() — Dynamic code execution via eval() in packages/core/src/errors/operation-type.ts
Permissions Pass
- Permissions — No dangerous permissions requested
No AI report is available for this listing yet.
Drive Electron apps the way Playwright drives browsers — MCP server for AI agents.
Electron Stagewright
Agent-native UX from line one. Drive Electron apps the way Playwright drives browsers — but designed for AI agents, not adapted for them.
A Model Context Protocol (MCP) server that lets AI agents — Claude Code, Codex, Cursor, Cline, Aider, and any MCP-compatible host — operate real Electron desktop applications. Click, type, evaluate JavaScript in main or renderer, capture screenshots, intercept IPC, replay sessions, validate signed .app bundles, and more.
Status: pre-alpha. Architecture locked, implementation underway. Star the repo to follow releases.
Why this exists
Most MCP servers in the wild are Playwright APIs wrapped in an MCP transport. They work, but their UX is a human's API exposed to an agent — leaving the agent to do all the reasoning, comparisons, and recovery manually. Token budgets evaporate on round-trips that shouldn't need to exist.
Electron Stagewright is designed agent-first from the primitive level up:
- Errors carry hints, suggested next actions, and similar-ref alternatives — agents recover without an extra round-trip asking for context.
- Every response reports its own token cost — agents budget in real time, not after the fact.
get_statereturns the full state envelope in one call — visible, enabled, checked, focused, disabled, aria-expanded, aria-busy, aria-invalid. No 4-call chain to decide if a button is clickable.wait_for_stateaccepts composite predicates —{ visible: true, enabled: true, focused: false }evaluated atomically by the server. One call replaces three.- Snapshots flag
recently_changedelements — agents focus reasoning on what differs from the last view instead of reprocessing the whole tree. - Snapshot diffs are a parameter, not a separate tool —
snapshot({ since: 'last' })returns only deltas. Fewer APIs to remember. expect_*primitives replace read-compare-retry chains —expect_text({ ref, equals: 'Welcome', timeoutMs: 5000 })is one call, not five.findqueries the accessibility tree semantically —find({ role: 'button', name_contains: 'Submit', visible: true })— no CSS selectors, no XPath, no guessing.- Hot-reload-aware — if the renderer reloaded during a session, the next response carries
_meta.renderer_reloaded_since_last_snapshot: trueso agents know their refs are stale before failing. - Framework-agnostic snapshot — works on React, Vue, Svelte, Lit, Solid, Qwik, vanilla. Detection via accessibility roles and ARIA, never via framework-internal properties.
What competitors don't cover (yet)
The MCP ecosystem for browser automation is mature. The MCP ecosystem for desktop Electron apps is fragmented and missing three structural capabilities that no existing server delivers:
- Attach to a running dev server without restarting it. Every alternative requires
--remote-debugging-portfrom launch. Electron Stagewright injects at runtime via Node Inspector handshake — your dev server keeps running, your state is preserved. - Session traces with deterministic replay and per-tool token budgets. Inspired by Playwright's
trace.zipbut designed for LLM agent sessions: timeline of DOM, console, network, IPC, and screenshots — replayable against a fresh app instance, with token estimates so agents can cap runaway loops. - End-to-end validation of signed, notarized, packaged
.appbundles —codesign, Gatekeeper assessment, autoUpdater feed inspection,protocol.registerFileProtocolscheme verification,crashReportercapture. The full production surface, not just dev.
Microsoft's official Playwright MCP team explicitly declined to support Electron ("you can release your own server for Electron" — Pavel Feldman, lead). This project takes the invitation seriously.
Quick start
The package is not published yet. Once the first release ships:
# Register with Claude Code
claude mcp add electron-stagewright --scope user -- npx -y @electron-stagewright/core
# Or in your project .mcp.json
{
"mcpServers": {
"electron-stagewright": {
"command": "npx",
"args": ["-y", "@electron-stagewright/core"]
}
}
}
Then from any MCP-compatible agent:
// Launch
mcp__electron-stagewright__launch({
main: "/abs/path/to/.vite/build/main.js",
env: { MY_ENV_VAR: "value" }
})
// Inspect with full state per ref
mcp__electron-stagewright__snapshot()
// → [1] button "Open File" enabled=true visible=true
// [2] button "Settings" enabled=true visible=true
// [3] textbox "Email" value="" focused=false
// [4] heading "Welcome"
// Interact by ref
mcp__electron-stagewright__click({ ref: 2 })
// Wait for a composite state in one call
mcp__electron-stagewright__wait_for_state({
ref: 3, state: { focused: true, enabled: true }, timeoutMs: 2000
})
// Assert + retry in one call instead of read-compare-retry chain
mcp__electron-stagewright__expect_text({ ref: 4, equals: "Welcome back" })
// Stop
mcp__electron-stagewright__stop()
What each response looks like (the agent-UX detail)
Success:
{
"ok": true,
"ref": 3,
"settled": true,
"_meta": {
"estimated_tokens": 47,
"elapsed_ms": 142,
"renderer_reloaded_since_last_snapshot": false,
},
}
Error:
{
"ok": false,
"error": "ref 7 not found in current snapshot",
"code": "REF_NOT_FOUND",
"hint": "The DOM may have rerendered since the last snapshot.",
"next_actions": ["snapshot()", "wait_for_state({ ref: 5, state: 'visible' })"],
"similar_refs": [
{ "ref": 9, "role": "button", "name": "Submit" },
{ "ref": 12, "role": "button", "name": "Cancel" },
],
"retryable": false,
"http": 404,
"_meta": { "estimated_tokens": 89, "elapsed_ms": 23 },
}
The agent has everything to decide its next move without asking for context.
Architecture
Three transport implementations behind a single ITransport interface, so the project survives if Playwright's experimental _electron API changes or gets deprecated:
PlaywrightElectronTransport—_electron.launch(), fast path (default).CDPTransport— Chrome DevTools Protocol direct, no Playwright dependency, stable.InjectorTransport— Node Inspector handshake into running process, no pre-flag required.
Plugin model: small core, domain plugins ship as @electron-stagewright/plugin-* packages (production, trace, network, clock, storage, ipc, macos-native).
Dogfooding targets
The MCP is built against two real Electron applications maintained by the author, covering distinct verticals so the design doesn't accidentally bias to one shape:
- Code-editor shape — a code editor with runtime sandboxes, licensing, and IPC-heavy state. Stresses keyboard-driven flows, editor state, and license verification.
- POS shape — a multi-tenant Point of Sale desktop app with embedded Fastify server and SQLite. Stresses forms, large tables, embedded backend, auto-updater feeds.
If your Electron app has a shape these don't cover, open an issue — we'd love to add it as an example fixture.
Contributing
This project is in its earliest days. Issues and discussions welcome. See CONTRIBUTING.md.
License
MIT — see LICENSE.
Reviews (0)
Sign in to leave a review.
Leave a reviewNo results found