Is your feature request related to a problem? Please describe.
Feature Request: Programmatic Server API for in-process embedding
Context
Gemini CLI integrates chrome-devtools-mcp as a browser subagent. Currently we
spawn it via npx using StdioClientTransport, which works but has drawbacks:
- Cold-start latency (npx download + process spawn)
- stderr output leaking into the host CLI's terminal
- A full process boundary for what could be in-process communication
We'd like to embed chrome-devtools-mcp in-process using the MCP SDK's
InMemoryTransport, but the current architecture makes this impossible.
What blocks in-process use today
-
No programmatic API — main.js creates the McpServer, registers tools,
and connects StdioServerTransport all at the top level. There's no exported
function to create a configured server instance.
-
CLI-coupled configuration — All options (headless, sessionMode,
userDataDir, experimentalVision, etc.) are parsed from process.argv via
yargs in cli.js. There's no way to pass options programmatically.
-
Hardcoded transport — StdioServerTransport is instantiated and
connected at the top of main.js with no way to substitute
InMemoryTransport.
-
Process-level side effects — main.js registers
process.on('unhandledRejection'), sets up Clearcut telemetry, and prints
disclaimers to console.error. These would pollute a host process.
Describe the solution you'd like
What we need
A programmatic entry point, something like:
import { createServer } from "chrome-devtools-mcp";
const server = await createServer({
headless: false,
experimentalVision: true,
userDataDir: "~/.gemini/cli-browser-profile",
usageStatistics: false,
// ... other options currently parsed from CLI args
});
// Connect with any MCP transport
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
await server.connect(serverTransport);
const client = new Client({ name: "my-app" });
await client.connect(clientTransport);
Key requirements
- Options passed as a typed object instead of
process.argv
- No
process.on handlers or console.error side effects
- Transport provided by the caller (not hardcoded to stdio)
- Returns the
McpServer instance for the caller to connect
This would also benefit other embedders (VS Code extensions, Electron apps,
etc.) that want to use chrome-devtools-mcp without spawning a child process.
Describe alternatives you've considered
-
npx at runtime (current) — We spawn npx -y chrome-devtools-mcp@0.17.1 via StdioClientTransport. This works but adds cold-start latency, requires network access, and leaks stderr output into the host terminal. We've mitigated the stderr issue by setting stderr: 'pipe' on the transport.
-
Side-car bundle — Bundle chrome-devtools-mcp as a separate JS file alongside our CLI bundle using esbuild, then spawn with node chrome-devtools-mcp.js instead of npx. This eliminates the network dependency but still requires a child process (~8-9 MB bundle increase). We plan to implement this as a near-term improvement.
Additional context
Drafted with Gemini
Is your feature request related to a problem? Please describe.
Feature Request: Programmatic Server API for in-process embedding
Context
Gemini CLI integrates
chrome-devtools-mcpas a browser subagent. Currently wespawn it via
npxusingStdioClientTransport, which works but has drawbacks:We'd like to embed
chrome-devtools-mcpin-process using the MCP SDK'sInMemoryTransport, but the current architecture makes this impossible.What blocks in-process use today
No programmatic API —
main.jscreates theMcpServer, registers tools,and connects
StdioServerTransportall at the top level. There's no exportedfunction to create a configured server instance.
CLI-coupled configuration — All options (headless, sessionMode,
userDataDir, experimentalVision, etc.) are parsed from
process.argvviayargs in
cli.js. There's no way to pass options programmatically.Hardcoded transport —
StdioServerTransportis instantiated andconnected at the top of
main.jswith no way to substituteInMemoryTransport.Process-level side effects —
main.jsregistersprocess.on('unhandledRejection'), sets up Clearcut telemetry, and printsdisclaimers to
console.error. These would pollute a host process.Describe the solution you'd like
What we need
A programmatic entry point, something like:
Key requirements
process.argvprocess.onhandlers orconsole.errorside effectsMcpServerinstance for the caller to connectThis would also benefit other embedders (VS Code extensions, Electron apps,
etc.) that want to use
chrome-devtools-mcpwithout spawning a child process.Describe alternatives you've considered
npx at runtime (current) — We spawn
npx -y chrome-devtools-mcp@0.17.1via StdioClientTransport. This works but adds cold-start latency, requires network access, and leaks stderr output into the host terminal. We've mitigated the stderr issue by setting stderr: 'pipe' on the transport.Side-car bundle — Bundle chrome-devtools-mcp as a separate JS file alongside our CLI bundle using esbuild, then spawn with node chrome-devtools-mcp.js instead of npx. This eliminates the network dependency but still requires a child process (~8-9 MB bundle increase). We plan to implement this as a near-term improvement.
Additional context
Drafted with Gemini