mirror of
https://github.com/ChromeDevTools/chrome-devtools-mcp.git
synced 2026-09-14 19:45:30 +08:00
feat: option to disable source maps (#2628)
allowing to disable DevTools source maps similar to what DevTools settings allow in the UI.
This commit is contained in:
@@ -180,6 +180,11 @@ The Chrome DevTools MCP server supports the following configuration option:
|
||||
- **Type:** boolean
|
||||
- **Default:** `true`
|
||||
|
||||
- **`--sourceMaps`/ `--source-maps`**
|
||||
Whether to enable source maps in DevTools. Use --no-source-maps to disable.
|
||||
- **Type:** boolean
|
||||
- **Default:** `true`
|
||||
|
||||
- **`--screenshotFormat`/ `--screenshot-format`**
|
||||
Override the default output format used by take_screenshot when the caller does not specify one. JPEG and WebP are ~3-5x smaller than PNG, which reduces transfer and storage size. To reduce context size use --screenshotMaxWidth / --screenshotMaxHeight, since image tokens scale with dimensions rather than encoded bytes. Unset preserves the existing default ("png").
|
||||
- **Type:** string
|
||||
|
||||
@@ -58,6 +58,8 @@ interface McpContextOptions {
|
||||
experimentalIncludeAllPages?: boolean;
|
||||
// Whether CrUX data should be fetched.
|
||||
performanceCrux: boolean;
|
||||
// Whether source maps are enabled in DevTools.
|
||||
sourceMaps?: boolean;
|
||||
// The allow list of URL patterns to allow loading resources.
|
||||
allowList?: string[];
|
||||
// The block list of URL patterns to block loading resources.
|
||||
@@ -567,6 +569,7 @@ export class McpContext implements Context {
|
||||
page.browserContext(),
|
||||
),
|
||||
navigationTimeout: this.#options.navigationTimeout,
|
||||
sourceMaps: this.#options.sourceMaps,
|
||||
});
|
||||
this.#mcpPages.set(page, mcpPage);
|
||||
await mcpPage.init();
|
||||
|
||||
+6
-1
@@ -138,6 +138,7 @@ export class McpPage implements ContextPage {
|
||||
#hasNetworkBlockOrAllowlist: boolean;
|
||||
#locatorClass: typeof Locator;
|
||||
#navigationTimeout: number;
|
||||
#sourceMaps: boolean;
|
||||
|
||||
constructor(
|
||||
page: Page,
|
||||
@@ -147,11 +148,13 @@ export class McpPage implements ContextPage {
|
||||
locatorClass: typeof Locator;
|
||||
isolatedContextName?: string;
|
||||
navigationTimeout?: number;
|
||||
sourceMaps?: boolean;
|
||||
},
|
||||
) {
|
||||
this.#hasNetworkBlockOrAllowlist = options.hasNetworkBlockOrAllowlist;
|
||||
this.#locatorClass = options.locatorClass;
|
||||
this.#navigationTimeout = options.navigationTimeout ?? NAVIGATION_TIMEOUT;
|
||||
this.#sourceMaps = options.sourceMaps ?? true;
|
||||
this.pptrPage = page;
|
||||
this.id = id;
|
||||
this.isolatedContextName = options.isolatedContextName;
|
||||
@@ -196,7 +199,9 @@ export class McpPage implements ContextPage {
|
||||
}
|
||||
try {
|
||||
const session = await this.pptrPage.createCDPSession();
|
||||
this.#devtoolsUniverse = await createTargetUniverse(session);
|
||||
this.#devtoolsUniverse = await createTargetUniverse(session, {
|
||||
sourceMaps: this.#sourceMaps,
|
||||
});
|
||||
} catch (e) {
|
||||
logger?.('Failed to initialize DevTools universe', e);
|
||||
}
|
||||
|
||||
@@ -269,6 +269,12 @@ export const mcpOptions = {
|
||||
describe:
|
||||
'Set to false to disable JavaScript execution. When disabled, evaluation tools (evaluate_script and slim evaluate) are disabled, the initScript parameter in navigate_page is turned off, and navigating to javascript:, data:, or vbscript: URLs is disallowed.',
|
||||
},
|
||||
sourceMaps: {
|
||||
type: 'boolean',
|
||||
default: true,
|
||||
describe:
|
||||
'Whether to enable source maps in DevTools. Use --no-source-maps to disable.',
|
||||
},
|
||||
clearcutEndpoint: {
|
||||
type: 'string',
|
||||
hidden: true,
|
||||
@@ -535,6 +541,7 @@ export function parser(
|
||||
'$0 --no-performance-crux',
|
||||
'Disable CrUX (field data) integration in performance tools.',
|
||||
],
|
||||
['$0 --no-source-maps', 'Disable source maps in DevTools.'],
|
||||
[
|
||||
'$0 --no-javascript-evaluation',
|
||||
'Disable JavaScript execution (disables evaluation tools, initScript in navigate_page, and navigating to javascript:, data:, or vbscript: URLs).',
|
||||
|
||||
@@ -137,8 +137,13 @@ export interface TargetUniverse {
|
||||
session: CDPSession;
|
||||
}
|
||||
|
||||
export interface CreateTargetUniverseOptions {
|
||||
sourceMaps?: boolean;
|
||||
}
|
||||
|
||||
export async function createTargetUniverse(
|
||||
session: CDPSession,
|
||||
options?: CreateTargetUniverseOptions,
|
||||
): Promise<TargetUniverse> {
|
||||
const settingStorage = new DevTools.Common.Settings.SettingsStorage({});
|
||||
const universe = new DevTools.Foundation.Universe.Universe({
|
||||
@@ -156,6 +161,17 @@ export async function createTargetUniverse(
|
||||
supportsEmulation: false,
|
||||
});
|
||||
|
||||
const sourceMaps = options?.sourceMaps ?? true;
|
||||
const jsSourceMapsSetting = universe.settings.resolve(
|
||||
DevTools.SDKSettings.jsSourceMapsEnabledSettingDescriptor,
|
||||
);
|
||||
jsSourceMapsSetting.set(sourceMaps);
|
||||
|
||||
const cssSourceMapsSetting = universe.settings.resolve(
|
||||
DevTools.SDKSettings.cssSourceMapsEnabledSettingDescriptor,
|
||||
);
|
||||
cssSourceMapsSetting.set(sourceMaps);
|
||||
|
||||
const setting = universe.settings.resolve(
|
||||
DevTools.SourceMapManager.lazyLoadingSettingDescriptor,
|
||||
);
|
||||
|
||||
@@ -259,6 +259,7 @@ export class McpServer {
|
||||
experimentalIncludeAllPages:
|
||||
this.#serverArgs.experimentalIncludeAllPages,
|
||||
performanceCrux: this.#serverArgs.performanceCrux,
|
||||
sourceMaps: this.#serverArgs.sourceMaps,
|
||||
allowList: allowlist,
|
||||
blocklist: blocklist,
|
||||
allowUnrestrictedPaths: this.#serverArgs.allowUnrestrictedPaths,
|
||||
|
||||
@@ -437,5 +437,13 @@
|
||||
{
|
||||
"name": "category_memory",
|
||||
"flagType": "boolean"
|
||||
},
|
||||
{
|
||||
"name": "source_maps_present",
|
||||
"flagType": "boolean"
|
||||
},
|
||||
{
|
||||
"name": "source_maps",
|
||||
"flagType": "boolean"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -38,6 +38,7 @@ describe('cli args parsing', () => {
|
||||
memoryDebugging: false,
|
||||
experimentalStructuredContent: false,
|
||||
pageIdRouting: true,
|
||||
sourceMaps: true,
|
||||
};
|
||||
|
||||
it('parses with default args', async () => {
|
||||
@@ -415,4 +416,18 @@ describe('cli args parsing', () => {
|
||||
'https://b.com/*',
|
||||
]);
|
||||
});
|
||||
|
||||
it('parses source-maps flag', async () => {
|
||||
const defaultParsed = parseArguments(['main.js']);
|
||||
assert.strictEqual(defaultParsed.sourceMaps, true);
|
||||
|
||||
const disabledArgs = parseArguments(['--no-source-maps']);
|
||||
assert.strictEqual(disabledArgs.sourceMaps, false);
|
||||
|
||||
const explicitFalseArgs = parseArguments(['--source-maps=false']);
|
||||
assert.strictEqual(explicitFalseArgs.sourceMaps, false);
|
||||
|
||||
const explicitTrueArgs = parseArguments(['--source-maps=true']);
|
||||
assert.strictEqual(explicitTrueArgs.sourceMaps, true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -152,6 +152,51 @@ describe('createTargetUniverse', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('enables source maps by default', async () => {
|
||||
await withBrowser(async (browser, page) => {
|
||||
const targetUniverse = await createTargetUniverse(
|
||||
await page.createCDPSession(),
|
||||
);
|
||||
assert.ok(targetUniverse);
|
||||
|
||||
assert.strictEqual(
|
||||
targetUniverse.universe.settings
|
||||
.resolve(DevTools.SDKSettings.jsSourceMapsEnabledSettingDescriptor)
|
||||
.get(),
|
||||
true,
|
||||
);
|
||||
assert.strictEqual(
|
||||
targetUniverse.universe.settings
|
||||
.resolve(DevTools.SDKSettings.cssSourceMapsEnabledSettingDescriptor)
|
||||
.get(),
|
||||
true,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('disables source maps when sourceMaps is false', async () => {
|
||||
await withBrowser(async (browser, page) => {
|
||||
const targetUniverse = await createTargetUniverse(
|
||||
await page.createCDPSession(),
|
||||
{sourceMaps: false},
|
||||
);
|
||||
assert.ok(targetUniverse);
|
||||
|
||||
assert.strictEqual(
|
||||
targetUniverse.universe.settings
|
||||
.resolve(DevTools.SDKSettings.jsSourceMapsEnabledSettingDescriptor)
|
||||
.get(),
|
||||
false,
|
||||
);
|
||||
assert.strictEqual(
|
||||
targetUniverse.universe.settings
|
||||
.resolve(DevTools.SDKSettings.cssSourceMapsEnabledSettingDescriptor)
|
||||
.get(),
|
||||
false,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('SymbolizedError', () => {
|
||||
|
||||
@@ -643,6 +643,39 @@ describe('console', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('does not apply source maps when sourceMaps is false', async () => {
|
||||
server.addRoute('/main.min.js', (_req, res) => {
|
||||
res.setHeader('Content-Type', 'text/javascript');
|
||||
res.statusCode = 200;
|
||||
res.end(`function n(){throw new Error("b00m!")}function o(){n()}(function n(){o()})();
|
||||
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJiYXIiLCJFcnJvciIsImZvbyIsIklpZmUiXSwic291cmNlcyI6WyIuL21haW4uanMiXSwic291cmNlc0NvbnRlbnQiOlsiXG5mdW5jdGlvbiBiYXIoKSB7XG4gIHRocm93IG5ldyBFcnJvcignYjAwbSEnKTtcbn1cblxuZnVuY3Rpb24gZm9vKCkge1xuICBiYXIoKTtcbn1cblxuKGZ1bmN0aW9uIElpZmUoKSB7XG4gIGZvbygpO1xufSkoKTtcblxuIl0sIm1hcHBpbmdzIjoiQUFDQSxTQUFTQSxJQUNQLE1BQU0sSUFBSUMsTUFBTSxRQUNsQixDQUVBLFNBQVNDLElBQ1BGLEdBQ0YsRUFFQSxTQUFVRyxJQUNSRCxHQUNELEVBRkQiLCJpZ25vcmVMaXN0IjpbXX0=
|
||||
`);
|
||||
});
|
||||
server.addHtmlRoute(
|
||||
'/index.html',
|
||||
`<script src="${server.getRoute('/main.min.js')}"></script>`,
|
||||
);
|
||||
|
||||
await withMcpContext(
|
||||
async (response, context) => {
|
||||
const page = context.getSelectedMcpPage();
|
||||
await page.pptrPage.goto(server.getRoute('/index.html'));
|
||||
|
||||
await getConsoleMessage.handler(
|
||||
{params: {msgid: 1}, page: context.getSelectedMcpPage()},
|
||||
response,
|
||||
context,
|
||||
);
|
||||
const formattedResponse = await response.handle(context);
|
||||
const rawText = getTextContent(formattedResponse.content[0]);
|
||||
|
||||
assert.ok(rawText.includes('main.min.js'));
|
||||
assert.ok(!rawText.includes('main.js'));
|
||||
},
|
||||
{sourceMaps: false},
|
||||
);
|
||||
});
|
||||
|
||||
it('ignores frames from ignore listed URLs', async t => {
|
||||
server.addHtmlRoute(
|
||||
'/index.html',
|
||||
|
||||
@@ -161,6 +161,7 @@ export async function withMcpContext(
|
||||
debug?: boolean;
|
||||
autoOpenDevTools?: boolean;
|
||||
performanceCrux?: boolean;
|
||||
sourceMaps?: boolean;
|
||||
executablePath?: string;
|
||||
args?: string[];
|
||||
blockedUrlPattern?: string[];
|
||||
@@ -183,6 +184,7 @@ export async function withMcpContext(
|
||||
{
|
||||
experimentalDevToolsDebugging: false,
|
||||
performanceCrux: options.performanceCrux ?? true,
|
||||
sourceMaps: options.sourceMaps ?? true,
|
||||
allowList: options.allowedUrlPattern,
|
||||
blocklist: options.blockedUrlPattern,
|
||||
allowUnrestrictedPaths: options.allowUnrestrictedPaths ?? false,
|
||||
|
||||
Reference in New Issue
Block a user