mirror of
https://github.com/ChromeDevTools/chrome-devtools-mcp.git
synced 2026-09-14 19:45:30 +08:00
fix: warn on unknown CLI args (#2577)
This commit is contained in:
+5
-5
@@ -4,7 +4,7 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import type {parseArguments} from './bin/chrome-devtools-mcp-cli-options.js';
|
||||
import type {ParsedArguments} from './bin/chrome-devtools-mcp-cli-options.js';
|
||||
import type {McpContext} from './McpContext.js';
|
||||
import type {McpPage} from './McpPage.js';
|
||||
import type {DataFormat} from './McpResponse.js';
|
||||
@@ -46,7 +46,7 @@ function buildDisabledMessage(
|
||||
|
||||
function getCategoryStatus(
|
||||
category: ToolCategory,
|
||||
serverArgs: ReturnType<typeof parseArguments>,
|
||||
serverArgs: ParsedArguments,
|
||||
): {categoryFlag?: string; disabled: boolean} {
|
||||
const categoryFlag = buildFlag(category);
|
||||
|
||||
@@ -70,7 +70,7 @@ function getCategoryStatus(
|
||||
|
||||
function getConditionStatus(
|
||||
condition: string,
|
||||
serverArgs: ReturnType<typeof parseArguments>,
|
||||
serverArgs: ParsedArguments,
|
||||
): {conditionFlag?: string; disabled: boolean} {
|
||||
if (condition && !serverArgs[condition]) {
|
||||
return {conditionFlag: condition, disabled: true};
|
||||
@@ -81,7 +81,7 @@ function getConditionStatus(
|
||||
|
||||
function getToolStatusInfo(
|
||||
tool: ToolDefinition | DefinedPageTool,
|
||||
serverArgs: ReturnType<typeof parseArguments>,
|
||||
serverArgs: ParsedArguments,
|
||||
): {disabled: boolean; reason?: string} {
|
||||
const category = tool.annotations.category;
|
||||
const categoryCheck = getCategoryStatus(category, serverArgs);
|
||||
@@ -224,7 +224,7 @@ export class ToolHandler {
|
||||
|
||||
constructor(
|
||||
private readonly tool: ToolDefinition | DefinedPageTool,
|
||||
private readonly serverArgs: ReturnType<typeof parseArguments>,
|
||||
private readonly serverArgs: ParsedArguments,
|
||||
private readonly getContext: () => Promise<McpContext>,
|
||||
private readonly toolMutex: Mutex,
|
||||
) {
|
||||
|
||||
@@ -384,23 +384,14 @@ export function parser(
|
||||
argv = process.argv,
|
||||
env = process.env,
|
||||
) {
|
||||
// Preserve yargs' mixed camel/kebab-case expansion under strict validation.
|
||||
const kebabCaseAliases: Record<string, string> = {};
|
||||
for (const option of Object.keys(cliOptions)) {
|
||||
const alias = option.replace(
|
||||
/[A-Z]/g,
|
||||
letter => `-${letter.toLowerCase()}`,
|
||||
);
|
||||
if (alias !== option) {
|
||||
kebabCaseAliases[option] = alias;
|
||||
}
|
||||
}
|
||||
|
||||
const yargsInstance = yargs(hideBin(argv))
|
||||
.scriptName('npx chrome-devtools-mcp@latest')
|
||||
.parserConfiguration({
|
||||
'strip-aliased': true,
|
||||
'strip-dashed': true,
|
||||
})
|
||||
.options(cliOptions)
|
||||
.alias(kebabCaseAliases)
|
||||
.strictOptions()
|
||||
.showHelpOnFail(false, 'Specify --help for available options')
|
||||
.middleware(args => {
|
||||
// We can't set default in the options else
|
||||
// Yargs will complain
|
||||
@@ -418,6 +409,23 @@ export function parser(
|
||||
);
|
||||
args.usageStatistics = false;
|
||||
}
|
||||
|
||||
const cliOptionsAllowedArgs = [
|
||||
...Object.keys(cliOptions),
|
||||
// Yargs populated with positional args
|
||||
'_',
|
||||
'$0',
|
||||
];
|
||||
|
||||
const unknownArgs = Object.keys(args).filter(
|
||||
arg => !cliOptionsAllowedArgs.includes(arg),
|
||||
);
|
||||
|
||||
if (unknownArgs.length > 0) {
|
||||
console.error(
|
||||
`Unknown arguments: ${unknownArgs.map(arg => `--${arg}`)}`,
|
||||
);
|
||||
}
|
||||
})
|
||||
.example([
|
||||
[
|
||||
|
||||
+3
-3
@@ -6,7 +6,7 @@
|
||||
|
||||
import type fs from 'node:fs';
|
||||
|
||||
import type {parseArguments} from './bin/chrome-devtools-mcp-cli-options.js';
|
||||
import {type ParsedArguments} from './bin/chrome-devtools-mcp-cli-options.js';
|
||||
import type {Channel} from './browser.js';
|
||||
import {ensureBrowserConnected, ensureBrowserLaunched} from './browser.js';
|
||||
import {loadIssueDescriptions} from './devtools/issueDescriptions.js';
|
||||
@@ -41,7 +41,7 @@ export {buildFlag} from './ToolHandler.js';
|
||||
const ROOTS_REQUEST_TIMEOUT = 5_000;
|
||||
|
||||
export async function createMcpServer(
|
||||
serverArgs: ReturnType<typeof parseArguments>,
|
||||
serverArgs: ParsedArguments,
|
||||
options: {
|
||||
logFile?: fs.WriteStream;
|
||||
},
|
||||
@@ -230,7 +230,7 @@ export async function createMcpServer(
|
||||
return {server};
|
||||
}
|
||||
|
||||
export const logDisclaimers = (args: ReturnType<typeof parseArguments>) => {
|
||||
export const logDisclaimers = (args: ParsedArguments) => {
|
||||
console.error(
|
||||
`chrome-devtools-mcp exposes content of the browser instance to the MCP clients allowing them to inspect,
|
||||
debug, and modify any data in the browser or DevTools.
|
||||
|
||||
+11
-32
@@ -17,25 +17,15 @@ function parseArguments(argv: string[], env: NodeJS.ProcessEnv = {}) {
|
||||
|
||||
describe('cli args parsing', () => {
|
||||
const defaultArgs = {
|
||||
'category-emulation': true,
|
||||
categoryEmulation: true,
|
||||
'category-performance': true,
|
||||
categoryPerformance: true,
|
||||
'category-network': true,
|
||||
categoryNetwork: true,
|
||||
'category-extensions': false,
|
||||
categoryExtensions: false,
|
||||
'category-experimental-third-party': false,
|
||||
categoryExperimentalThirdParty: false,
|
||||
'auto-connect': undefined,
|
||||
autoConnect: undefined,
|
||||
'performance-crux': true,
|
||||
performanceCrux: true,
|
||||
'usage-statistics': true,
|
||||
usageStatistics: true,
|
||||
'redact-network-headers': false,
|
||||
redactNetworkHeaders: false,
|
||||
'allow-unrestricted-paths': false,
|
||||
allowUnrestrictedPaths: false,
|
||||
};
|
||||
|
||||
@@ -57,17 +47,22 @@ describe('cli args parsing', () => {
|
||||
_: [],
|
||||
headless: false,
|
||||
$0: 'npx chrome-devtools-mcp@latest',
|
||||
'browser-url': 'http://localhost:3000',
|
||||
browserUrl: 'http://localhost:3000',
|
||||
u: 'http://localhost:3000',
|
||||
});
|
||||
});
|
||||
|
||||
it('rejects unknown options', async () => {
|
||||
assert.throws(
|
||||
() => parseArguments(['--browserURL', 'http://localhost:3000']),
|
||||
/Unknown argument: browserURL/,
|
||||
);
|
||||
let output = '';
|
||||
const originalError = console.error;
|
||||
console.error = (msg: string) => {
|
||||
output += msg;
|
||||
};
|
||||
try {
|
||||
parseArguments(['--browserURL', 'http://localhost:3000']);
|
||||
assert.match(output, /Unknown arguments: --browserURL/);
|
||||
} finally {
|
||||
console.error = originalError;
|
||||
}
|
||||
});
|
||||
|
||||
it('parses mixed-form option names', async () => {
|
||||
@@ -84,7 +79,6 @@ describe('cli args parsing', () => {
|
||||
headless: false,
|
||||
$0: 'npx chrome-devtools-mcp@latest',
|
||||
channel: 'stable',
|
||||
'user-data-dir': '/tmp/chrome-profile',
|
||||
userDataDir: '/tmp/chrome-profile',
|
||||
});
|
||||
});
|
||||
@@ -96,9 +90,7 @@ describe('cli args parsing', () => {
|
||||
_: [],
|
||||
headless: false,
|
||||
$0: 'npx chrome-devtools-mcp@latest',
|
||||
'browser-url': undefined,
|
||||
browserUrl: undefined,
|
||||
u: undefined,
|
||||
channel: 'stable',
|
||||
});
|
||||
});
|
||||
@@ -110,8 +102,6 @@ describe('cli args parsing', () => {
|
||||
_: [],
|
||||
headless: false,
|
||||
$0: 'npx chrome-devtools-mcp@latest',
|
||||
'executable-path': '/tmp/test 123/chrome',
|
||||
e: '/tmp/test 123/chrome',
|
||||
executablePath: '/tmp/test 123/chrome',
|
||||
});
|
||||
});
|
||||
@@ -142,7 +132,6 @@ describe('cli args parsing', () => {
|
||||
headless: false,
|
||||
$0: 'npx chrome-devtools-mcp@latest',
|
||||
channel: 'stable',
|
||||
'chrome-arg': ['--no-sandbox', '--disable-setuid-sandbox'],
|
||||
chromeArg: ['--no-sandbox', '--disable-setuid-sandbox'],
|
||||
});
|
||||
});
|
||||
@@ -158,10 +147,6 @@ describe('cli args parsing', () => {
|
||||
headless: false,
|
||||
$0: 'npx chrome-devtools-mcp@latest',
|
||||
channel: 'stable',
|
||||
'ignore-default-chrome-arg': [
|
||||
'--disable-extensions',
|
||||
'--disable-cancel-all-touches',
|
||||
],
|
||||
ignoreDefaultChromeArg: [
|
||||
'--disable-extensions',
|
||||
'--disable-cancel-all-touches',
|
||||
@@ -179,9 +164,7 @@ describe('cli args parsing', () => {
|
||||
_: [],
|
||||
headless: false,
|
||||
$0: 'npx chrome-devtools-mcp@latest',
|
||||
'ws-endpoint': 'ws://127.0.0.1:9222/devtools/browser/abc123',
|
||||
wsEndpoint: 'ws://127.0.0.1:9222/devtools/browser/abc123',
|
||||
w: 'ws://127.0.0.1:9222/devtools/browser/abc123',
|
||||
});
|
||||
});
|
||||
|
||||
@@ -195,9 +178,7 @@ describe('cli args parsing', () => {
|
||||
_: [],
|
||||
headless: false,
|
||||
$0: 'npx chrome-devtools-mcp@latest',
|
||||
'ws-endpoint': 'wss://example.com:9222/devtools/browser/abc123',
|
||||
wsEndpoint: 'wss://example.com:9222/devtools/browser/abc123',
|
||||
w: 'wss://example.com:9222/devtools/browser/abc123',
|
||||
});
|
||||
});
|
||||
|
||||
@@ -222,7 +203,6 @@ describe('cli args parsing', () => {
|
||||
headless: false,
|
||||
$0: 'npx chrome-devtools-mcp@latest',
|
||||
channel: 'stable',
|
||||
'category-emulation': false,
|
||||
categoryEmulation: false,
|
||||
});
|
||||
});
|
||||
@@ -234,7 +214,6 @@ describe('cli args parsing', () => {
|
||||
headless: false,
|
||||
$0: 'npx chrome-devtools-mcp@latest',
|
||||
channel: 'stable',
|
||||
'auto-connect': true,
|
||||
autoConnect: true,
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user