Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/cli/src/serve/acp-http/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)`,
Expand Down
18 changes: 11 additions & 7 deletions packages/cli/src/serve/cdp-mcp-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<NodeJS.ProcessEnv>,
): 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<NodeJS.ProcessEnv>,
): 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
);
}
11 changes: 7 additions & 4 deletions packages/cli/src/serve/run-qwen-serve.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});

Expand Down
5 changes: 4 additions & 1 deletion packages/cli/src/serve/run-qwen-serve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
),
});
}

Expand Down
5 changes: 4 additions & 1 deletion packages/cli/src/serve/server/serve-features.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading