Workspace root of / denies every path because the separator is appended twice
Description of the bug
McpContext.validatePath() rejects every path when a configured workspace root is the filesystem root.
The allowed prefix is built as canonicalRoot + path.sep in src/McpContext.ts:
if (
canonicalPath === canonicalRoot ||
canonicalPath.startsWith(canonicalRoot + path.sep)
)For the filesystem root this doubles the separator — / becomes // on POSIX, and C:\ becomes C:\\ on Windows — so no path below the root ever matches, and every file-writing tool fails with:
Access denied: path /Users/me/shots/fullpage.png (canonical: /Users/me/shots/fullpage.png) is not within any of the configured workspace roots.That makes --workspace=/ unusable, and / is exactly the value the --allow-unrestricted-paths deprecation notice recommends:
--allowUnrestrictedPaths ... [deprecated: Use --workspace=/ instead.]Narrower roots such as --workspace=/Users/me work correctly, so this only affects a root that already ends with the separator.
Reproduction
- Start the server from a client that does not negotiate the MCP
rootscapability, with the filesystem root as the workspace root:
node build/src/bin/chrome-devtools-mcp.js --headless --isolated --no-page-id-routing --workspace=/- Call
take_screenshotwith afilePathoutside the temp directory:
{"name": "take_screenshot", "arguments": {"filePath": "/Users/me/shots/fullpage.png"}}- The call is rejected with the error above. Repeating step 2 with
--workspace=/Users/mewrites the screenshot as expected.
Reproduced on 1.9.0 and on main, both through a real server process.
Expectation
--workspace=/ should allow file writes anywhere, as the deprecation notice describes, while narrower roots keep their existing guardrails.
Possible fix
Only append the separator when the canonical root does not already end with one:
const rootPrefix = canonicalRoot.endsWith(path.sep)
? canonicalRoot
: canonicalRoot + path.sep;
if (canonicalPath === canonicalRoot || canonicalPath.startsWith(rootPrefix)) {I have this change plus a regression test in tests/roots.test.ts ready to go and am happy to open a PR if that is welcome.
MCP configuration
{
"mcpServers": {
"chrome-devtools": {
"command": "node",
"args": ["build/src/bin/chrome-devtools-mcp.js", "--headless", "--workspace=/"]
}
}
}Chrome DevTools MCP version
1.9.0
Chrome version
153.0.8010.53
Coding agent version
pi-coding-agent 0.87.1 (where I first hit this); reproduced with a minimal MCP client that omits the roots capability.
Node version
v22.21.1
Operating system
macOS
Extra checklist
- I want to provide a PR to fix this bug
Source: ChromeDevTools/chrome-devtools-mcp