Skip to content

feat(desktop): bundle chrome-devtools-mcp as dependency, eliminate npx requirement#1670

Merged
benjaminshafii merged 1 commit intodevfrom
feat/bundle-chrome-devtools-mcp
May 6, 2026
Merged

feat(desktop): bundle chrome-devtools-mcp as dependency, eliminate npx requirement#1670
benjaminshafii merged 1 commit intodevfrom
feat/bundle-chrome-devtools-mcp

Conversation

@benjaminshafii
Copy link
Copy Markdown
Member

Summary

  • Bundles chrome-devtools-mcp@0.17.0 as a direct dependency of @openwork/desktop, so the Electron app no longer requires npm/npx on PATH to run Chrome DevTools MCP.
  • In the Electron runtime, the main process resolves the bundled bin path via createRequire and exposes it through a new resolveChromeDevtoolsMcpBin IPC handler.
  • When connecting Chrome DevTools MCP from the UI, the resolved ["node", "<abs-path>"] command is written to opencode.json instead of ["npx", "-y", "chrome-devtools-mcp@latest"].
  • The Bun-compiled sidecar shim build is removed from prepare-sidecar.mjs. The shim script itself is updated to try the bundled package first and fall back to npm exec only if unavailable.

Why

Not every user has npx available. Since Electron already ships a full Node.js runtime, we can resolve and run the bundled package directly — zero external tooling required.

Test plan

  • 19 new tests across 2 test files (all pass):
    • apps/app/tests/chrome-devtools-mcp-resolution.test.ts — tests buildChromeDevtoolsCommand with resolved base, isChromeDevtoolsMcp, usesChromeDevtoolsAutoConnect, and verifies the installed package bin is resolvable.
    • apps/desktop/scripts/chrome-devtools-mcp-shim.test.ts — verifies the shim resolution logic, bin shebang, package.json bin field, and pinned version.
  • All 32 existing tests pass (bun test apps/app/tests/ — 0 failures).
  • Tauri path is untouched (the .rs auto-injection and Tauri sidecar config remain as-is for backwards compatibility).
bun test apps/app/tests/
# 32 pass, 0 fail, 48 expect() calls

bun test apps/desktop/scripts/chrome-devtools-mcp-shim.test.ts
# 4 pass, 0 fail, 5 expect() calls

Files changed

File Change
apps/desktop/package.json Add chrome-devtools-mcp@0.17.0 dependency
apps/desktop/electron/main.mjs Add resolveChromeDevtoolsMcpBin IPC + createRequire import
apps/app/src/app/mcp.ts Add resolveChromeDevtoolsMcpCommand() async resolver
apps/app/src/react-app/domains/connections/store.ts Use resolved command for Electron runtime
apps/desktop/scripts/chrome-devtools-mcp-shim.ts Rewrite: bundled bin first, npm exec fallback
apps/desktop/scripts/prepare-sidecar.mjs Remove Bun-compiled chrome-devtools sidecar build
pnpm-lock.yaml Lockfile update

…x requirement

Instead of shelling out to npm exec (which requires npm/npx on PATH),
the Electron main process now resolves the chrome-devtools-mcp binary
directly from node_modules via createRequire. When the user connects
Chrome DevTools MCP in the Electron app, the resolved absolute path is
written to opencode.json as ["node", "<path>"], so OpenCode can spawn
it without any external tool dependency.

Changes:
- Add chrome-devtools-mcp@0.17.0 as a dependency of @openwork/desktop
- Add resolveChromeDevtoolsMcpBin IPC handler in Electron main process
- Add resolveChromeDevtoolsMcpCommand() in mcp.ts for Electron runtime
- Update connections store to resolve bundled bin before writing config
- Rewrite shim to try bundled package first, npm exec as fallback
- Remove Bun-compiled sidecar build from prepare-sidecar.mjs
- Add isolated tests for bin resolution and command building
@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented May 6, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
openwork-app Ready Ready Preview, Comment May 6, 2026 2:01am
openwork-den Ready Ready Preview, Comment May 6, 2026 2:01am
openwork-den-worker-proxy Ready Ready Preview, Comment May 6, 2026 2:01am
openwork-landing Ready Ready Preview, Comment, Open in v0 May 6, 2026 2:01am
openwork-share Ready Ready Preview, Comment May 6, 2026 2:01am

