Sharing Chrome DevTools MCP Across Claude Sessions
- •Multiple Claude Code sessions collide when chrome-devtools-mcp reuses one Chrome profile directory
- •Wrapper assigns persistent per-session profiles using git root, tty fallback, and pid fallback
- •Nguyen later recommends one debuggable Chrome shared through --browserUrl for subagent workflows
Dale Nguyen published a September 11 guide explaining why multiple Claude Code sessions can break when they use chrome-devtools-mcp to control Chrome from the same repository. The failure appears when a second terminal tries to launch a browser with the same profile directory and receives an error saying the browser is already running for a path such as /Users/you/.cache/chrome-devtools-mcp/profiles/my-repo-85156b57 and that --isolated should be used for multiple browser instances.
The immediate cause is a collision between 3 facts: Chrome refuses 2 instances on one --user-data-dir, every Claude Code session starts its own MCP server, and the default profile path can be the same for both sessions. Nguyen’s first wrapper sets a per-session --userDataDir for chrome-devtools-mcp, deriving a stable profile key from the git root and an 8-character shasum hash, then falling back to a terminal tty suffix or pid suffix only when the profile is actually busy. The wrapper prints diagnostics to stderr because stdout carries the MCP protocol stream.
Nguyen says the tempting --isolated flag works but discards the profile on exit, so every run starts logged out. His preferred first fix is “partitioned and persistent”: one Chrome profile per session, stored under $HOME/.cache/chrome-devtools-mcp/profiles, so cookies survive restarts while concurrent terminals avoid Chrome’s SingletonLock.
Installation uses chmod +x on ~/.claude/mcp-wrappers/chrome-devtools.sh, removes any existing chrome-devtools MCP entry, and adds the wrapper with claude mcp add chrome-devtools --scope user. The article warns that every running Claude session must be restarted because an MCP server reads its command arguments only once at startup.
Nguyen identifies 2 silent bugs in the wrapper. The first is keying only on the directory: git root and branch are too coarse when 2 terminals run in the same checkout, so the key must be at least as fine-grained as the unit that can run concurrently. The tty works for terminal-scoped fallback, but Claude runs shells detached, so the wrapper walks up to 8 process ancestors to find the first real tty instead of relying on $$ or stdin.
The second bug is an in-use check that matches the wrong command-line flag. Chrome uses --user-data-dir, while chrome-devtools-mcp uses --userDataDir, and the MCP server may hold the profile before Chrome launches on the first browser tool call. Nguyen’s final pgrep pattern matches both dash-case and camelCase spellings and treats either whitespace or end-of-string as the boundary, preventing a base profile from matching a suffixed sibling while still detecting a last-argument holder.
Nguyen tested 3 simultaneous MCP servers in one repo. With 3 sessions in the same tty and a staggered 3s start, 3 of 3 browsers worked; with 3 distinct ttys starting at the same instant, 3 of 3 worked; with 3 sessions in the same tty starting at the same instant, only 1 of 3 worked. He attributes the failure to check-then-act timing and says scripts launching 10 sessions in a loop should set CDP_PROFILE explicitly per session.
After a week using the isolation wrapper with subagents, Nguyen changed the recommended default. Three general-purpose subagents launched 3 MCP processes, 3 Chromes, 3 fresh profiles, and 3 login pages, because subagents do not share the parent session’s MCP server. Page-scoped tools use pageId routing, enabled by default, so agents sharing a browser should operate only on tabs they opened themselves.
Nguyen’s final approach is one Chrome shared by many clients through the Chrome DevTools Protocol (browser debugging interface). chrome-devtools-mcp supports --browserUrl for attaching to a running debuggable Chrome instance such as http://127.0.0.1:9222. The later wrapper launches one Chrome with --remote-debugging-port, keeps a shared profile, lets every session and subagent attach to it, and preserves the isolation logic as a fallback rather than making each agent start logged out.