From 9a2569e891ce03dbcdb469eb2c2785164af977f7 Mon Sep 17 00:00:00 2001 From: yiliang114 Date: Thu, 9 Jul 2026 11:07:01 +0800 Subject: [PATCH] fix(cli): keep CDP MCP env reads at serve boundaries --- packages/cli/src/serve/acp-http/index.ts | 2 +- packages/cli/src/serve/cdp-mcp-command.ts | 18 +++++++++++------- packages/cli/src/serve/run-qwen-serve.test.ts | 11 +++++++---- packages/cli/src/serve/run-qwen-serve.ts | 5 ++++- .../cli/src/serve/server/serve-features.ts | 5 ++++- 5 files changed, 27 insertions(+), 14 deletions(-) diff --git a/packages/cli/src/serve/acp-http/index.ts b/packages/cli/src/serve/acp-http/index.ts index a2a452b21b..10f1a249ce 100644 --- a/packages/cli/src/serve/acp-http/index.ts +++ b/packages/cli/src/serve/acp-http/index.ts @@ -102,7 +102,7 @@ function buildChromeDevToolsMcpRuntimeConfig( ) { return undefined; } - const command = resolveCdpMcpCommand(); + const command = resolveCdpMcpCommand(process.env); if (!command) { writeStderrLine( `qwen serve: set ${QWEN_CDP_MCP_COMMAND_ENV} to enable browser automation MCP (no adapter is bundled)`, diff --git a/packages/cli/src/serve/cdp-mcp-command.ts b/packages/cli/src/serve/cdp-mcp-command.ts index 0ce365942e..ac0bc02bdc 100644 --- a/packages/cli/src/serve/cdp-mcp-command.ts +++ b/packages/cli/src/serve/cdp-mcp-command.ts @@ -6,22 +6,26 @@ /** Stdio MCP adapter command used by the optional CDP browser automation bridge. */ export const QWEN_CDP_MCP_COMMAND_ENV = 'QWEN_CDP_MCP_COMMAND'; +const QWEN_SERVE_ACP_HTTP_ENV = 'QWEN_SERVE_ACP_HTTP'; export function resolveCdpMcpCommand( - env: NodeJS.ProcessEnv = process.env, + env: Readonly, ): string | undefined { const command = env[QWEN_CDP_MCP_COMMAND_ENV]?.trim(); return command ? command : undefined; } -export function isBrowserAutomationMcpAvailable(opts: { - cdpTunnelOverWs?: boolean; - token?: string; -}): boolean { +export function isBrowserAutomationMcpAvailable( + opts: { + cdpTunnelOverWs?: boolean; + token?: string; + }, + env: Readonly, +): boolean { return ( opts.cdpTunnelOverWs === true && !opts.token && - process.env['QWEN_SERVE_ACP_HTTP'] !== '0' && - resolveCdpMcpCommand() !== undefined + env[QWEN_SERVE_ACP_HTTP_ENV] !== '0' && + resolveCdpMcpCommand(env) !== undefined ); } diff --git a/packages/cli/src/serve/run-qwen-serve.test.ts b/packages/cli/src/serve/run-qwen-serve.test.ts index 4c56a7070a..eaaed23e55 100644 --- a/packages/cli/src/serve/run-qwen-serve.test.ts +++ b/packages/cli/src/serve/run-qwen-serve.test.ts @@ -1516,10 +1516,13 @@ describe('runQwenServe runtime startup failures', () => { it('does not enable browser automation MCP on bearer-protected endpoints', () => { expect( - isBrowserAutomationMcpAvailable({ - cdpTunnelOverWs: true, - token: 'secret-token', - }), + isBrowserAutomationMcpAvailable( + { + cdpTunnelOverWs: true, + token: 'secret-token', + }, + process.env, + ), ).toBe(false); }); diff --git a/packages/cli/src/serve/run-qwen-serve.ts b/packages/cli/src/serve/run-qwen-serve.ts index d4f6bbf846..362e27f17b 100644 --- a/packages/cli/src/serve/run-qwen-serve.ts +++ b/packages/cli/src/serve/run-qwen-serve.ts @@ -854,7 +854,10 @@ function currentServeFeaturesForRunQwenServe( // so the bootstrap `/capabilities` window doesn't briefly under-report them. clientMcpOverWsEnabled: opts.clientMcpOverWs === true, cdpTunnelOverWsEnabled: opts.cdpTunnelOverWs === true, - browserAutomationMcpAvailable: isBrowserAutomationMcpAvailable(opts), + browserAutomationMcpAvailable: isBrowserAutomationMcpAvailable( + opts, + process.env, + ), }); } diff --git a/packages/cli/src/serve/server/serve-features.ts b/packages/cli/src/serve/server/serve-features.ts index 722f910fcd..09c88e96f7 100644 --- a/packages/cli/src/serve/server/serve-features.ts +++ b/packages/cli/src/serve/server/serve-features.ts @@ -95,7 +95,10 @@ export function createServeFeatures( multiWorkspaceSessionsEnabled, clientMcpOverWsEnabled: opts.clientMcpOverWs === true, cdpTunnelOverWsEnabled: opts.cdpTunnelOverWs === true, - browserAutomationMcpAvailable: isBrowserAutomationMcpAvailable(opts), + browserAutomationMcpAvailable: isBrowserAutomationMcpAvailable( + opts, + process.env, + ), voiceTranscriptionAvailable: getCachedVoiceTranscriptionAvailable(), // Advertised whenever the `/voice/stream` WS endpoint exists (ACP HTTP // on). A configured token no longer suppresses it — the browser carries