Skip to content

Auto-install Playwright Chromium for MCP tools#2942

Open
glendaviesnz wants to merge 6 commits intotrunkfrom
playwright-external-agents
Open

Auto-install Playwright Chromium for MCP tools#2942
glendaviesnz wants to merge 6 commits intotrunkfrom
playwright-external-agents

Conversation

@glendaviesnz
Copy link
Copy Markdown

@glendaviesnz glendaviesnz commented Mar 30, 2026

Fixes: https://linear.app/a8c/issue/STU-1531/make-playwright-browser-dependency-install-more-robust

Summary

I struck a problem with an external MCP client (Codex) could not get the take_screenshot tool to work as it got stuck in a missing chromium loop - I found it very hard to reproduce though, but this PR makes changes to:

  • verify Playwright Chromium is available before Studio MCP launches the shared browser
  • auto-install Playwright Chromium when the managed browser is missing
  • keep explicit executable and channel overrides for environments that need a custom browser path
  • add focused tests for install and override behavior

Problem

The take_screenshot and validate_blocks MCP tools run inside the Studio CLI MCP server and depend on the shared Playwright browser launcher.

When Studio MCP is available but Playwright's managed Chromium browser is missing, those tools can fail even though the site itself is healthy. This is especially relevant for MCP consumers because the screenshot and validation tools need a working browser runtime inside Studio, not just in the calling agent.

What changed

This update adds a repair-first flow for Studio MCP browser startup:

  • if the user has explicitly configured STUDIO_MCP_BROWSER_EXECUTABLE_PATH or STUDIO_MCP_BROWSER_CHANNEL, Studio respects that configuration
  • otherwise, Studio checks whether Playwright's managed Chromium executable exists
  • if it is missing, Studio runs playwright install chromium from the CLI runtime before launching the shared browser
  • after the install attempt, Studio continues with the existing browser launch candidates and returns clearer guidance if launch still fails

This keeps the default MCP path aligned with a Studio-managed Playwright browser while preserving explicit overrides for locked-down or unusual environments.

Why this approach

This makes the MCP screenshot and validation tools more reliable because it:

  • addresses the missing-browser case directly
  • keeps behavior more reproducible across machines
  • preserves an explicit override path when users need to point Studio at a different browser
  • gives clearer diagnostics when repair is not possible

Test instructions

Automated

  • npx vitest run apps/cli/ai/tests/browser-utils.test.ts --config apps/cli/vitest.config.ts
  • npx tsc -p apps/cli/tsconfig.json --noEmit

Manual

  1. Start from a Studio environment where the Playwright Chromium cache is missing.
  2. Run the Studio MCP server and invoke take_screenshot or validate_blocks without any browser override env vars set.
  3. Confirm Studio attempts to install Playwright Chromium and then proceeds with the MCP tool.
  4. Repeat with STUDIO_MCP_BROWSER_CHANNEL=chrome or STUDIO_MCP_BROWSER_EXECUTABLE_PATH=... set and confirm Studio skips the auto-install path and uses the configured override.
  5. Simulate a failed install or offline environment and confirm the MCP error explains that auto-install failed and points the user at the override options.

If you don't have an MCP client handy, you can still smoke test the install path from the repo root:

  1. Run npm run cli:build.
  2. Run node --input-type=module.
  3. Paste the script below into the REPL.
  4. Confirm the first check shows the Playwright-managed executable is missing, the install step downloads Chromium into /tmp/studio-empty-playwright, and the browser launches successfully from that managed path.
import { execFileSync } from 'node:child_process';
import { existsSync, mkdirSync, rmSync } from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';

const browserPath = '/tmp/studio-empty-playwright';

rmSync(browserPath, { recursive: true, force: true });
mkdirSync(browserPath, { recursive: true });
process.env.PLAYWRIGHT_BROWSERS_PATH = browserPath;

const { chromium } = await import('playwright');

const executablePathBefore = chromium.executablePath();
console.log('Before install:', {
  executablePath: executablePathBefore,
  exists: existsSync(executablePathBefore),
});

if (!existsSync(executablePathBefore)) {
  const packageJsonPath = fileURLToPath(import.meta.resolve('playwright/package.json'));
  const cliPath = path.join(path.dirname(packageJsonPath), 'cli.js');

  execFileSync(process.execPath, [cliPath, 'install', 'chromium'], {
    stdio: 'inherit',
    env: {
      ...process.env,
      CI: process.env.CI ?? '1',
    },
  });
}

const executablePathAfter = chromium.executablePath();
console.log('After install:', {
  executablePath: executablePathAfter,
  exists: existsSync(executablePathAfter),
});

const browser = await chromium.launch({
  executablePath: executablePathAfter,
  args: ['--ignore-certificate-errors'],
});

console.log('Launched browser version:', browser.version());
await browser.close();

@glendaviesnz glendaviesnz self-assigned this Mar 30, 2026
@glendaviesnz
Copy link
Copy Markdown
Author

I am still doing some testing on this, so leaving as draft. Came from trying to get a Codex plugin working with Studio MCP

@glendaviesnz glendaviesnz changed the title Make MCP browser launch more flexible Auto-install Playwright Chromium for MCP tools Mar 31, 2026
@glendaviesnz glendaviesnz marked this pull request as ready for review March 31, 2026 22:48
@glendaviesnz glendaviesnz force-pushed the playwright-external-agents branch from 361bcba to 9bdb608 Compare March 31, 2026 22:51
@wpmobilebot
Copy link
Copy Markdown
Collaborator

wpmobilebot commented Mar 31, 2026

📊 Performance Test Results

Comparing 4f65c83 vs trunk

app-size

Metric trunk 4f65c83 Diff Change
App Size (Mac) 1271.46 MB 1271.47 MB +0.01 MB ⚪ 0.0%

site-editor

Metric trunk 4f65c83 Diff Change
load 1600 ms 1614 ms +14 ms ⚪ 0.0%

site-startup

Metric trunk 4f65c83 Diff Change
siteCreation 8157 ms 8170 ms +13 ms ⚪ 0.0%
siteStartup 4845 ms 4830 ms 15 ms ⚪ 0.0%

Results are median values from multiple test runs.

Legend: 🟢 Improvement (faster) | 🔴 Regression (slower) | ⚪ No change (<50ms diff)

@glendaviesnz glendaviesnz requested a review from a team April 8, 2026 03:39
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.

2 participants