Electron Stagewrightdocs

Connect your MCP client

Wire the published server into your MCP client — Claude Code, Codex, Claude Desktop, Cursor, VS Code, opencode, or any MCP-capable host — and confirm it connected, so an agent can drive your own Electron app. This is the task-oriented counterpart to Getting started: that tutorial clones the repository to drive the bundled example; here you install the published package and point your client at it.

The server speaks the Model Context Protocol over stdio — your client spawns it as a child process and exchanges JSON-RPC frames over stdin/stdout. You give the client a command and args that launch the server; everything else is the client's standard MCP configuration.

Before you start

Pick how the client launches the server

The client needs a command and args that start the stdio server. Prefer a pinned, project-local install: it avoids registry work during normal client startup, travels with the project's lockfile, and gives --app-root a stable security boundary.

Configure your client

Each client stores MCP servers in its own config file, and the command and arguments you picked above are the same everywhere; only the wrapper changes. Claude Desktop and Cursor use the common mcpServers JSON shape, Codex uses TOML, VS Code uses a servers key, and opencode takes the command as one array. Each section below shows the exact shape. The Claude Desktop and Cursor examples use the project-local node form, which needs that install first; with npx, put the npx command and arguments in their place.

Claude Code

Register the server with claude mcp add; everything after -- is the command and arguments you picked above:

claude mcp add electron-stagewright -- \
  npx -y --prefix ~/ --package @electron-stagewright/core@0.8.1 \
  --package playwright@1.63.0 --package electron@42.11.10 \
  electron-stagewright --tool-profile essential

The default scope is the current project only; --scope project writes the same entry to a shared .mcp.json. claude mcp list should show the server as connected, and /mcp inside a session lists its tools as mcp__electron-stagewright__electron_launch and so on. Start a new session after adding it so the agent sees the tools.

Codex

Run the terminal bootstrap above first, then register the server with codex mcp add:

codex mcp add electron-stagewright -- \
  npx -y --prefix ~/ --package @electron-stagewright/core@0.8.1 \
  --package playwright@1.63.0 --package electron@42.11.10 \
  electron-stagewright --tool-profile essential

That writes an entry to ~/.codex/config.toml. Edit it to add two settings Codex needs for this server:

[mcp_servers.electron-stagewright]
command = "npx"
args = [
  "-y",
  "--prefix", "~/",
  "--package", "@electron-stagewright/core@0.8.1",
  "--package", "playwright@1.63.0",
  "--package", "electron@42.11.10",
  "electron-stagewright",
  "--tool-profile", "essential",
]
startup_timeout_sec = 30
env_vars = ["DISPLAY", "WAYLAND_DISPLAY", "XAUTHORITY"]

codex mcp list shows only the configuration. Run /mcp in the Codex TUI to see whether the server connected; its tools appear under the electron-stagewright name.

Claude Desktop

Edit claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/; Windows: %APPDATA%\Claude\), then fully restart the app:

{
  "mcpServers": {
    "electron-stagewright": {
      "command": "node",
      "args": [
        "/absolute/path/to/your-electron-app/node_modules/@electron-stagewright/core/dist/cli.js",
        "--tool-profile",
        "essential",
        "--app-root",
        "/absolute/path/to/your-electron-app"
      ]
    }
  }
}

Cursor

Add an MCP server in .cursor/mcp.json (project-scoped) or the global ~/.cursor/mcp.json, then reload:

{
  "mcpServers": {
    "electron-stagewright": {
      "command": "node",
      "args": [
        "/absolute/path/to/your-electron-app/node_modules/@electron-stagewright/core/dist/cli.js",
        "--tool-profile",
        "essential",
        "--app-root",
        "/absolute/path/to/your-electron-app"
      ]
    }
  }
}

VS Code

VS Code reads .vscode/mcp.json in the workspace. Its top-level key is servers, not mcpServers, so a config copied from another client will not load:

{
  "servers": {
    "electron-stagewright": {
      "type": "stdio",
      "command": "npx",
      "args": [
        "-y",
        "--prefix",
        "~/",
        "--package",
        "@electron-stagewright/core@0.8.1",
        "--package",
        "playwright@1.63.0",
        "--package",
        "electron@42.11.10",
        "electron-stagewright",
        "--tool-profile",
        "essential"
      ]
    }
  }
}

To add it to your user profile instead, pass the same command to code --add-mcp '{"name":"electron-stagewright","command":"npx","args":[...]}'. Run MCP: List Servers from the Command Palette to check that it started.

opencode

Add the server to opencode.json in the project. opencode takes the command and its arguments as one array:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "electron-stagewright": {
      "type": "local",
      "command": [
        "npx",
        "-y",
        "--prefix",
        "~/",
        "--package",
        "@electron-stagewright/core@0.8.1",
        "--package",
        "playwright@1.63.0",
        "--package",
        "electron@42.11.10",
        "electron-stagewright",
        "--tool-profile",
        "essential"
      ],
      "enabled": true
    }
  }
}

opencode mcp list should report electron-stagewright as connected.

Desktop apps that do not see your shell PATH

Some desktop hosts, Claude Desktop among them, do not load your shell profile when you open them from the Dock or Finder. A Node.js installed through nvm, fnm, volta, or asdf is then missing from their PATH, and the server fails to start with npx or node not found in the host's log. An absolute path to npx is not enough on its own: npx is a Node.js script, so it fails with env: node: No such file or directory. Give the host the absolute npx and a PATH that contains Node.js:

{
  "command": "/Users/you/.local/share/fnm/aliases/default/bin/npx",
  "args": ["-y", "--prefix", "~/", "--package", "@electron-stagewright/core@0.8.1", "..."],
  "env": { "PATH": "/Users/you/.local/share/fnm/aliases/default/bin:/usr/bin:/bin" }
}

Use a directory that stays stable across shells. command -v node prints a per-session path under fnm, so point at the default alias instead (~/.local/share/fnm/aliases/default/bin); with nvm, use ~/.nvm/versions/node/<version>/bin. The project-local form avoids npx but still needs the absolute path to node as its command.

Any other MCP host

Use the same command and args in whatever stdio-server schema your host expects. Any host that spawns a stdio MCP server can run this one; the transport contract is the child process's stdin and stdout.

Server flags

Append flags to args (after the package/CLI). The common ones:

Profile Intended surface electron_screenshot
essential Focused launch, inspect, interact, and assert No
testing Broader test driving with screenshot evidence Yes
debug Attach, inspect, and diagnostics Yes
full Complete compatibility surface Yes

--screenshot-dir supplies the default output directory when the selected profile exposes electron_screenshot; use testing, debug, or full when stable screenshot artifacts are part of the workflow.

With npx, server flags follow the electron-stagewright bin name:

{
  "args": [
    "-y",
    "--prefix",
    "~/",
    "--package",
    "@electron-stagewright/core@0.8.1",
    "--package",
    "playwright@1.63.0",
    "--package",
    "electron@42.11.10",
    "electron-stagewright",
    "--tool-profile",
    "essential",
    "--app-root",
    "/absolute/path/to/your-electron-app",
    "--allow-eval=renderer"
  ]
}

Verify it connected

Before restarting the client, run doctor from a terminal with the same package list and flags. A working setup prints one JSON document with "ok": true and exits 0; each entry in checks reports pass, or skip when it does not apply (for example, the display check outside Linux):

{
  "ok": true,
  "checks": [
    { "id": "node", "status": "pass", "message": "Node v24.19.0 satisfies the >=24 floor." },
    {
      "id": "playwright",
      "status": "pass",
      "message": "playwright is resolvable by the server process."
    },
    {
      "id": "electron",
      "status": "pass",
      "message": "electron is resolvable by the server process."
    }
  ]
}

The real report lists more checks; the shape is the same. After saving the config and restarting the client:

  1. The client lists the server's tools. You should see the electron_* catalog — electron_launch, electron_snapshot, electron_find, and the rest. If electron_eval_main and electron_eval_renderer are absent, that is expected: they only appear when you pass --allow-eval.
  2. Drive one round-trip. Ask the agent to electron_launch your app, then electron_snapshot. A populated snapshot — the accessibility tree with numbered refs — means the wiring works. End with electron_stop so no app process outlives the session.

No host handy? The Getting started scripted scenario connects a real MCP client over stdio without any host, which is a quick way to confirm the server itself runs.

Update to a new release

Every install form above pins exact versions, so nothing updates on its own. Move to a new release deliberately, in this order:

  1. Find the release and its package set. npm view @electron-stagewright/core version prints the latest core version. Each release's notes list what changed, what to act on, and the plugin versions that go with that core; the README quick start shows the tested Playwright and Electron versions. Every @electron-stagewright/plugin-* package depends on one exact core version, so plan to move each plugin you load together with core; an old plugin pin installs a second copy of core. npm view @electron-stagewright/plugin-trace dependencies shows which core a plugin version needs. The demo package does not depend on core.

  2. Prepare the new package list before any host uses it. With npx, run install-electron and doctor --json with the new --package list and your server flags, exactly as for a first install; the project-local and global forms install and fetch Electron in step 3. npx treats a changed list as a separate install, so its Electron binary has to be fetched even when only core changed; Electron reuses its download cache, so this is quick when the Electron version did not change.

  3. Point the host at the new versions. Keep every flag you already pass (--allow-eval, --app-root, --plugin, --tool-profile, and so on); only the versions change.

    • Claude Code: claude mcp add refuses a name that already exists, and claude mcp remove forgets your flags. Print the current entry first, then remove it and add it back in the same scope with the same flags and the new versions:

      claude mcp get electron-stagewright   # note the Scope and the Args
      claude mcp remove electron-stagewright -s local
      claude mcp add electron-stagewright -s local -- \
        npx -y --prefix ~/ --package @electron-stagewright/core@<new> \
        --package playwright@<new> --package electron@<new> \
        electron-stagewright <the same flags as before>
      

      Use -s user or -s project instead of -s local when claude mcp get shows that scope; a project-scope entry lives in .mcp.json, so you can also edit the versions there.

    • Codex: edit the versions in args under [mcp_servers.electron-stagewright] in ~/.codex/config.toml.

    • Claude Desktop, Cursor, VS Code, opencode: edit the versions in that host's config file.

    • Project-local: update the dependencies (add electron@<new> to the same command if you added Electron only for Stagewright), then fetch the Electron binary:

      pnpm add --save-dev --save-exact @electron-stagewright/core@<new> playwright@<new>
      pnpm exec install-electron
      
    • Global: rerun the global install with the new versions, then install-electron.

  4. Restart the host, or start a new session, so it spawns the updated server.

  5. Confirm the version. electron-stagewright --version, run through the same npx -y --prefix ~/ --package ... command, prints the core version, and doctor --json reports the running versions under runtime.server (core, playwright, electron). With the debug or full profile, the electron_doctor tool returns the same report from inside a session.

Remove the server

  1. Remove it from the host.
    • Claude Code: claude mcp remove electron-stagewright (add --scope project to remove a shared entry from .mcp.json).
    • Codex: codex mcp remove electron-stagewright.
    • Claude Desktop, Cursor, VS Code, opencode: delete the electron-stagewright entry from the config file, then restart or reload the host.
  2. Uninstall the packages if you installed them. Project-local: pnpm remove @electron-stagewright/core playwright, plus Electron if you added it only for Stagewright and any plugin packages. Global: pnpm remove --global with the same names. The npx form installs nothing permanently.
  3. Optionally reclaim disk space. npx keeps each package list under _npx in npm's cache (npm config get cache prints its location, usually ~/.npm). Deleting _npx is safe; the next npx run of any tool downloads again. Electron keeps downloaded archives in its own cache: ~/Library/Caches/electron on macOS, ~/.cache/electron on Linux, and %LOCALAPPDATA%\electron\Cache on Windows. Screenshots go to the OS temporary directory unless you set --screenshot-dir.

Troubleshooting

The failure modes are almost all about the stdio channel or the spawn command.

Symptom Likely cause Fix
Server shows "failed" / disconnects immediately Something wrote to stdout — for a stdio server, stdout is the protocol channel, so any stray print corrupts the stream The server sends all diagnostics to stderr by design. If you wrapped it in a shell script, make sure the wrapper prints nothing to stdout.
Client reports "server not found" / no tools Wrong command/args With npx, confirm the exact package name. With the local-checkout form, the path must be absolute and you must have run pnpm build.
Codex reports the server timed out during startup Codex allows 10 seconds by default, and an npx resolution can take longer Set startup_timeout_sec = 30 on the server in ~/.codex/config.toml, and run the terminal bootstrap first.
A desktop host logs npx or node not found The host started from the Dock or Finder without your shell PATH Use the absolute npx path and an env.PATH that contains Node.js; see the desktop-apps section above.
doctor fails the display check, or no app window opens on Linux The server process has neither DISPLAY nor WAYLAND_DISPLAY (a headless machine, an SSH session, or a host that filters the environment, such as Codex) Run the host in a desktop session, start it under xvfb-run -a, or forward DISPLAY, WAYLAND_DISPLAY and XAUTHORITY (in Codex, through env_vars).
Server won't start; a version/engine error Node below the version floor The server requires Node 24+. Check node -v; with npx, the client must resolve a new-enough Node.
doctor reports electron as failed right after a fresh install Electron has not downloaded its binary yet; it does that on first use Run install-electron with the same --package list (or pnpm exec install-electron in the project), then run doctor again.
electron_launch reports that Playwright or Electron is not installed The core package was started without an optional launch peer Use the pinned npx form shown above, install all three packages globally, or pass executablePath to electron_launch.
doctor fails playwright or electron with Cannot find module under npx npx ran inside a project that already has that package at the pinned version, so it left the package out of its cache Add --prefix ~/ after -y in every npx command for the server, rerun install-electron and doctor, then restart the host.
project_runtime warns about ABI or a native addon The server's default Electron differs from the app's runtime, or inventory is incomplete Start the server with --app-root <project>, run electron-stagewright doctor --json, then launch with main; the project runtime is the default under --app-root.
electron_eval_main / electron_eval_renderer missing Eval tools are gated off by default Add --allow-eval (or --allow-eval=renderer / =main) to args. Read the security model first.
A known core tool is missing The selected core profile does not include it Restart with the profile named in the tool's recovery hint, or use --tool-profile full.
electron_launch returns FUSES_BLOCK_LAUNCH A main-based Playwright launch selected a runtime that disables the Node CLI inspect fuse For a packaged app, launch with executablePath and no main; otherwise use a compatible development runtime.
electron_launch returns ELECTRON_RUNTIME_MISSING Electron downloads its binary on first use, and the server refuses to do that mid-session Run install-electron with the server's --package list (or pnpm exec install-electron in the project), or pass executablePath.
The app won't launch from electron_launch main is not an absolute path, or the app needs attach/inject Pass an absolute main; see Launch, attach, or inject for apps that are already running.

Where next