豆豆友情提示:这是一个非官方 GitHub 代理镜像,主要用于网络测试或访问加速。请勿在此进行登录、注册或处理任何敏感信息。进行这些操作请务必访问官方网站 github.com。 Raw 内容也通过此代理提供。
Skip to content

Commit 1e0ee69

Browse files
nattalliusNatallia Harshunova
andauthored
chore: Implement install_extension command (#764)
Co-authored-by: Natallia Harshunova <nharshunova@chromium.org>
1 parent 59bdee0 commit 1e0ee69

File tree

15 files changed

+136
-0
lines changed

15 files changed

+136
-0
lines changed

scripts/generate-docs.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,9 +278,15 @@ async function generateToolDocumentation(): Promise<void> {
278278
// Convert ToolDefinitions to ToolWithAnnotations
279279
const toolsWithAnnotations: ToolWithAnnotations[] = tools
280280
.filter(tool => {
281+
// Filter out extension tools
282+
if (tool.name === 'install_extension') {
283+
return false;
284+
}
285+
281286
if (!tool.annotations.conditions) {
282287
return true;
283288
}
289+
284290
// Only include unconditional tools.
285291
return tool.annotations.conditions.length === 0;
286292
})

src/McpContext.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -690,4 +690,8 @@ export class McpContext implements Context {
690690
});
691691
await this.#networkCollector.init(await this.browser.pages());
692692
}
693+
694+
async installExtension(path: string): Promise<string> {
695+
return this.browser.installExtension(path);
696+
}
693697
}

src/browser.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ interface McpLaunchOptions {
145145
chromeArgs?: string[];
146146
ignoreDefaultChromeArgs?: string[];
147147
devtools: boolean;
148+
enableExtensions?: boolean;
148149
}
149150

150151
export async function launch(options: McpLaunchOptions): Promise<Browser> {
@@ -201,6 +202,7 @@ export async function launch(options: McpLaunchOptions): Promise<Browser> {
201202
ignoreDefaultArgs: ignoreDefaultArgs,
202203
acceptInsecureCerts: options.acceptInsecureCerts,
203204
handleDevToolsAsPage: true,
205+
enableExtensions: options.enableExtensions,
204206
});
205207
if (options.logFile) {
206208
// FIXME: we are probably subscribing too late to catch startup logs. We

src/cli.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,12 @@ export const cliOptions = {
198198
default: true,
199199
describe: 'Set to false to exclude tools related to network.',
200200
},
201+
categoryExtensions: {
202+
type: 'boolean',
203+
default: false,
204+
hidden: true,
205+
describe: 'Set to false to exclude tools related to extensions.',
206+
},
201207
usageStatistics: {
202208
type: 'boolean',
203209
// Marked as `false` until the feature is ready to be enabled by default.

src/main.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ async function getContext(): Promise<McpContext> {
9191
ignoreDefaultChromeArgs,
9292
acceptInsecureCerts: args.acceptInsecureCerts,
9393
devtools,
94+
enableExtensions: args.categoryExtensions,
9495
});
9596

9697
if (context?.browser !== browser) {
@@ -139,6 +140,12 @@ function registerTool(tool: ToolDefinition): void {
139140
) {
140141
return;
141142
}
143+
if (
144+
tool.annotations.category === ToolCategory.EXTENSIONS &&
145+
args.categoryExtensions === false
146+
) {
147+
return;
148+
}
142149
if (
143150
tool.annotations.conditions?.includes('computerVision') &&
144151
!args.experimentalVision

src/tools/ToolDefinition.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ export type Context = Readonly<{
121121
* Returns a reqid for a cdpRequestId.
122122
*/
123123
resolveCdpElementId(cdpBackendNodeId: number): string | undefined;
124+
installExtension(path: string): Promise<string>;
124125
}>;
125126

126127
export function defineTool<Schema extends zod.ZodRawShape>(

src/tools/categories.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export enum ToolCategory {
1111
PERFORMANCE = 'performance',
1212
NETWORK = 'network',
1313
DEBUGGING = 'debugging',
14+
EXTENSIONS = 'extensions',
1415
}
1516

1617
export const labels = {
@@ -20,4 +21,5 @@ export const labels = {
2021
[ToolCategory.PERFORMANCE]: 'Performance',
2122
[ToolCategory.NETWORK]: 'Network',
2223
[ToolCategory.DEBUGGING]: 'Debugging',
24+
[ToolCategory.EXTENSIONS]: 'Extensions',
2325
};

src/tools/extensions.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/**
2+
* @license
3+
* Copyright 2026 Google LLC
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
import {zod} from '../third_party/index.js';
8+
9+
import {ToolCategory} from './categories.js';
10+
import {defineTool} from './ToolDefinition.js';
11+
12+
export const installExtension = defineTool({
13+
name: 'install_extension',
14+
description: 'Installs a Chrome extension from the given path.',
15+
annotations: {
16+
category: ToolCategory.EXTENSIONS,
17+
readOnlyHint: false,
18+
},
19+
schema: {
20+
path: zod
21+
.string()
22+
.describe('Absolute path to the unpacked extension folder.'),
23+
},
24+
handler: async (request, response, context) => {
25+
const {path} = request.params;
26+
const id = await context.installExtension(path);
27+
response.appendResponseLine(`Extension installed. Id: ${id}`);
28+
},
29+
});

src/tools/tools.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import * as consoleTools from './console.js';
88
import * as emulationTools from './emulation.js';
9+
import * as extensionTools from './extensions.js';
910
import * as inputTools from './input.js';
1011
import * as networkTools from './network.js';
1112
import * as pagesTools from './pages.js';
@@ -18,6 +19,7 @@ import type {ToolDefinition} from './ToolDefinition.js';
1819
const tools = [
1920
...Object.values(consoleTools),
2021
...Object.values(emulationTools),
22+
...Object.values(extensionTools),
2123
...Object.values(inputTools),
2224
...Object.values(networkTools),
2325
...Object.values(pagesTools),

tests/cli.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ describe('cli args parsing', () => {
1515
categoryEmulation: true,
1616
'category-performance': true,
1717
categoryPerformance: true,
18+
'category-extensions': false,
19+
categoryExtensions: false,
1820
'category-network': true,
1921
categoryNetwork: true,
2022
'auto-connect': undefined,

0 commit comments

Comments
 (0)