Dynamic Browser Connection Switching via `switch_browser` Tool
Is your feature request related to a problem? Please describe.
Yes. The chrome-devtools-mcp server currently requires the browser connection URL to be hardcoded at initialization time through command-line arguments (--browserUrl or --wsEndpoint) or via the MCP client's
configuration file. This creates several critical limitations that make the MCP unusable for many real-world development workflows.
The Core Problems:
1. Dynamic Port Allocation
Many browser automation tools use dynamic port allocation where the actual port number isn't known until runtime. Since I don't know the port until after the tool starts, it's impossible to configure the MCP server connection URL ahead of time.
2. Multi-Session Workflow Constraints
When the browser connection is hardcoded at MCP server startup, only one coding session can effectively use the MCP server at a time. To switch between different browser instances, I must:
- Exit the MCP client entirely (claude code CLI)
- Manually edit the JSON configuration file with the MCP command line args
- Restart the client
- Manually resume my previous conversation/session
This workflow is disruptive and time-consuming for what should be a simple operation.
3. Real-World Impact
My specific workflow involves using Claude Code with Cypress tests. When I start a Cypress test session, Chrome DevTools opens on a random port.
Analogies to Illustrate the Limitation:
This is like a phone that requires you to specify who you're going to call before turning it on, and can only call that one person until you restart the phone with a different number configured, or a GPS that requires you to enter your destination before starting your car, and won't let you change destinations mid-trip. If you need to make a detour or change plans, you'd have to pull over, turn off the car, reconfigure the GPS, and restart.
Describe the solution you'd like
A switch_browser tool that accepts a browser connection URL as a parameter, allowing MCP clients to dynamically connect to different browser instances during a session.
Proposed Tool Signature:
{
"name": "switch_browser",
"parameters": {
"url": "http://127.0.0.1:9222", // or ws://... endpoint
"timeout": 10000 // optional, defaults to 10000ms
}
}
Key Capabilities:
- Disconnect from current browser (if any)
- Connect to a new browser instance via HTTP URL or WebSocket endpoint
- Support both http:// URLs (auto-converted to WebSocket) and direct ws:// endpoints
- Configurable timeout to prevent infinite hangs when browsers are unreachable
- Maintain backward compatibility (existing workflows unchanged)
Workflow This Enables:
- Start Claude Code (or any MCP client) with the MCP server in --no-launch mode
- Run my Cypress tests (or any browser-launching tool)
- Use switch_browser to connect to the active Chrome DevTools instance
- Debug, iterate, and switch between different test sessions seamlessly
- No restarts, no config file editing, no session interruption
Benefits:
- Adapts to dynamic port allocation from automation tools
- Enables multi-session debugging workflows
- Provides runtime flexibility analogous to a web browser's address bar
- Makes chrome-devtools-mcp more friendly to tools like Cypress, Playwright, and containerized browsers
Describe alternatives you've considered
Alternative: Static Port Configuration
We could assign predetermined fixed ports to our various browser tools and put corresponding instances of chrome-devtools-mcp in the MCP client config:
{
"chrome-devtools-9222": { "args": ["--browserUrl=http://127.0.0.1:9222"] },
"chrome-devtools-9223": { "args": ["--browserUrl=http://127.0.0.1:9223"] },
"chrome-devtools-9224": { "args": ["--browserUrl=http://127.0.0.1:9224"] }
}
Why this approach does not work:
- Not always possible to control port allocation
- Increases config complexity
- Extra context tokens, extra subprocesses
- Prevents running multiple browser instances simultaneously without config changes
- Still requires restarting the MCP client to add new ports
Additional context
I've already implemented this feature in PR #582
The implementation includes:
- Proper timeout handling with AbortController to prevent infinite hangs
- Support for both HTTP URLs (auto-converted to WebSocket via /json/version endpoint) and direct WebSocket endpoints
- Test coverage
- Full backward compatibility - no breaking changes to existing workflows
- Documentation updates
I'm working on some browser agent workflows for Amp (ampcode.com) and +1 this feature. Super helpful to have more of a human/agent flow.
Thank you, I like this too - I can see the value for this. @OrKoN what are your thoughts on this?
I think it adds some complexity but it is doable. I wonder if there are alternatives:
- If the client can call the tool to switch browser, why cannot it edit the mcp config and restart it? I do not see restart as a big issue because it is what the proposed PR in practice implements. MCP clients (e.g., Cline) auto-restart the MCP server if the config changes.
- Is it possible to configure other tools to use a fixed port?
Let's collect some feedback (at least thumbs ups) from other users? But generally I think we should try adding this, especially, with the connect to existing session notes. Some thoughts on the design:
- not sure if we need the
--no-launchflag, instead I would opt into supporting--browserUrl=dynamicto indicate that the url would be set dynamically. - instead of
switch_browser, I would call itconnect_browserto align with Puppeteer's APIs. We should keep the logic of figuring our how to connect to a URL or ws endpoint to Puppeteer. The current PR has unrelated refactors such as extracting the config.ts, we should not use args beyond main.ts.
If the client can call the tool to switch browser, why cannot it edit the mcp config and restart it? I do not see restart as a big issue because it is what the proposed PR in practice implements. MCP clients (e.g., Cline) auto-restart the MCP server if the config changes.
This relies on the AI agent or the user to update the config whenever needed, and relies on the implementation details of the MCP client, to then prompt to restart the MCP client. To me this is roundabout way to interact with an MCP server and it just pushes the complexity onto the user. My ideal for an MCP server is "set it and forget it" - config is part of installation that you generally don't have to look at again. The connection URL could be an installation detail for some setups, but wouldn't be for others. If it helps - I just tried installing new MCP servers in both Claude Code and Gemini CLI and neither prompted me to restart.
Your recommendations for the feature's behavior and entrypoints all make sense to me.
Oh, and personally I think that --browserUrl=dynamic would be a great default behavior for this MCP server. Opt-in to tightly coupling the MCP to a specific dev tools instance, rather than opt-out.
I think it adds some complexity but it is doable. I wonder if there are alternatives:
- If the client can call the tool to switch browser, why cannot it edit the mcp config and restart it? I do not see restart as a big issue because it is what the proposed PR in practice implements. MCP clients (e.g., Cline) auto-restart the MCP server if the config changes.
- Is it possible to configure other tools to use a fixed port?
Let's collect some feedback (at least thumbs ups) from other users? But generally I think we should try adding this, especially, with the connect to existing session notes. Some thoughts on the design:
- not sure if we need the
--no-launchflag, instead I would opt into supporting--browserUrl=dynamicto indicate that the url would be set dynamically.- instead of
switch_browser, I would call itconnect_browserto align with Puppeteer's APIs. We should keep the logic of figuring our how to connect to a URL or ws endpoint to Puppeteer. The current PR has unrelated refactors such as extracting the config.ts, we should not use args beyond main.ts.
RE connect to existing session feature: Isn't auto-discovery anyway going to solve this use case here?