@benjaminshafii benjaminshafii merged commit fe9881b into dev May 6, 2026
11 checks passed
benjaminshafii added a commit that referenced this pull request May 6, 2026
…ixed)

Re-implements both features with fixes for the issues found in #1670/#1671:

Fixes from PR1 (chrome-devtools-mcp bundling):
- Use 'node' string literal instead of process.execPath in the IPC
  handler — process.execPath in Electron is the Electron binary, not
  node, so OpenCode couldn't spawn the command
- Fix args filter to only carry --prefixed flags (not -y from npx)
- Fix mcp.add fallback path to use resolved command from mcpEntryConfig
  instead of the original entry.command

Fixes from PR2 (embedded browser panel):
- Guard against zero-dimension bounds on first render — skip
  browser.show() until the panel has non-zero dimensions, let
  ResizeObserver trigger the actual show
- Defensive try/catch in destroyBrowserView for already-destroyed
  webContents

Verified:
- resolveChromeDevtoolsMcpBin returns ['node', '<abs-path>'] (not
  ['Electron', '<path>'])
- All 17 existing tests pass
- Electron app starts and loads successfully
- CDP targets visible at the remote debugging port
benjaminshafii added a commit that referenced this pull request May 6, 2026
…e-implement

* Revert "feat(desktop): add embedded browser panel with WebContentsView (#1671)"

This reverts commit 610ae1c.

* Revert "feat(desktop): bundle chrome-devtools-mcp as dependency, eliminate npx requirement (#1670)"

This reverts commit fe9881b.

* feat(desktop): bundle chrome-devtools-mcp + embedded browser panel (fixed)

Re-implements both features with fixes for the issues found in #1670/#1671:

Fixes from PR1 (chrome-devtools-mcp bundling):
- Use 'node' string literal instead of process.execPath in the IPC
  handler — process.execPath in Electron is the Electron binary, not
  node, so OpenCode couldn't spawn the command
- Fix args filter to only carry --prefixed flags (not -y from npx)
- Fix mcp.add fallback path to use resolved command from mcpEntryConfig
  instead of the original entry.command

Fixes from PR2 (embedded browser panel):
- Guard against zero-dimension bounds on first render — skip
  browser.show() until the panel has non-zero dimensions, let
  ResizeObserver trigger the actual show
- Defensive try/catch in destroyBrowserView for already-destroyed
  webContents

Verified:
- resolveChromeDevtoolsMcpBin returns ['node', '<abs-path>'] (not
  ['Electron', '<path>'])
- All 17 existing tests pass
- Electron app starts and loads successfully
- CDP targets visible at the remote debugging port

* feat(desktop): auto-inject chrome-devtools MCP into opencode.json on engine start

When the OpenCode engine starts in the Electron desktop app,
ensureOpencodeConfig now automatically adds a chrome-devtools MCP entry
to opencode.json if one doesn't already exist. The command uses the
bundled chrome-devtools-mcp package (['node', '<abs-path>']) so no
npm/npx is needed at runtime.

This mirrors what Tauri's ensure_workspace_files() does in files.rs for
the starter preset, making Control Chrome a zero-setup default for all
Electron workspaces.

* fix(desktop): seed chrome-devtools MCP at workspace creation time

ensureOpencodeConfig in runtime.mjs only runs when the OpenCode engine
starts, which happens asynchronously after the workspace is selected.
New workspaces were left without a chrome-devtools entry because the
engine hadn't started yet.

Fix: call seedChromeDevtoolsMcp(folderPath) directly inside the
workspaceCreate IPC handler so the config is written synchronously
during workspace creation. The runtime.mjs ensureOpencodeConfig
remains as a backup for workspaces created before this change.

Verified: created a workspace via IPC, confirmed opencode.jsonc
contains chrome-devtools with ['node', '<bundled-bin-path>'].

* fix(desktop): migrate legacy npx/bare chrome-devtools commands to bundled node path

Existing workspaces created by Tauri or older Electron versions have
chrome-devtools MCP entries with npx-based or bare-binary commands
like ['npx','-y','chrome-devtools-mcp@latest'] or ['chrome-devtools-mcp'].

Both seedChromeDevtoolsMcp (main.mjs, runs at workspace creation) and
ensureOpencodeConfig (runtime.mjs, runs at engine start) now detect
these legacy commands and migrate them to the bundled ['node', path]
command. User-customised commands (absolute paths, etc.) are preserved.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant