Skip to content

Commit eec74c2

Browse files
committed
feat: option to disable source maps
1 parent d1e73ff commit eec74c2

11 files changed

Lines changed: 141 additions & 1 deletion

File tree

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,11 @@ The Chrome DevTools MCP server supports the following configuration option:
768768
- **Type:** boolean
769769
- **Default:** `true`
770770

771+
- **`--sourceMaps`/ `--source-maps`**
772+
Whether to enable source maps in DevTools. Use --no-source-maps to disable.
773+
- **Type:** boolean
774+
- **Default:** `true`
775+
771776
- **`--screenshotFormat`/ `--screenshot-format`**
772777
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 helps reduce context size in AI conversations. Unset preserves the existing default ("png").
773778
- **Type:** string

src/McpContext.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ interface McpContextOptions {
5757
experimentalIncludeAllPages?: boolean;
5858
// Whether CrUX data should be fetched.
5959
performanceCrux: boolean;
60+
// Whether source maps are enabled in DevTools.
61+
sourceMaps?: boolean;
6062
// The allow list of URL patterns to allow loading resources.
6163
allowList?: string[];
6264
// The block list of URL patterns to block loading resources.
@@ -556,6 +558,7 @@ export class McpContext implements Context {
556558
page.browserContext(),
557559
),
558560
navigationTimeout: this.#options.navigationTimeout,
561+
sourceMaps: this.#options.sourceMaps,
559562
});
560563
this.#mcpPages.set(page, mcpPage);
561564
await mcpPage.init();

src/McpPage.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ export class McpPage implements ContextPage {
138138
#hasNetworkBlockOrAllowlist: boolean;
139139
#locatorClass: typeof Locator;
140140
#navigationTimeout: number;
141+
#sourceMaps: boolean;
141142

142143
constructor(
143144
page: Page,
@@ -147,11 +148,13 @@ export class McpPage implements ContextPage {
147148
locatorClass: typeof Locator;
148149
isolatedContextName?: string;
149150
navigationTimeout?: number;
151+
sourceMaps?: boolean;
150152
},
151153
) {
152154
this.#hasNetworkBlockOrAllowlist = options.hasNetworkBlockOrAllowlist;
153155
this.#locatorClass = options.locatorClass;
154156
this.#navigationTimeout = options.navigationTimeout ?? NAVIGATION_TIMEOUT;
157+
this.#sourceMaps = options.sourceMaps ?? true;
155158
this.pptrPage = page;
156159
this.id = id;
157160
this.isolatedContextName = options.isolatedContextName;
@@ -196,7 +199,9 @@ export class McpPage implements ContextPage {
196199
}
197200
try {
198201
const session = await this.pptrPage.createCDPSession();
199-
this.#devtoolsUniverse = await createTargetUniverse(session);
202+
this.#devtoolsUniverse = await createTargetUniverse(session, {
203+
sourceMaps: this.#sourceMaps,
204+
});
200205
} catch (e) {
201206
logger?.('Failed to initialize DevTools universe', e);
202207
}

src/config/mcp-options.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,12 @@ export const mcpOptions = {
280280
describe:
281281
'Set to false to opt-out of usage statistics collection. Google collects usage data to improve the tool, handled under the Google Privacy Policy (https://policies.google.com/privacy). This is independent from Chrome browser metrics. Disabled if `CHROME_DEVTOOLS_MCP_NO_USAGE_STATISTICS` or `CI` env variables are set.',
282282
},
283+
sourceMaps: {
284+
type: 'boolean',
285+
default: true,
286+
describe:
287+
'Whether to enable source maps in DevTools. Use --no-source-maps to disable.',
288+
},
283289
clearcutEndpoint: {
284290
type: 'string',
285291
hidden: true,
@@ -538,6 +544,7 @@ export function parser(
538544
'$0 --no-performance-crux',
539545
'Disable CrUX (field data) integration in performance tools.',
540546
],
547+
['$0 --no-source-maps', 'Disable source maps in DevTools.'],
541548
[
542549
'$0 --slim',
543550
'Only 3 tools: navigation, JavaScript execution and screenshot',

src/devtools/DevtoolsUtils.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,13 @@ export interface TargetUniverse {
137137
session: CDPSession;
138138
}
139139

140+
export interface CreateTargetUniverseOptions {
141+
sourceMaps?: boolean;
142+
}
143+
140144
export async function createTargetUniverse(
141145
session: CDPSession,
146+
options?: CreateTargetUniverseOptions,
142147
): Promise<TargetUniverse> {
143148
const settingStorage = new DevTools.Common.Settings.SettingsStorage({});
144149
const universe = new DevTools.Foundation.Universe.Universe({
@@ -156,6 +161,17 @@ export async function createTargetUniverse(
156161
supportsEmulation: false,
157162
});
158163

164+
const sourceMaps = options?.sourceMaps ?? true;
165+
const jsSourceMapsSetting = universe.settings.resolve(
166+
DevTools.SDKSettings.jsSourceMapsEnabledSettingDescriptor,
167+
);
168+
jsSourceMapsSetting.set(sourceMaps);
169+
170+
const cssSourceMapsSetting = universe.settings.resolve(
171+
DevTools.SDKSettings.cssSourceMapsEnabledSettingDescriptor,
172+
);
173+
cssSourceMapsSetting.set(sourceMaps);
174+
159175
const setting = universe.settings.resolve(
160176
DevTools.SourceMapManager.lazyLoadingSettingDescriptor,
161177
);

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ export async function createMcpServer(
175175
experimentalDevToolsDebugging: devtools,
176176
experimentalIncludeAllPages: serverArgs.experimentalIncludeAllPages,
177177
performanceCrux: serverArgs.performanceCrux,
178+
sourceMaps: serverArgs.sourceMaps,
178179
allowList: allowlist,
179180
blocklist: blocklist,
180181
allowUnrestrictedPaths: serverArgs.allowUnrestrictedPaths,

src/telemetry/flag_usage_metrics.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,5 +389,13 @@
389389
{
390390
"name": "page_id_routing",
391391
"flagType": "boolean"
392+
},
393+
{
394+
"name": "source_maps_present",
395+
"flagType": "boolean"
396+
},
397+
{
398+
"name": "source_maps",
399+
"flagType": "boolean"
392400
}
393401
]

tests/cli.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ describe('cli args parsing', () => {
3030
memoryDebugging: false,
3131
experimentalStructuredContent: false,
3232
pageIdRouting: true,
33+
sourceMaps: true,
3334
};
3435

3536
it('parses with default args', async () => {
@@ -338,4 +339,18 @@ describe('cli args parsing', () => {
338339
'https://b.com/*',
339340
]);
340341
});
342+
343+
it('parses source-maps flag', async () => {
344+
const defaultParsed = parseArguments(['main.js']);
345+
assert.strictEqual(defaultParsed.sourceMaps, true);
346+
347+
const disabledArgs = parseArguments(['--no-source-maps']);
348+
assert.strictEqual(disabledArgs.sourceMaps, false);
349+
350+
const explicitFalseArgs = parseArguments(['--source-maps=false']);
351+
assert.strictEqual(explicitFalseArgs.sourceMaps, false);
352+
353+
const explicitTrueArgs = parseArguments(['--source-maps=true']);
354+
assert.strictEqual(explicitTrueArgs.sourceMaps, true);
355+
});
341356
});

tests/devtools/DevtoolsUtils.test.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,51 @@ describe('createTargetUniverse', () => {
152152
);
153153
});
154154
});
155+
156+
it('enables source maps by default', async () => {
157+
await withBrowser(async (browser, page) => {
158+
const targetUniverse = await createTargetUniverse(
159+
await page.createCDPSession(),
160+
);
161+
assert.ok(targetUniverse);
162+
163+
assert.strictEqual(
164+
targetUniverse.universe.settings
165+
.resolve(DevTools.SDKSettings.jsSourceMapsEnabledSettingDescriptor)
166+
.get(),
167+
true,
168+
);
169+
assert.strictEqual(
170+
targetUniverse.universe.settings
171+
.resolve(DevTools.SDKSettings.cssSourceMapsEnabledSettingDescriptor)
172+
.get(),
173+
true,
174+
);
175+
});
176+
});
177+
178+
it('disables source maps when sourceMaps is false', async () => {
179+
await withBrowser(async (browser, page) => {
180+
const targetUniverse = await createTargetUniverse(
181+
await page.createCDPSession(),
182+
{sourceMaps: false},
183+
);
184+
assert.ok(targetUniverse);
185+
186+
assert.strictEqual(
187+
targetUniverse.universe.settings
188+
.resolve(DevTools.SDKSettings.jsSourceMapsEnabledSettingDescriptor)
189+
.get(),
190+
false,
191+
);
192+
assert.strictEqual(
193+
targetUniverse.universe.settings
194+
.resolve(DevTools.SDKSettings.cssSourceMapsEnabledSettingDescriptor)
195+
.get(),
196+
false,
197+
);
198+
});
199+
});
155200
});
156201

157202
describe('SymbolizedError', () => {

tests/tools/console.test.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,39 @@ describe('console', () => {
635635
});
636636
});
637637

638+
it('does not apply source maps when sourceMaps is false', async () => {
639+
server.addRoute('/main.min.js', (_req, res) => {
640+
res.setHeader('Content-Type', 'text/javascript');
641+
res.statusCode = 200;
642+
res.end(`function n(){throw new Error("b00m!")}function o(){n()}(function n(){o()})();
643+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJiYXIiLCJFcnJvciIsImZvbyIsIklpZmUiXSwic291cmNlcyI6WyIuL21haW4uanMiXSwic291cmNlc0NvbnRlbnQiOlsiXG5mdW5jdGlvbiBiYXIoKSB7XG4gIHRocm93IG5ldyBFcnJvcignYjAwbSEnKTtcbn1cblxuZnVuY3Rpb24gZm9vKCkge1xuICBiYXIoKTtcbn1cblxuKGZ1bmN0aW9uIElpZmUoKSB7XG4gIGZvbygpO1xufSkoKTtcblxuIl0sIm1hcHBpbmdzIjoiQUFDQSxTQUFTQSxJQUNQLE1BQU0sSUFBSUMsTUFBTSxRQUNsQixDQUVBLFNBQVNDLElBQ1BGLEdBQ0YsRUFFQSxTQUFVRyxJQUNSRCxHQUNELEVBRkQiLCJpZ25vcmVMaXN0IjpbXX0=
644+
`);
645+
});
646+
server.addHtmlRoute(
647+
'/index.html',
648+
`<script src="${server.getRoute('/main.min.js')}"></script>`,
649+
);
650+
651+
await withMcpContext(
652+
async (response, context) => {
653+
const page = context.getSelectedMcpPage();
654+
await page.pptrPage.goto(server.getRoute('/index.html'));
655+
656+
await getConsoleMessage.handler(
657+
{params: {msgid: 1}, page: context.getSelectedMcpPage()},
658+
response,
659+
context,
660+
);
661+
const formattedResponse = await response.handle(context);
662+
const rawText = getTextContent(formattedResponse.content[0]);
663+
664+
assert.ok(rawText.includes('main.min.js'));
665+
assert.ok(!rawText.includes('main.js'));
666+
},
667+
{sourceMaps: false},
668+
);
669+
});
670+
638671
it('ignores frames from ignore listed URLs', async t => {
639672
server.addHtmlRoute(
640673
'/index.html',

0 commit comments

Comments
 (0)