Skip to content

Commit 80b7b4f

Browse files
Merge branch 'main' into extensions-skill
2 parents 71ac52b + aa33bff commit 80b7b4f

8 files changed

Lines changed: 103 additions & 27 deletions

File tree

package-lock.json

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
"@rollup/plugin-json": "^6.1.0",
5555
"@rollup/plugin-node-resolve": "^16.0.3",
5656
"@stylistic/eslint-plugin": "^5.4.0",
57+
"@toon-format/toon": "^2.2.0",
5758
"@types/debug": "^4.1.12",
5859
"@types/filesystem": "^0.0.36",
5960
"@types/node": "^25.0.0",

src/McpResponse.ts

Lines changed: 47 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import type {McpContext} from './McpContext.js';
1717
import type {McpPage} from './McpPage.js';
1818
import {UncaughtError} from './PageCollector.js';
1919
import {TextSnapshot} from './TextSnapshot.js';
20-
import {DevTools, type Protocol} from './third_party/index.js';
20+
import {DevTools, toonEncode, type Protocol} from './third_party/index.js';
2121
import type {
2222
ConsoleMessage,
2323
ImageContent,
@@ -498,6 +498,7 @@ export class McpResponse implements Response {
498498
async handle(
499499
toolName: string,
500500
context: McpContext,
501+
useToon = false,
501502
): Promise<{
502503
content: Array<TextContent | ImageContent>;
503504
structuredContent: object;
@@ -726,20 +727,25 @@ export class McpResponse implements Response {
726727
}
727728
}
728729

729-
return this.format(toolName, context, {
730-
detailedConsoleMessage,
731-
consoleMessages,
732-
snapshot,
733-
detailedNetworkRequest,
734-
networkRequests,
735-
traceInsight: this.#attachedTraceInsight,
736-
traceSummary: this.#attachedTraceSummary,
737-
extensions,
738-
lighthouseResult: this.#attachedLighthouseResult,
739-
thirdPartyDeveloperTools,
740-
webmcpTools,
741-
errorMessage: this.#error?.message,
742-
});
730+
return this.format(
731+
toolName,
732+
context,
733+
{
734+
detailedConsoleMessage,
735+
consoleMessages,
736+
snapshot,
737+
detailedNetworkRequest,
738+
networkRequests,
739+
traceInsight: this.#attachedTraceInsight,
740+
traceSummary: this.#attachedTraceSummary,
741+
extensions,
742+
lighthouseResult: this.#attachedLighthouseResult,
743+
thirdPartyDeveloperTools,
744+
webmcpTools,
745+
errorMessage: this.#error?.message,
746+
},
747+
useToon,
748+
);
743749
}
744750

745751
format(
@@ -759,6 +765,7 @@ export class McpResponse implements Response {
759765
webmcpTools?: WebMCPTool[];
760766
errorMessage?: string;
761767
},
768+
useToon: boolean,
762769
): {content: Array<TextContent | ImageContent>; structuredContent: object} {
763770
const structuredContent: {
764771
snapshot?: object;
@@ -1006,9 +1013,13 @@ Call ${handleDialog.name} to handle it before continuing.`);
10061013
response.push(`Saved snapshot to ${data.snapshot}.`);
10071014
structuredContent.snapshotFilePath = data.snapshot;
10081015
} else {
1009-
response.push('## Latest page snapshot');
1010-
response.push(data.snapshot.toString());
10111016
structuredContent.snapshot = data.snapshot.toJSON();
1017+
response.push('## Latest page snapshot');
1018+
response.push(
1019+
useToon
1020+
? toonEncode(structuredContent.snapshot)
1021+
: data.snapshot.toString(),
1022+
);
10121023
}
10131024
}
10141025

@@ -1041,8 +1052,12 @@ Call ${handleDialog.name} to handle it before continuing.`);
10411052
const paginatedRecord = Object.fromEntries(paginationData.items);
10421053
const formatter = new HeapSnapshotFormatter(paginatedRecord);
10431054

1044-
response.push(formatter.toString());
10451055
structuredContent.heapSnapshotData = formatter.toJSON();
1056+
response.push(
1057+
useToon
1058+
? toonEncode(structuredContent.heapSnapshotData)
1059+
: formatter.toString(),
1060+
);
10461061
}
10471062
const nodes = this.#heapSnapshotOptions.nodes;
10481063
if (nodes) {
@@ -1154,11 +1169,14 @@ Call ${handleDialog.name} to handle it before continuing.`);
11541169
structuredContent.pagination = paginationData.pagination;
11551170
response.push(...paginationData.info);
11561171
if (data.networkRequests) {
1157-
structuredContent.networkRequests = [];
1158-
for (const formatter of paginationData.items) {
1159-
response.push(formatter.toString());
1160-
structuredContent.networkRequests.push(formatter.toJSON());
1161-
}
1172+
structuredContent.networkRequests = paginationData.items.map(i =>
1173+
i.toJSON(),
1174+
);
1175+
response.push(
1176+
...(useToon
1177+
? [toonEncode(structuredContent.networkRequests)]
1178+
: paginationData.items.map(i => i.toString())),
1179+
);
11621180
}
11631181
} else {
11641182
response.push('No requests found.');
@@ -1176,11 +1194,15 @@ Call ${handleDialog.name} to handle it before continuing.`);
11761194
this.#consoleDataOptions.pagination,
11771195
);
11781196
structuredContent.pagination = paginationData.pagination;
1179-
response.push(...paginationData.info);
1180-
response.push(...paginationData.items.map(item => item.toString()));
11811197
structuredContent.consoleMessages = paginationData.items.map(item =>
11821198
item.toJSON(),
11831199
);
1200+
response.push(...paginationData.info);
1201+
if (useToon) {
1202+
response.push(toonEncode(structuredContent.consoleMessages));
1203+
} else {
1204+
response.push(...paginationData.items.map(item => item.toString()));
1205+
}
11841206
} else {
11851207
response.push('<no console messages found>');
11861208
}

src/ToolHandler.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,7 @@ export class ToolHandler {
262262
const {content, structuredContent} = await response.handle(
263263
this.tool.name,
264264
context,
265+
this.serverArgs.experimentalToonFormat ?? false,
265266
);
266267
const result: CallToolResult & {
267268
structuredContent?: Record<string, unknown>;

src/bin/chrome-devtools-mcp-cli-options.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,12 @@ export const cliOptions = {
170170
type: 'boolean',
171171
describe: 'Whether to output structured formatted content.',
172172
},
173+
experimentalToonFormat: {
174+
type: 'boolean',
175+
describe:
176+
'Whether to format structured data in text response using Token-Oriented Object Notation. Defaults to false which represents the embedded content as formatted JSON instead.',
177+
hidden: true,
178+
},
173179
experimentalIncludeAllPages: {
174180
type: 'boolean',
175181
describe:
@@ -306,7 +312,7 @@ export function parseArguments(
306312
const yargsInstance = yargs(hideBin(argv))
307313
.scriptName('npx chrome-devtools-mcp@latest')
308314
.options(cliOptions)
309-
.check(args => {
315+
.middleware(args => {
310316
// We can't set default in the options else
311317
// Yargs will complain
312318
if (
@@ -323,7 +329,6 @@ export function parseArguments(
323329
);
324330
args.usageStatistics = false;
325331
}
326-
return true;
327332
})
328333
.example([
329334
[

src/telemetry/flag_usage_metrics.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,5 +313,13 @@
313313
{
314314
"name": "allowed_url_pattern_present",
315315
"flagType": "boolean"
316+
},
317+
{
318+
"name": "experimental_toon_format_present",
319+
"flagType": "boolean"
320+
},
321+
{
322+
"name": "experimental_toon_format",
323+
"flagType": "boolean"
316324
}
317325
]

src/third_party/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ export {
5757
Browser as BrowserEnum,
5858
type ChromeReleaseChannel as BrowsersChromeReleaseChannel,
5959
} from '@puppeteer/browsers';
60+
export {encode as toonEncode} from '@toon-format/toon';
6061

6162
import {
6263
snapshot as snapshotImpl,

tests/third_party_notices.test.js.snapshot

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -907,6 +907,36 @@ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
907907
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
908908

909909

910+
-------------------- DEPENDENCY DIVIDER --------------------
911+
912+
Name: @toon-format/toon
913+
URL: https://toonformat.dev
914+
Version: <VERSION>
915+
License: MIT
916+
917+
MIT License
918+
919+
Copyright (c) 2025-PRESENT Johann Schopplich
920+
921+
Permission is hereby granted, free of charge, to any person obtaining a copy
922+
of this software and associated documentation files (the "Software"), to deal
923+
in the Software without restriction, including without limitation the rights
924+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
925+
copies of the Software, and to permit persons to whom the Software is
926+
furnished to do so, subject to the following conditions:
927+
928+
The above copyright notice and this permission notice shall be included in all
929+
copies or substantial portions of the Software.
930+
931+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
932+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
933+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
934+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
935+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
936+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
937+
SOFTWARE.
938+
939+
910940
-------------------- DEPENDENCY DIVIDER --------------------
911941

912942
Name: chrome-devtools-frontend

0 commit comments

Comments
 (0)