mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-20 08:42:39 -07:00
fix: suppress MCP server stderr from corrupting alternate buffer UI
Pipe stderr from npx chrome-devtools-mcp instead of inheriting it. The server's banner warnings were leaking into the terminal and corrupting the Ink-based UI in alternate buffer mode. Piped output is forwarded to debugLogger so it remains visible with --debug.
This commit is contained in:
@@ -31,6 +31,7 @@ vi.mock('@modelcontextprotocol/sdk/client/index.js', () => ({
|
||||
vi.mock('@modelcontextprotocol/sdk/client/stdio.js', () => ({
|
||||
StdioClientTransport: vi.fn().mockImplementation(() => ({
|
||||
close: vi.fn().mockResolvedValue(undefined),
|
||||
stderr: null,
|
||||
})),
|
||||
}));
|
||||
|
||||
@@ -144,14 +145,16 @@ describe('BrowserManager', () => {
|
||||
await manager.ensureConnection();
|
||||
|
||||
// Verify StdioClientTransport was created with correct args
|
||||
expect(StdioClientTransport).toHaveBeenCalledWith({
|
||||
command: 'npx',
|
||||
args: expect.arrayContaining([
|
||||
'-y',
|
||||
expect.stringMatching(/chrome-devtools-mcp@/),
|
||||
'--experimental-vision',
|
||||
]),
|
||||
});
|
||||
expect(StdioClientTransport).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
command: 'npx',
|
||||
args: expect.arrayContaining([
|
||||
'-y',
|
||||
expect.stringMatching(/chrome-devtools-mcp@/),
|
||||
'--experimental-vision',
|
||||
]),
|
||||
}),
|
||||
);
|
||||
// Persistent mode should NOT include --isolated or --autoConnect
|
||||
const args = vi.mocked(StdioClientTransport).mock.calls[0]?.[0]
|
||||
?.args as string[];
|
||||
@@ -180,10 +183,12 @@ describe('BrowserManager', () => {
|
||||
const manager = new BrowserManager(headlessConfig);
|
||||
await manager.ensureConnection();
|
||||
|
||||
expect(StdioClientTransport).toHaveBeenCalledWith({
|
||||
command: 'npx',
|
||||
args: expect.arrayContaining(['--headless']),
|
||||
});
|
||||
expect(StdioClientTransport).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
command: 'npx',
|
||||
args: expect.arrayContaining(['--headless']),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('should pass profilePath as --userDataDir when configured', async () => {
|
||||
@@ -203,10 +208,12 @@ describe('BrowserManager', () => {
|
||||
const manager = new BrowserManager(profileConfig);
|
||||
await manager.ensureConnection();
|
||||
|
||||
expect(StdioClientTransport).toHaveBeenCalledWith({
|
||||
command: 'npx',
|
||||
args: expect.arrayContaining(['--userDataDir', '/path/to/profile']),
|
||||
});
|
||||
expect(StdioClientTransport).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
command: 'npx',
|
||||
args: expect.arrayContaining(['--userDataDir', '/path/to/profile']),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('should pass --isolated when sessionMode is isolated', async () => {
|
||||
|
||||
@@ -279,12 +279,25 @@ export class BrowserManager {
|
||||
`Launching chrome-devtools-mcp (${sessionMode} mode) with args: ${mcpArgs.join(' ')}`,
|
||||
);
|
||||
|
||||
// Create stdio transport to npx chrome-devtools-mcp
|
||||
// Create stdio transport to npx chrome-devtools-mcp.
|
||||
// stderr is piped (not inherited) to prevent MCP server banners and
|
||||
// warnings from corrupting the UI in alternate buffer mode.
|
||||
this.mcpTransport = new StdioClientTransport({
|
||||
command: 'npx',
|
||||
args: mcpArgs,
|
||||
stderr: 'pipe',
|
||||
});
|
||||
|
||||
// Forward piped stderr to debugLogger so it's visible with --debug.
|
||||
const stderrStream = this.mcpTransport.stderr;
|
||||
if (stderrStream) {
|
||||
stderrStream.on('data', (chunk: Buffer) => {
|
||||
debugLogger.log(
|
||||
`[chrome-devtools-mcp stderr] ${chunk.toString().trimEnd()}`,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
this.mcpTransport.onclose = () => {
|
||||
debugLogger.error(
|
||||
'chrome-devtools-mcp transport closed unexpectedly. ' +
|
||||
|
||||
Reference in New Issue
Block a user