Bug Description
After upgrading from @playwright/mcp@0.0.60 to @playwright/mcp@0.0.70 (via @latest), the MCP server fails with:
Error: ENOENT: no such file or directory, mkdir '/.playwright-mcp'
This happens on macOS where / is a read-only filesystem (SIP/APFS sealed system volume). The navigate, click, and other state-mutating tools fail, while snapshot and run_code work since they don't trigger outputFile().
Root Cause
The outputDir() function was refactored between v0.0.60 and v0.0.70, removing the fallback to os.tmpdir().
v0.0.60 (playwright/lib/mcp/browser/config.js:293) — has proper fallback:
function outputDir(config, clientInfo) {
const rootPath = firstRootPath(clientInfo);
return config.outputDir
?? (rootPath ? path.join(rootPath, ".playwright-mcp") : void 0)
?? path.join(tmpDir(), String(clientInfo.timestamp));
// ↑ safe fallback to tmpdir
}
v0.0.70 (playwright-core/lib/tools/backend/context.js:272) — no fallback:
function outputDir(options) {
if (options.config.outputDir)
return path.resolve(options.config.outputDir);
return path.resolve(options.cwd, ".playwright-mcp");
// ↑ options.cwd is "/" when launched as MCP server without explicit CWD
}
When the MCP server is spawned by an IDE (e.g. Windsurf/VS Code) without an explicit cwd, options.cwd resolves to /, leading to mkdir('/.playwright-mcp') which fails on macOS.
Expected Behavior
outputDir() should fall back to os.tmpdir() or os.homedir() when the CWD-based path is not writable, as it did in v0.0.60.
Environment
- OS: macOS 15 (Sequoia) — APFS sealed system volume,
/ is read-only
- Node: v22.x
- Package:
@playwright/mcp@0.0.70 (latest as of April 2, 2026)
- Working version:
@playwright/mcp@0.0.60
- IDE: Windsurf (Codeium)
- MCP config:
{
"args": ["-y", "@playwright/mcp@latest"],
"command": "npx",
"env": { "HOME": "/Users/username" }
}
Workaround
Pin to @playwright/mcp@0.0.60 in the MCP config.
Suggested Fix
Restore the fallback chain in outputDir():
function outputDir(options) {
if (options.config.outputDir)
return path.resolve(options.config.outputDir);
const cwdPath = path.resolve(options.cwd, options.config.skillMode ? ".playwright-cli" : ".playwright-mcp");
// Fallback if CWD is root or not writable
if (options.cwd === '/' || options.cwd === '')
return path.join(os.tmpdir(), 'playwright-mcp-output');
return cwdPath;
}
Bug Description
After upgrading from
@playwright/mcp@0.0.60to@playwright/mcp@0.0.70(via@latest), the MCP server fails with:This happens on macOS where
/is a read-only filesystem (SIP/APFS sealed system volume). Thenavigate,click, and other state-mutating tools fail, whilesnapshotandrun_codework since they don't triggeroutputFile().Root Cause
The
outputDir()function was refactored between v0.0.60 and v0.0.70, removing the fallback toos.tmpdir().v0.0.60 (
playwright/lib/mcp/browser/config.js:293) — has proper fallback:v0.0.70 (
playwright-core/lib/tools/backend/context.js:272) — no fallback:When the MCP server is spawned by an IDE (e.g. Windsurf/VS Code) without an explicit
cwd,options.cwdresolves to/, leading tomkdir('/.playwright-mcp')which fails on macOS.Expected Behavior
outputDir()should fall back toos.tmpdir()oros.homedir()when the CWD-based path is not writable, as it did in v0.0.60.Environment
/is read-only@playwright/mcp@0.0.70(latest as of April 2, 2026)@playwright/mcp@0.0.60{ "args": ["-y", "@playwright/mcp@latest"], "command": "npx", "env": { "HOME": "/Users/username" } }Workaround
Pin to
@playwright/mcp@0.0.60in the MCP config.Suggested Fix
Restore the fallback chain in
outputDir():