@rabbitai-lab/agent-browser-mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,1901 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/server.ts
4
+ import { createServer } from "http";
5
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
6
+ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
7
+ import { randomUUID } from "crypto";
8
+
9
+ // src/executor.ts
10
+ import { spawn } from "child_process";
11
+
12
+ // src/utils.ts
13
+ function shellEscape(str) {
14
+ if (!str) return "''";
15
+ if (/^[a-zA-Z0-9./:@_\-+%*=~]+$/.test(str)) return str;
16
+ return "'" + str.replace(/'/g, "'\\''") + "'";
17
+ }
18
+ function getRequestBody(req) {
19
+ return new Promise((resolve, reject) => {
20
+ const chunks = [];
21
+ req.on("data", (chunk) => chunks.push(chunk));
22
+ req.on("end", () => {
23
+ const raw = Buffer.concat(chunks).toString("utf-8");
24
+ if (!raw) {
25
+ resolve(void 0);
26
+ return;
27
+ }
28
+ try {
29
+ resolve(JSON.parse(raw));
30
+ } catch (e) {
31
+ reject(new Error(`Invalid JSON body: ${e.message}`));
32
+ }
33
+ });
34
+ req.on("error", reject);
35
+ });
36
+ }
37
+ function buildGlobalArgs(options) {
38
+ if (!options) return "";
39
+ const args = [];
40
+ if (options.session) args.push(`--session ${shellEscape(options.session)}`);
41
+ if (options.headed) args.push("--headed");
42
+ if (options.cdp) args.push(`--cdp ${shellEscape(options.cdp)}`);
43
+ if (options.profile) args.push(`--profile ${shellEscape(options.profile)}`);
44
+ if (options.proxy) args.push(`--proxy ${shellEscape(options.proxy)}`);
45
+ if (options.json) args.push("--json");
46
+ if (options.debug) args.push("--debug");
47
+ return args.join(" ");
48
+ }
49
+ function extractGlobalOptions(args) {
50
+ const globalKeys = /* @__PURE__ */ new Set(["session", "headed", "cdp", "profile", "proxy", "json", "debug"]);
51
+ const global = {};
52
+ const rest = {};
53
+ for (const [key, value] of Object.entries(args)) {
54
+ if (globalKeys.has(key)) {
55
+ global[key] = value;
56
+ } else {
57
+ rest[key] = value;
58
+ }
59
+ }
60
+ return { global, rest };
61
+ }
62
+
63
+ // src/executor.ts
64
+ var DEFAULT_OPTIONS = {
65
+ cliPath: "agent-browser",
66
+ timeout: 12e4
67
+ };
68
+ var CliExecutor = class {
69
+ options;
70
+ activeProcesses = /* @__PURE__ */ new Set();
71
+ constructor(options) {
72
+ this.options = { ...DEFAULT_OPTIONS, ...options };
73
+ }
74
+ async execute(command, globalOptions) {
75
+ const cliPath = this.options.cliPath;
76
+ const timeout = this.options.timeout;
77
+ const globalArgs = buildGlobalArgs(globalOptions);
78
+ const fullCommand = globalArgs ? `${command} ${globalArgs}` : command;
79
+ return new Promise((resolve) => {
80
+ const proc = spawn(cliPath, [fullCommand], {
81
+ shell: true,
82
+ env: { ...process.env }
83
+ });
84
+ this.activeProcesses.add(proc);
85
+ let stdout = "";
86
+ let stderr = "";
87
+ let settled = false;
88
+ const finish = (error) => {
89
+ if (settled) return;
90
+ settled = true;
91
+ this.activeProcesses.delete(proc);
92
+ resolve({ stdout, stderr, exitCode: proc.exitCode ?? -1, error });
93
+ };
94
+ proc.stdout?.on("data", (chunk) => {
95
+ stdout += chunk.toString();
96
+ });
97
+ proc.stderr?.on("data", (chunk) => {
98
+ stderr += chunk.toString();
99
+ });
100
+ proc.on("close", (code) => {
101
+ if (code === 0) {
102
+ finish();
103
+ } else {
104
+ finish(stderr || `Process exited with code ${code}`);
105
+ }
106
+ });
107
+ proc.on("error", (err) => {
108
+ finish(err.message);
109
+ });
110
+ setTimeout(() => {
111
+ if (!settled) {
112
+ proc.kill("SIGTERM");
113
+ finish(`Command timed out after ${timeout}ms`);
114
+ }
115
+ }, timeout);
116
+ });
117
+ }
118
+ async close() {
119
+ for (const proc of this.activeProcesses) {
120
+ proc.kill("SIGTERM");
121
+ }
122
+ this.activeProcesses.clear();
123
+ }
124
+ };
125
+
126
+ // src/tools/navigation.ts
127
+ import { z as z2 } from "zod";
128
+
129
+ // src/tools/schemas.ts
130
+ import { z } from "zod";
131
+ var GlobalOptionsSchema = {
132
+ session: z.string().optional().describe("Isolated browser session name (--session)"),
133
+ headed: z.boolean().optional().describe("Show browser window, not headless (--headed)"),
134
+ cdp: z.string().optional().describe("Connect via Chrome DevTools Protocol port or URL (--cdp)"),
135
+ profile: z.string().optional().describe("Chrome profile name or directory path (--profile)"),
136
+ proxy: z.string().optional().describe("Proxy server URL (--proxy)"),
137
+ json: z.boolean().optional().describe("JSON output (--json)"),
138
+ debug: z.boolean().optional().describe("Debug output (--debug)")
139
+ };
140
+ var SelectorSchema = z.string().describe("CSS selector, XPath, or @ref from snapshot (e.g., @e1)");
141
+ var DirectionSchema = z.enum(["up", "down", "left", "right"]);
142
+
143
+ // src/tools/navigation.ts
144
+ function buildOpenCommand(params) {
145
+ const parts = [`open ${shellEscape(params.url)}`];
146
+ if (params.headers) parts.push(`--headers ${shellEscape(params.headers)}`);
147
+ return parts.join(" ");
148
+ }
149
+ function buildConnectCommand(params) {
150
+ return `connect ${shellEscape(params.target)}`;
151
+ }
152
+ function buildCloseCommand(params) {
153
+ const parts = ["close"];
154
+ if (params.all) parts.push("--all");
155
+ return parts.join(" ");
156
+ }
157
+ function buildBackCommand() {
158
+ return "back";
159
+ }
160
+ function buildForwardCommand() {
161
+ return "forward";
162
+ }
163
+ function buildReloadCommand() {
164
+ return "reload";
165
+ }
166
+ function registerNavigationTools(server, executor) {
167
+ server.tool(
168
+ "open",
169
+ "Navigate to a URL",
170
+ {
171
+ url: z2.string().describe("URL to navigate to"),
172
+ headers: z2.string().optional().describe("HTTP headers as JSON string"),
173
+ ...GlobalOptionsSchema
174
+ },
175
+ async (args) => {
176
+ const { global, rest } = extractGlobalOptions(args);
177
+ const cmd = buildOpenCommand(rest);
178
+ const result = await executor.execute(cmd, global);
179
+ return {
180
+ content: [{ type: "text", text: result.stdout || "OK" }],
181
+ ...result.error ? { isError: true } : {}
182
+ };
183
+ }
184
+ );
185
+ server.tool(
186
+ "back",
187
+ "Go back to the previous page",
188
+ { ...GlobalOptionsSchema },
189
+ async (args) => {
190
+ const { global } = extractGlobalOptions(args);
191
+ const result = await executor.execute(buildBackCommand(), global);
192
+ return {
193
+ content: [{ type: "text", text: result.stdout || "OK" }],
194
+ ...result.error ? { isError: true } : {}
195
+ };
196
+ }
197
+ );
198
+ server.tool(
199
+ "forward",
200
+ "Go forward to the next page",
201
+ { ...GlobalOptionsSchema },
202
+ async (args) => {
203
+ const { global } = extractGlobalOptions(args);
204
+ const result = await executor.execute(buildForwardCommand(), global);
205
+ return {
206
+ content: [{ type: "text", text: result.stdout || "OK" }],
207
+ ...result.error ? { isError: true } : {}
208
+ };
209
+ }
210
+ );
211
+ server.tool(
212
+ "reload",
213
+ "Reload the current page",
214
+ { ...GlobalOptionsSchema },
215
+ async (args) => {
216
+ const { global } = extractGlobalOptions(args);
217
+ const result = await executor.execute(buildReloadCommand(), global);
218
+ return {
219
+ content: [{ type: "text", text: result.stdout || "OK" }],
220
+ ...result.error ? { isError: true } : {}
221
+ };
222
+ }
223
+ );
224
+ server.tool(
225
+ "close",
226
+ "Close the browser session",
227
+ {
228
+ all: z2.boolean().optional().describe("Close every browser session"),
229
+ ...GlobalOptionsSchema
230
+ },
231
+ async (args) => {
232
+ const { global, rest } = extractGlobalOptions(args);
233
+ const cmd = buildCloseCommand(rest);
234
+ const result = await executor.execute(cmd, global);
235
+ return {
236
+ content: [{ type: "text", text: result.stdout || "OK" }],
237
+ ...result.error ? { isError: true } : {}
238
+ };
239
+ }
240
+ );
241
+ server.tool(
242
+ "connect",
243
+ "Connect to a browser via CDP (Chrome DevTools Protocol)",
244
+ {
245
+ target: z2.string().describe("CDP port number or URL to connect to"),
246
+ ...GlobalOptionsSchema
247
+ },
248
+ async (args) => {
249
+ const { global, rest } = extractGlobalOptions(args);
250
+ const cmd = buildConnectCommand(rest);
251
+ const result = await executor.execute(cmd, global);
252
+ return {
253
+ content: [{ type: "text", text: result.stdout || "OK" }],
254
+ ...result.error ? { isError: true } : {}
255
+ };
256
+ }
257
+ );
258
+ }
259
+
260
+ // src/tools/interaction.ts
261
+ import { z as z3 } from "zod";
262
+ function buildClickCommand(params) {
263
+ const parts = [`click ${shellEscape(params.selector)}`];
264
+ if (params.newTab) parts.push("--new-tab");
265
+ return parts.join(" ");
266
+ }
267
+ function buildDblclickCommand(params) {
268
+ return `dblclick ${shellEscape(params.selector)}`;
269
+ }
270
+ function buildTypeCommand(params) {
271
+ return `type ${shellEscape(params.selector)} ${shellEscape(params.text)}`;
272
+ }
273
+ function buildFillCommand(params) {
274
+ return `fill ${shellEscape(params.selector)} ${shellEscape(params.text)}`;
275
+ }
276
+ function buildPressCommand(params) {
277
+ return `press ${shellEscape(params.key)}`;
278
+ }
279
+ function buildHoverCommand(params) {
280
+ return `hover ${shellEscape(params.selector)}`;
281
+ }
282
+ function buildFocusCommand(params) {
283
+ return `focus ${shellEscape(params.selector)}`;
284
+ }
285
+ function buildCheckCommand(params) {
286
+ return `check ${shellEscape(params.selector)}`;
287
+ }
288
+ function buildUncheckCommand(params) {
289
+ return `uncheck ${shellEscape(params.selector)}`;
290
+ }
291
+ function buildSelectCommand(params) {
292
+ const values = params.values.map((v) => shellEscape(v)).join(" ");
293
+ return `select ${shellEscape(params.selector)} ${values}`;
294
+ }
295
+ function buildDragCommand(params) {
296
+ return `drag ${shellEscape(params.source)} ${shellEscape(params.target)}`;
297
+ }
298
+ function buildUploadCommand(params) {
299
+ const files = params.files.map((f) => shellEscape(f)).join(" ");
300
+ return `upload ${shellEscape(params.selector)} ${files}`;
301
+ }
302
+ function buildDownloadCommand(params) {
303
+ return `download ${shellEscape(params.selector)} ${shellEscape(params.path)}`;
304
+ }
305
+ function buildScrollCommand(params) {
306
+ const dir = params.direction || "down";
307
+ const amount = params.amount || 300;
308
+ let cmd = `scroll ${dir} ${amount}`;
309
+ if (params.selector) cmd += ` -s ${shellEscape(params.selector)}`;
310
+ return cmd;
311
+ }
312
+ function buildScrollIntoViewCommand(params) {
313
+ return `scrollintoview ${shellEscape(params.selector)}`;
314
+ }
315
+ function buildWaitCommand(params) {
316
+ const target = params.target;
317
+ if (/^\d+$/.test(target)) return `wait ${target}`;
318
+ return `wait ${shellEscape(target)}`;
319
+ }
320
+ function registerInteractionTools(server, executor) {
321
+ server.tool(
322
+ "click",
323
+ "Click an element by selector or @ref",
324
+ {
325
+ selector: SelectorSchema,
326
+ newTab: z3.boolean().optional().describe("Open link in new tab"),
327
+ ...GlobalOptionsSchema
328
+ },
329
+ async (args) => {
330
+ const { global, rest } = extractGlobalOptions(args);
331
+ const result = await executor.execute(buildClickCommand(rest), global);
332
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
333
+ }
334
+ );
335
+ server.tool(
336
+ "dblclick",
337
+ "Double-click an element",
338
+ {
339
+ selector: SelectorSchema,
340
+ ...GlobalOptionsSchema
341
+ },
342
+ async (args) => {
343
+ const { global, rest } = extractGlobalOptions(args);
344
+ const result = await executor.execute(buildDblclickCommand(rest), global);
345
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
346
+ }
347
+ );
348
+ server.tool(
349
+ "type",
350
+ "Type text into an element (appends to existing content)",
351
+ {
352
+ selector: SelectorSchema,
353
+ text: z3.string().describe("Text to type"),
354
+ ...GlobalOptionsSchema
355
+ },
356
+ async (args) => {
357
+ const { global, rest } = extractGlobalOptions(args);
358
+ const result = await executor.execute(buildTypeCommand(rest), global);
359
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
360
+ }
361
+ );
362
+ server.tool(
363
+ "fill",
364
+ "Clear and fill an element with text",
365
+ {
366
+ selector: SelectorSchema,
367
+ text: z3.string().describe("Text to fill"),
368
+ ...GlobalOptionsSchema
369
+ },
370
+ async (args) => {
371
+ const { global, rest } = extractGlobalOptions(args);
372
+ const result = await executor.execute(buildFillCommand(rest), global);
373
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
374
+ }
375
+ );
376
+ server.tool(
377
+ "press",
378
+ "Press a keyboard key (e.g., Enter, Tab, Control+a)",
379
+ {
380
+ key: z3.string().describe("Key to press (e.g., Enter, Tab, Control+a)"),
381
+ ...GlobalOptionsSchema
382
+ },
383
+ async (args) => {
384
+ const { global, rest } = extractGlobalOptions(args);
385
+ const result = await executor.execute(buildPressCommand(rest), global);
386
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
387
+ }
388
+ );
389
+ server.tool(
390
+ "hover",
391
+ "Hover over an element",
392
+ {
393
+ selector: SelectorSchema,
394
+ ...GlobalOptionsSchema
395
+ },
396
+ async (args) => {
397
+ const { global, rest } = extractGlobalOptions(args);
398
+ const result = await executor.execute(buildHoverCommand(rest), global);
399
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
400
+ }
401
+ );
402
+ server.tool(
403
+ "focus",
404
+ "Focus an element",
405
+ {
406
+ selector: SelectorSchema,
407
+ ...GlobalOptionsSchema
408
+ },
409
+ async (args) => {
410
+ const { global, rest } = extractGlobalOptions(args);
411
+ const result = await executor.execute(buildFocusCommand(rest), global);
412
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
413
+ }
414
+ );
415
+ server.tool(
416
+ "check",
417
+ "Check a checkbox",
418
+ {
419
+ selector: SelectorSchema,
420
+ ...GlobalOptionsSchema
421
+ },
422
+ async (args) => {
423
+ const { global, rest } = extractGlobalOptions(args);
424
+ const result = await executor.execute(buildCheckCommand(rest), global);
425
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
426
+ }
427
+ );
428
+ server.tool(
429
+ "uncheck",
430
+ "Uncheck a checkbox",
431
+ {
432
+ selector: SelectorSchema,
433
+ ...GlobalOptionsSchema
434
+ },
435
+ async (args) => {
436
+ const { global, rest } = extractGlobalOptions(args);
437
+ const result = await executor.execute(buildUncheckCommand(rest), global);
438
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
439
+ }
440
+ );
441
+ server.tool(
442
+ "select",
443
+ "Select dropdown option(s)",
444
+ {
445
+ selector: SelectorSchema,
446
+ values: z3.array(z3.string()).describe("Option value(s) to select"),
447
+ ...GlobalOptionsSchema
448
+ },
449
+ async (args) => {
450
+ const { global, rest } = extractGlobalOptions(args);
451
+ const result = await executor.execute(buildSelectCommand(rest), global);
452
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
453
+ }
454
+ );
455
+ server.tool(
456
+ "drag",
457
+ "Drag and drop from source to target element",
458
+ {
459
+ source: z3.string().describe("Source element selector or @ref"),
460
+ target: z3.string().describe("Target element selector or @ref"),
461
+ ...GlobalOptionsSchema
462
+ },
463
+ async (args) => {
464
+ const { global, rest } = extractGlobalOptions(args);
465
+ const result = await executor.execute(buildDragCommand(rest), global);
466
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
467
+ }
468
+ );
469
+ server.tool(
470
+ "upload",
471
+ "Upload file(s) to an element",
472
+ {
473
+ selector: SelectorSchema,
474
+ files: z3.array(z3.string()).describe("File path(s) to upload"),
475
+ ...GlobalOptionsSchema
476
+ },
477
+ async (args) => {
478
+ const { global, rest } = extractGlobalOptions(args);
479
+ const result = await executor.execute(buildUploadCommand(rest), global);
480
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
481
+ }
482
+ );
483
+ server.tool(
484
+ "download",
485
+ "Download a file by clicking an element",
486
+ {
487
+ selector: SelectorSchema,
488
+ path: z3.string().describe("Download destination path"),
489
+ ...GlobalOptionsSchema
490
+ },
491
+ async (args) => {
492
+ const { global, rest } = extractGlobalOptions(args);
493
+ const result = await executor.execute(buildDownloadCommand(rest), global);
494
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
495
+ }
496
+ );
497
+ server.tool(
498
+ "scroll",
499
+ "Scroll the page or a scrollable container",
500
+ {
501
+ direction: z3.enum(["up", "down", "left", "right"]).optional().describe("Scroll direction (default: down)"),
502
+ amount: z3.number().optional().describe("Pixels to scroll (default: 300)"),
503
+ selector: z3.string().optional().describe("Scrollable container selector"),
504
+ ...GlobalOptionsSchema
505
+ },
506
+ async (args) => {
507
+ const { global, rest } = extractGlobalOptions(args);
508
+ const result = await executor.execute(buildScrollCommand(rest), global);
509
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
510
+ }
511
+ );
512
+ server.tool(
513
+ "scroll_into_view",
514
+ "Scroll an element into view",
515
+ {
516
+ selector: SelectorSchema,
517
+ ...GlobalOptionsSchema
518
+ },
519
+ async (args) => {
520
+ const { global, rest } = extractGlobalOptions(args);
521
+ const result = await executor.execute(buildScrollIntoViewCommand(rest), global);
522
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
523
+ }
524
+ );
525
+ server.tool(
526
+ "wait",
527
+ "Wait for an element, timeout, or condition",
528
+ {
529
+ target: z3.string().describe("CSS selector, @ref, or milliseconds to wait"),
530
+ ...GlobalOptionsSchema
531
+ },
532
+ async (args) => {
533
+ const { global, rest } = extractGlobalOptions(args);
534
+ const result = await executor.execute(buildWaitCommand(rest), global);
535
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
536
+ }
537
+ );
538
+ }
539
+
540
+ // src/tools/query.ts
541
+ import { z as z4 } from "zod";
542
+ function buildSnapshotCommand(params) {
543
+ const parts = ["snapshot"];
544
+ if (params.interactive) parts.push("-i");
545
+ if (params.compact) parts.push("-c");
546
+ if (params.depth) parts.push(`-d ${params.depth}`);
547
+ if (params.selector) parts.push(`-s ${shellEscape(params.selector)}`);
548
+ return parts.join(" ");
549
+ }
550
+ function buildGetCommand(params) {
551
+ const what = params.what;
552
+ const parts = [`get ${what}`];
553
+ if (params.selector) parts.push(shellEscape(params.selector));
554
+ if (what === "attr" && params.attribute) parts.push(shellEscape(params.attribute));
555
+ return parts.join(" ");
556
+ }
557
+ function buildIsCommand(params) {
558
+ return `is ${params.what} ${shellEscape(params.selector)}`;
559
+ }
560
+ function buildFindCommand(params) {
561
+ const parts = [`find ${params.locator} ${shellEscape(params.value)}`];
562
+ if (params.action) parts.push(params.action);
563
+ if (params.actionText) parts.push(shellEscape(params.actionText));
564
+ if (params.name) parts.push(`--name ${shellEscape(params.name)}`);
565
+ if (params.exact) parts.push("--exact");
566
+ return parts.join(" ");
567
+ }
568
+ function buildEvalCommand(params) {
569
+ return `eval ${shellEscape(params.script)}`;
570
+ }
571
+ function registerQueryTools(server, executor) {
572
+ server.tool(
573
+ "snapshot",
574
+ "Capture accessibility tree with element refs (for AI agents)",
575
+ {
576
+ interactive: z4.boolean().optional().describe("Only interactive elements (-i)"),
577
+ compact: z4.boolean().optional().describe("Remove empty structural elements (-c)"),
578
+ depth: z4.number().optional().describe("Limit tree depth (-d)"),
579
+ selector: z4.string().optional().describe("Scope to CSS selector (-s)"),
580
+ ...GlobalOptionsSchema
581
+ },
582
+ async (args) => {
583
+ const { global, rest } = extractGlobalOptions(args);
584
+ const result = await executor.execute(buildSnapshotCommand(rest), global);
585
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
586
+ }
587
+ );
588
+ server.tool(
589
+ "get",
590
+ "Get element information (text, html, value, attribute, title, URL, etc.)",
591
+ {
592
+ what: z4.enum(["text", "html", "value", "attr", "title", "url", "count", "box", "styles", "cdp-url"]).describe("What to get"),
593
+ selector: z4.string().optional().describe("Element selector or @ref (required for most properties)"),
594
+ attribute: z4.string().optional().describe("Attribute name (required when what=attr)"),
595
+ ...GlobalOptionsSchema
596
+ },
597
+ async (args) => {
598
+ const { global, rest } = extractGlobalOptions(args);
599
+ const result = await executor.execute(buildGetCommand(rest), global);
600
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
601
+ }
602
+ );
603
+ server.tool(
604
+ "is",
605
+ "Check element state (visible, enabled, checked)",
606
+ {
607
+ what: z4.enum(["visible", "enabled", "checked"]).describe("State to check"),
608
+ selector: SelectorSchema,
609
+ ...GlobalOptionsSchema
610
+ },
611
+ async (args) => {
612
+ const { global, rest } = extractGlobalOptions(args);
613
+ const result = await executor.execute(buildIsCommand(rest), global);
614
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
615
+ }
616
+ );
617
+ server.tool(
618
+ "find",
619
+ "Find elements by locator and perform an action",
620
+ {
621
+ locator: z4.enum(["role", "text", "label", "placeholder", "alt", "title", "testid", "first", "last", "nth"]).describe("Locator strategy"),
622
+ value: z4.string().describe("Locator value to search for"),
623
+ action: z4.enum(["click", "fill", "type", "hover", "focus", "check", "uncheck"]).optional().describe("Action to perform on found element"),
624
+ actionText: z4.string().optional().describe("Text for fill/type actions"),
625
+ name: z4.string().optional().describe("Name filter (for role locator)"),
626
+ exact: z4.boolean().optional().describe("Exact match"),
627
+ ...GlobalOptionsSchema
628
+ },
629
+ async (args) => {
630
+ const { global, rest } = extractGlobalOptions(args);
631
+ const result = await executor.execute(buildFindCommand(rest), global);
632
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
633
+ }
634
+ );
635
+ server.tool(
636
+ "eval",
637
+ "Run JavaScript in the browser page",
638
+ {
639
+ script: z4.string().describe("JavaScript expression to evaluate"),
640
+ ...GlobalOptionsSchema
641
+ },
642
+ async (args) => {
643
+ const { global, rest } = extractGlobalOptions(args);
644
+ const result = await executor.execute(buildEvalCommand(rest), global);
645
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
646
+ }
647
+ );
648
+ }
649
+
650
+ // src/tools/visual.ts
651
+ import { z as z5 } from "zod";
652
+ function buildScreenshotCommand(params) {
653
+ const parts = ["screenshot"];
654
+ if (params.full) parts.push("--full");
655
+ if (params.annotate) parts.push("--annotate");
656
+ if (params.selector) parts.push(shellEscape(params.selector));
657
+ if (params.path) parts.push(shellEscape(params.path));
658
+ if (params.format) parts.push(`--screenshot-format ${params.format}`);
659
+ if (params.quality !== void 0) parts.push(`--screenshot-quality ${params.quality}`);
660
+ return parts.join(" ");
661
+ }
662
+ function buildPdfCommand(params) {
663
+ return `pdf ${shellEscape(params.path)}`;
664
+ }
665
+ function buildDiffSnapshotCommand(params) {
666
+ return "diff snapshot";
667
+ }
668
+ function buildDiffScreenshotCommand(params) {
669
+ const parts = ["diff screenshot"];
670
+ if (params.baseline) parts.push(`--baseline ${shellEscape(params.baseline)}`);
671
+ return parts.join(" ");
672
+ }
673
+ function buildDiffUrlCommand(params) {
674
+ return `diff url ${shellEscape(params.url1)} ${shellEscape(params.url2)}`;
675
+ }
676
+ function buildHighlightCommand(params) {
677
+ return `highlight ${shellEscape(params.selector)}`;
678
+ }
679
+ function registerVisualTools(server, executor) {
680
+ server.tool(
681
+ "screenshot",
682
+ "Take a screenshot of the current page",
683
+ {
684
+ selector: z5.string().optional().describe("Element selector to screenshot"),
685
+ path: z5.string().optional().describe("Output file path"),
686
+ full: z5.boolean().optional().describe("Full page screenshot (--full)"),
687
+ annotate: z5.boolean().optional().describe("Annotated screenshot with numbered labels (--annotate)"),
688
+ format: z5.enum(["png", "jpeg"]).optional().describe("Screenshot format"),
689
+ quality: z5.number().optional().describe("JPEG quality 0-100"),
690
+ ...GlobalOptionsSchema
691
+ },
692
+ async (args) => {
693
+ const { global, rest } = extractGlobalOptions(args);
694
+ const result = await executor.execute(buildScreenshotCommand(rest), global);
695
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
696
+ }
697
+ );
698
+ server.tool(
699
+ "pdf",
700
+ "Save the current page as PDF",
701
+ {
702
+ path: z5.string().describe("Output PDF file path"),
703
+ ...GlobalOptionsSchema
704
+ },
705
+ async (args) => {
706
+ const { global, rest } = extractGlobalOptions(args);
707
+ const result = await executor.execute(buildPdfCommand(rest), global);
708
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
709
+ }
710
+ );
711
+ server.tool(
712
+ "diff_snapshot",
713
+ "Compare current accessibility snapshot vs last snapshot",
714
+ { ...GlobalOptionsSchema },
715
+ async (args) => {
716
+ const { global } = extractGlobalOptions(args);
717
+ const result = await executor.execute(buildDiffSnapshotCommand({}), global);
718
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
719
+ }
720
+ );
721
+ server.tool(
722
+ "diff_screenshot",
723
+ "Compare current screenshot vs baseline image",
724
+ {
725
+ baseline: z5.string().describe("Path to baseline image"),
726
+ ...GlobalOptionsSchema
727
+ },
728
+ async (args) => {
729
+ const { global, rest } = extractGlobalOptions(args);
730
+ const result = await executor.execute(buildDiffScreenshotCommand(rest), global);
731
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
732
+ }
733
+ );
734
+ server.tool(
735
+ "diff_url",
736
+ "Compare two URLs side by side",
737
+ {
738
+ url1: z5.string().describe("First URL"),
739
+ url2: z5.string().describe("Second URL"),
740
+ ...GlobalOptionsSchema
741
+ },
742
+ async (args) => {
743
+ const { global, rest } = extractGlobalOptions(args);
744
+ const result = await executor.execute(buildDiffUrlCommand(rest), global);
745
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
746
+ }
747
+ );
748
+ server.tool(
749
+ "highlight",
750
+ "Highlight an element on the page (for debugging)",
751
+ {
752
+ selector: SelectorSchema,
753
+ ...GlobalOptionsSchema
754
+ },
755
+ async (args) => {
756
+ const { global, rest } = extractGlobalOptions(args);
757
+ const result = await executor.execute(buildHighlightCommand(rest), global);
758
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
759
+ }
760
+ );
761
+ }
762
+
763
+ // src/tools/mouse.ts
764
+ import { z as z6 } from "zod";
765
+ function buildMouseMoveCommand(params) {
766
+ return `mouse move ${params.x} ${params.y}`;
767
+ }
768
+ function buildMouseDownCommand(params) {
769
+ const btn = params.button ? ` ${params.button}` : "";
770
+ return `mouse down${btn}`;
771
+ }
772
+ function buildMouseUpCommand(params) {
773
+ const btn = params.button ? ` ${params.button}` : "";
774
+ return `mouse up${btn}`;
775
+ }
776
+ function buildMouseWheelCommand(params) {
777
+ const dx = params.deltaX ? ` ${params.deltaX}` : "";
778
+ return `mouse wheel ${params.deltaY}${dx}`;
779
+ }
780
+ function registerMouseTools(server, executor) {
781
+ server.tool(
782
+ "mouse_move",
783
+ "Move mouse to coordinates",
784
+ {
785
+ x: z6.number().describe("X coordinate"),
786
+ y: z6.number().describe("Y coordinate"),
787
+ ...GlobalOptionsSchema
788
+ },
789
+ async (args) => {
790
+ const { global, rest } = extractGlobalOptions(args);
791
+ const result = await executor.execute(buildMouseMoveCommand(rest), global);
792
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
793
+ }
794
+ );
795
+ server.tool(
796
+ "mouse_down",
797
+ "Press a mouse button",
798
+ {
799
+ button: z6.enum(["left", "right", "middle"]).optional().describe("Mouse button (default: left)"),
800
+ ...GlobalOptionsSchema
801
+ },
802
+ async (args) => {
803
+ const { global, rest } = extractGlobalOptions(args);
804
+ const result = await executor.execute(buildMouseDownCommand(rest), global);
805
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
806
+ }
807
+ );
808
+ server.tool(
809
+ "mouse_up",
810
+ "Release a mouse button",
811
+ {
812
+ button: z6.enum(["left", "right", "middle"]).optional().describe("Mouse button (default: left)"),
813
+ ...GlobalOptionsSchema
814
+ },
815
+ async (args) => {
816
+ const { global, rest } = extractGlobalOptions(args);
817
+ const result = await executor.execute(buildMouseUpCommand(rest), global);
818
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
819
+ }
820
+ );
821
+ server.tool(
822
+ "mouse_wheel",
823
+ "Scroll the mouse wheel",
824
+ {
825
+ deltaY: z6.number().describe("Vertical scroll amount"),
826
+ deltaX: z6.number().optional().describe("Horizontal scroll amount"),
827
+ ...GlobalOptionsSchema
828
+ },
829
+ async (args) => {
830
+ const { global, rest } = extractGlobalOptions(args);
831
+ const result = await executor.execute(buildMouseWheelCommand(rest), global);
832
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
833
+ }
834
+ );
835
+ }
836
+
837
+ // src/tools/keyboard.ts
838
+ import { z as z7 } from "zod";
839
+ function buildKeyboardTypeCommand(params) {
840
+ return `keyboard type ${shellEscape(params.text)}`;
841
+ }
842
+ function buildKeyboardInsertCommand(params) {
843
+ return `keyboard inserttext ${shellEscape(params.text)}`;
844
+ }
845
+ function buildKeydownCommand(params) {
846
+ return `keydown ${shellEscape(params.key)}`;
847
+ }
848
+ function buildKeyupCommand(params) {
849
+ return `keyup ${shellEscape(params.key)}`;
850
+ }
851
+ function registerKeyboardTools(server, executor) {
852
+ server.tool(
853
+ "keyboard_type",
854
+ "Type text with real keystrokes (no selector needed)",
855
+ {
856
+ text: z7.string().describe("Text to type"),
857
+ ...GlobalOptionsSchema
858
+ },
859
+ async (args) => {
860
+ const { global, rest } = extractGlobalOptions(args);
861
+ const result = await executor.execute(buildKeyboardTypeCommand(rest), global);
862
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
863
+ }
864
+ );
865
+ server.tool(
866
+ "keyboard_insert",
867
+ "Insert text without key events (no selector needed)",
868
+ {
869
+ text: z7.string().describe("Text to insert"),
870
+ ...GlobalOptionsSchema
871
+ },
872
+ async (args) => {
873
+ const { global, rest } = extractGlobalOptions(args);
874
+ const result = await executor.execute(buildKeyboardInsertCommand(rest), global);
875
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
876
+ }
877
+ );
878
+ server.tool(
879
+ "keydown",
880
+ "Press and hold a key (without releasing)",
881
+ {
882
+ key: z7.string().describe("Key to hold down (e.g., Shift, Control, Alt)"),
883
+ ...GlobalOptionsSchema
884
+ },
885
+ async (args) => {
886
+ const { global, rest } = extractGlobalOptions(args);
887
+ const result = await executor.execute(buildKeydownCommand(rest), global);
888
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
889
+ }
890
+ );
891
+ server.tool(
892
+ "keyup",
893
+ "Release a previously held key",
894
+ {
895
+ key: z7.string().describe("Key to release (e.g., Shift, Control, Alt)"),
896
+ ...GlobalOptionsSchema
897
+ },
898
+ async (args) => {
899
+ const { global, rest } = extractGlobalOptions(args);
900
+ const result = await executor.execute(buildKeyupCommand(rest), global);
901
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
902
+ }
903
+ );
904
+ }
905
+
906
+ // src/tools/browser-settings.ts
907
+ import { z as z8 } from "zod";
908
+ function buildSetViewportCommand(params) {
909
+ return `set viewport ${params.width} ${params.height}`;
910
+ }
911
+ function buildSetDeviceCommand(params) {
912
+ return `set device ${shellEscape(params.device)}`;
913
+ }
914
+ function buildSetGeolocationCommand(params) {
915
+ return `set geo ${params.latitude} ${params.longitude}`;
916
+ }
917
+ function buildSetOfflineCommand(params) {
918
+ const enabled = params.enabled !== false;
919
+ return `set offline ${enabled ? "on" : "off"}`;
920
+ }
921
+ function buildSetHeadersCommand(params) {
922
+ return `set headers ${shellEscape(params.headers)}`;
923
+ }
924
+ function buildSetCredentialsCommand(params) {
925
+ return `set credentials ${shellEscape(params.username)} ${shellEscape(params.password)}`;
926
+ }
927
+ function buildSetColorSchemeCommand(params) {
928
+ const parts = ["set media"];
929
+ if (params.scheme) parts.push(params.scheme);
930
+ return parts.join(" ");
931
+ }
932
+ function registerBrowserSettingsTools(server, executor) {
933
+ server.tool("set_viewport", "Set browser viewport size", {
934
+ width: z8.number().describe("Viewport width"),
935
+ height: z8.number().describe("Viewport height"),
936
+ ...GlobalOptionsSchema
937
+ }, async (args) => {
938
+ const { global, rest } = extractGlobalOptions(args);
939
+ const result = await executor.execute(buildSetViewportCommand(rest), global);
940
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
941
+ });
942
+ server.tool("set_device", "Emulate a device", {
943
+ device: z8.string().describe('Device name (e.g., "iPhone 15 Pro")'),
944
+ ...GlobalOptionsSchema
945
+ }, async (args) => {
946
+ const { global, rest } = extractGlobalOptions(args);
947
+ const result = await executor.execute(buildSetDeviceCommand(rest), global);
948
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
949
+ });
950
+ server.tool("set_geolocation", "Set geolocation", {
951
+ latitude: z8.number().describe("Latitude"),
952
+ longitude: z8.number().describe("Longitude"),
953
+ ...GlobalOptionsSchema
954
+ }, async (args) => {
955
+ const { global, rest } = extractGlobalOptions(args);
956
+ const result = await executor.execute(buildSetGeolocationCommand(rest), global);
957
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
958
+ });
959
+ server.tool("set_offline", "Toggle offline mode", {
960
+ enabled: z8.boolean().optional().describe("Enable offline mode (default: true)"),
961
+ ...GlobalOptionsSchema
962
+ }, async (args) => {
963
+ const { global, rest } = extractGlobalOptions(args);
964
+ const result = await executor.execute(buildSetOfflineCommand(rest), global);
965
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
966
+ });
967
+ server.tool("set_headers", "Set HTTP headers", {
968
+ headers: z8.string().describe("Headers as JSON string"),
969
+ ...GlobalOptionsSchema
970
+ }, async (args) => {
971
+ const { global, rest } = extractGlobalOptions(args);
972
+ const result = await executor.execute(buildSetHeadersCommand(rest), global);
973
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
974
+ });
975
+ server.tool("set_credentials", "Set HTTP authentication credentials", {
976
+ username: z8.string().describe("Username"),
977
+ password: z8.string().describe("Password"),
978
+ ...GlobalOptionsSchema
979
+ }, async (args) => {
980
+ const { global, rest } = extractGlobalOptions(args);
981
+ const result = await executor.execute(buildSetCredentialsCommand(rest), global);
982
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
983
+ });
984
+ server.tool("set_color_scheme", "Set color scheme preference", {
985
+ scheme: z8.enum(["dark", "light"]).optional().describe("Color scheme"),
986
+ ...GlobalOptionsSchema
987
+ }, async (args) => {
988
+ const { global, rest } = extractGlobalOptions(args);
989
+ const result = await executor.execute(buildSetColorSchemeCommand(rest), global);
990
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
991
+ });
992
+ }
993
+
994
+ // src/tools/network.ts
995
+ import { z as z9 } from "zod";
996
+ function buildNetworkRouteCommand(params) {
997
+ const parts = [`network route ${shellEscape(params.url)}`];
998
+ if (params.abort) parts.push("--abort");
999
+ if (params.body) parts.push(`--body ${shellEscape(params.body)}`);
1000
+ return parts.join(" ");
1001
+ }
1002
+ function buildNetworkUnrouteCommand(params) {
1003
+ if (params.url) return `network unroute ${shellEscape(params.url)}`;
1004
+ return "network unroute";
1005
+ }
1006
+ function buildNetworkRequestsCommand(params) {
1007
+ const parts = ["network requests"];
1008
+ if (params.clear) parts.push("--clear");
1009
+ if (params.filter) parts.push(`--filter ${shellEscape(params.filter)}`);
1010
+ return parts.join(" ");
1011
+ }
1012
+ function buildNetworkRequestDetailCommand(params) {
1013
+ return `network request ${shellEscape(params.requestId)}`;
1014
+ }
1015
+ function buildNetworkHarCommand(params) {
1016
+ const parts = [`network har ${params.action}`];
1017
+ if (params.path) parts.push(shellEscape(params.path));
1018
+ return parts.join(" ");
1019
+ }
1020
+ function registerNetworkTools(server, executor) {
1021
+ server.tool("network_route", "Intercept network requests by URL pattern", {
1022
+ url: z9.string().describe("URL pattern to intercept"),
1023
+ abort: z9.boolean().optional().describe("Abort the request"),
1024
+ body: z9.string().optional().describe("Response body as JSON (--body)"),
1025
+ ...GlobalOptionsSchema
1026
+ }, async (args) => {
1027
+ const { global, rest } = extractGlobalOptions(args);
1028
+ const result = await executor.execute(buildNetworkRouteCommand(rest), global);
1029
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1030
+ });
1031
+ server.tool("network_unroute", "Remove a network route", {
1032
+ url: z9.string().optional().describe("URL pattern to remove (omit to remove all)"),
1033
+ ...GlobalOptionsSchema
1034
+ }, async (args) => {
1035
+ const { global, rest } = extractGlobalOptions(args);
1036
+ const result = await executor.execute(buildNetworkUnrouteCommand(rest), global);
1037
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1038
+ });
1039
+ server.tool("network_requests", "List network requests", {
1040
+ clear: z9.boolean().optional().describe("Clear request log (--clear)"),
1041
+ filter: z9.string().optional().describe("Filter pattern (--filter)"),
1042
+ ...GlobalOptionsSchema
1043
+ }, async (args) => {
1044
+ const { global, rest } = extractGlobalOptions(args);
1045
+ const result = await executor.execute(buildNetworkRequestsCommand(rest), global);
1046
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1047
+ });
1048
+ server.tool("network_request_detail", "Get full details of a network request", {
1049
+ requestId: z9.string().describe("Request ID from network requests list"),
1050
+ ...GlobalOptionsSchema
1051
+ }, async (args) => {
1052
+ const { global, rest } = extractGlobalOptions(args);
1053
+ const result = await executor.execute(buildNetworkRequestDetailCommand(rest), global);
1054
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1055
+ });
1056
+ server.tool("network_har", "Start or stop HAR recording", {
1057
+ action: z9.enum(["start", "stop"]).describe("Start or stop recording"),
1058
+ path: z9.string().optional().describe("HAR file output path"),
1059
+ ...GlobalOptionsSchema
1060
+ }, async (args) => {
1061
+ const { global, rest } = extractGlobalOptions(args);
1062
+ const result = await executor.execute(buildNetworkHarCommand(rest), global);
1063
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1064
+ });
1065
+ }
1066
+
1067
+ // src/tools/storage.ts
1068
+ import { z as z10 } from "zod";
1069
+ function buildCookiesGetCommand() {
1070
+ return "cookies get";
1071
+ }
1072
+ function buildCookiesSetCommand(params) {
1073
+ const parts = [`cookies set ${shellEscape(params.name)} ${shellEscape(params.value)}`];
1074
+ if (params.url) parts.push(`--url ${shellEscape(params.url)}`);
1075
+ if (params.domain) parts.push(`--domain ${shellEscape(params.domain)}`);
1076
+ if (params.path) parts.push(`--path ${shellEscape(params.path)}`);
1077
+ if (params.httpOnly) parts.push("--httpOnly");
1078
+ if (params.secure) parts.push("--secure");
1079
+ if (params.sameSite) parts.push(`--sameSite ${params.sameSite}`);
1080
+ if (params.expires !== void 0) parts.push(`--expires ${params.expires}`);
1081
+ return parts.join(" ");
1082
+ }
1083
+ function buildCookiesClearCommand() {
1084
+ return "cookies clear";
1085
+ }
1086
+ function buildStorageGetCommand(params) {
1087
+ const parts = [`storage ${params.type} get`];
1088
+ if (params.key) parts.push(shellEscape(params.key));
1089
+ return parts.join(" ");
1090
+ }
1091
+ function buildStorageSetCommand(params) {
1092
+ return `storage ${params.type} set ${shellEscape(params.key)} ${shellEscape(params.value)}`;
1093
+ }
1094
+ function buildStorageClearCommand(params) {
1095
+ return `storage ${params.type} clear`;
1096
+ }
1097
+ function registerStorageTools(server, executor) {
1098
+ server.tool("cookies_get", "Get all cookies", { ...GlobalOptionsSchema }, async (args) => {
1099
+ const { global } = extractGlobalOptions(args);
1100
+ const result = await executor.execute(buildCookiesGetCommand(), global);
1101
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1102
+ });
1103
+ server.tool("cookies_set", "Set a cookie", {
1104
+ name: z10.string().describe("Cookie name"),
1105
+ value: z10.string().describe("Cookie value"),
1106
+ url: z10.string().optional().describe("Cookie URL"),
1107
+ domain: z10.string().optional().describe("Cookie domain"),
1108
+ path: z10.string().optional().describe("Cookie path"),
1109
+ httpOnly: z10.boolean().optional().describe("HTTP only"),
1110
+ secure: z10.boolean().optional().describe("Secure only"),
1111
+ sameSite: z10.enum(["Strict", "Lax", "None"]).optional().describe("SameSite policy"),
1112
+ expires: z10.number().optional().describe("Expiration timestamp"),
1113
+ ...GlobalOptionsSchema
1114
+ }, async (args) => {
1115
+ const { global, rest } = extractGlobalOptions(args);
1116
+ const result = await executor.execute(buildCookiesSetCommand(rest), global);
1117
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1118
+ });
1119
+ server.tool("cookies_clear", "Clear all cookies", { ...GlobalOptionsSchema }, async (args) => {
1120
+ const { global } = extractGlobalOptions(args);
1121
+ const result = await executor.execute(buildCookiesClearCommand(), global);
1122
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1123
+ });
1124
+ server.tool("storage_get", "Get web storage value(s)", {
1125
+ type: z10.enum(["local", "session"]).describe("Storage type"),
1126
+ key: z10.string().optional().describe("Key to get (omit to get all)"),
1127
+ ...GlobalOptionsSchema
1128
+ }, async (args) => {
1129
+ const { global, rest } = extractGlobalOptions(args);
1130
+ const result = await executor.execute(buildStorageGetCommand(rest), global);
1131
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1132
+ });
1133
+ server.tool("storage_set", "Set a web storage value", {
1134
+ type: z10.enum(["local", "session"]).describe("Storage type"),
1135
+ key: z10.string().describe("Storage key"),
1136
+ value: z10.string().describe("Storage value"),
1137
+ ...GlobalOptionsSchema
1138
+ }, async (args) => {
1139
+ const { global, rest } = extractGlobalOptions(args);
1140
+ const result = await executor.execute(buildStorageSetCommand(rest), global);
1141
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1142
+ });
1143
+ server.tool("storage_clear", "Clear web storage", {
1144
+ type: z10.enum(["local", "session"]).describe("Storage type"),
1145
+ ...GlobalOptionsSchema
1146
+ }, async (args) => {
1147
+ const { global, rest } = extractGlobalOptions(args);
1148
+ const result = await executor.execute(buildStorageClearCommand(rest), global);
1149
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1150
+ });
1151
+ }
1152
+
1153
+ // src/tools/tabs.ts
1154
+ import { z as z11 } from "zod";
1155
+ function buildTabListCommand() {
1156
+ return "tab list";
1157
+ }
1158
+ function buildTabNewCommand(params) {
1159
+ const parts = ["tab new"];
1160
+ if (params.url) parts.push(shellEscape(params.url));
1161
+ if (params.label) parts.push(`--label ${shellEscape(params.label)}`);
1162
+ return parts.join(" ");
1163
+ }
1164
+ function buildTabCloseCommand(params) {
1165
+ if (params.ref) return `tab close ${shellEscape(params.ref)}`;
1166
+ return "tab close";
1167
+ }
1168
+ function buildTabSwitchCommand(params) {
1169
+ return `tab ${shellEscape(params.ref)}`;
1170
+ }
1171
+ function buildFrameCommand(params) {
1172
+ return `frame ${shellEscape(params.target)}`;
1173
+ }
1174
+ function buildWindowNewCommand() {
1175
+ return "window new";
1176
+ }
1177
+ function registerTabTools(server, executor) {
1178
+ server.tool("tab_list", "List all browser tabs", { ...GlobalOptionsSchema }, async (args) => {
1179
+ const { global } = extractGlobalOptions(args);
1180
+ const result = await executor.execute(buildTabListCommand(), global);
1181
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1182
+ });
1183
+ server.tool("tab_new", "Open a new tab", {
1184
+ url: z11.string().optional().describe("URL to open in new tab"),
1185
+ label: z11.string().optional().describe("Tab label (--label)"),
1186
+ ...GlobalOptionsSchema
1187
+ }, async (args) => {
1188
+ const { global, rest } = extractGlobalOptions(args);
1189
+ const result = await executor.execute(buildTabNewCommand(rest), global);
1190
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1191
+ });
1192
+ server.tool("tab_close", "Close a tab", {
1193
+ ref: z11.string().optional().describe("Tab reference or label (omit to close current)"),
1194
+ ...GlobalOptionsSchema
1195
+ }, async (args) => {
1196
+ const { global, rest } = extractGlobalOptions(args);
1197
+ const result = await executor.execute(buildTabCloseCommand(rest), global);
1198
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1199
+ });
1200
+ server.tool("tab_switch", "Switch to a tab by reference or label", {
1201
+ ref: z11.string().describe("Tab reference (e.g., t1) or label"),
1202
+ ...GlobalOptionsSchema
1203
+ }, async (args) => {
1204
+ const { global, rest } = extractGlobalOptions(args);
1205
+ const result = await executor.execute(buildTabSwitchCommand(rest), global);
1206
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1207
+ });
1208
+ server.tool("frame", "Switch frame context (iframe or main)", {
1209
+ target: z11.string().describe('CSS selector, @ref for iframe, or "main" to return to top-level frame'),
1210
+ ...GlobalOptionsSchema
1211
+ }, async (args) => {
1212
+ const { global, rest } = extractGlobalOptions(args);
1213
+ const result = await executor.execute(buildFrameCommand(rest), global);
1214
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1215
+ });
1216
+ server.tool("window_new", "Open a new browser window", { ...GlobalOptionsSchema }, async (args) => {
1217
+ const { global } = extractGlobalOptions(args);
1218
+ const result = await executor.execute(buildWindowNewCommand(), global);
1219
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1220
+ });
1221
+ }
1222
+
1223
+ // src/tools/debug.ts
1224
+ import { z as z12 } from "zod";
1225
+ function buildConsoleCommand(params) {
1226
+ const parts = ["console"];
1227
+ if (params.clear) parts.push("--clear");
1228
+ return parts.join(" ");
1229
+ }
1230
+ function buildErrorsCommand(params) {
1231
+ const parts = ["errors"];
1232
+ if (params.clear) parts.push("--clear");
1233
+ return parts.join(" ");
1234
+ }
1235
+ function buildTraceCommand(params) {
1236
+ const parts = [`trace ${params.action}`];
1237
+ if (params.path) parts.push(shellEscape(params.path));
1238
+ return parts.join(" ");
1239
+ }
1240
+ function buildProfilerCommand(params) {
1241
+ const parts = [`profiler ${params.action}`];
1242
+ if (params.path) parts.push(shellEscape(params.path));
1243
+ return parts.join(" ");
1244
+ }
1245
+ function buildRecordCommand(params) {
1246
+ if (params.action === "stop") return "record stop";
1247
+ if (params.action === "restart") return `record restart ${shellEscape(params.path)}`;
1248
+ const parts = [`record start ${shellEscape(params.path)}`];
1249
+ if (params.url) parts.push(shellEscape(params.url));
1250
+ return parts.join(" ");
1251
+ }
1252
+ function buildClipboardCommand(params) {
1253
+ const parts = [`clipboard ${params.operation}`];
1254
+ if (params.text) parts.push(shellEscape(params.text));
1255
+ return parts.join(" ");
1256
+ }
1257
+ function buildInspectCommand() {
1258
+ return "inspect";
1259
+ }
1260
+ function registerDebugTools(server, executor) {
1261
+ server.tool("console", "View console logs", {
1262
+ clear: z12.boolean().optional().describe("Clear console log"),
1263
+ ...GlobalOptionsSchema
1264
+ }, async (args) => {
1265
+ const { global, rest } = extractGlobalOptions(args);
1266
+ const result = await executor.execute(buildConsoleCommand(rest), global);
1267
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1268
+ });
1269
+ server.tool("errors", "View page errors", {
1270
+ clear: z12.boolean().optional().describe("Clear errors"),
1271
+ ...GlobalOptionsSchema
1272
+ }, async (args) => {
1273
+ const { global, rest } = extractGlobalOptions(args);
1274
+ const result = await executor.execute(buildErrorsCommand(rest), global);
1275
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1276
+ });
1277
+ server.tool("trace", "Record Chrome DevTools trace", {
1278
+ action: z12.enum(["start", "stop"]).describe("Start or stop tracing"),
1279
+ path: z12.string().optional().describe("Output trace file path"),
1280
+ ...GlobalOptionsSchema
1281
+ }, async (args) => {
1282
+ const { global, rest } = extractGlobalOptions(args);
1283
+ const result = await executor.execute(buildTraceCommand(rest), global);
1284
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1285
+ });
1286
+ server.tool("profiler", "Record Chrome DevTools profile", {
1287
+ action: z12.enum(["start", "stop"]).describe("Start or stop profiling"),
1288
+ path: z12.string().optional().describe("Output profile file path"),
1289
+ ...GlobalOptionsSchema
1290
+ }, async (args) => {
1291
+ const { global, rest } = extractGlobalOptions(args);
1292
+ const result = await executor.execute(buildProfilerCommand(rest), global);
1293
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1294
+ });
1295
+ server.tool("record", "Record browser session as video (WebM)", {
1296
+ action: z12.enum(["start", "stop", "restart"]).describe("Start, stop, or restart recording"),
1297
+ path: z12.string().optional().describe("Output video file path (required for start)"),
1298
+ url: z12.string().optional().describe("URL to open when recording starts"),
1299
+ ...GlobalOptionsSchema
1300
+ }, async (args) => {
1301
+ const { global, rest } = extractGlobalOptions(args);
1302
+ const result = await executor.execute(buildRecordCommand(rest), global);
1303
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1304
+ });
1305
+ server.tool("clipboard", "Read or write the clipboard", {
1306
+ operation: z12.enum(["read", "write", "copy", "paste"]).describe("Clipboard operation"),
1307
+ text: z12.string().optional().describe("Text for write operation"),
1308
+ ...GlobalOptionsSchema
1309
+ }, async (args) => {
1310
+ const { global, rest } = extractGlobalOptions(args);
1311
+ const result = await executor.execute(buildClipboardCommand(rest), global);
1312
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1313
+ });
1314
+ server.tool("inspect", "Open Chrome DevTools for the active page", { ...GlobalOptionsSchema }, async (args) => {
1315
+ const { global } = extractGlobalOptions(args);
1316
+ const result = await executor.execute(buildInspectCommand(), global);
1317
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1318
+ });
1319
+ }
1320
+
1321
+ // src/tools/auth.ts
1322
+ import { z as z13 } from "zod";
1323
+ function buildAuthSaveCommand(params) {
1324
+ const parts = [`auth save ${shellEscape(params.name)}`];
1325
+ if (params.url) parts.push(`--url ${shellEscape(params.url)}`);
1326
+ if (params.username) parts.push(`--username ${shellEscape(params.username)}`);
1327
+ if (params.password) parts.push(`--password ${shellEscape(params.password)}`);
1328
+ return parts.join(" ");
1329
+ }
1330
+ function buildAuthLoginCommand(params) {
1331
+ return `auth login ${shellEscape(params.name)}`;
1332
+ }
1333
+ function buildAuthListCommand() {
1334
+ return "auth list";
1335
+ }
1336
+ function buildAuthShowCommand(params) {
1337
+ return `auth show ${shellEscape(params.name)}`;
1338
+ }
1339
+ function buildAuthDeleteCommand(params) {
1340
+ return `auth delete ${shellEscape(params.name)}`;
1341
+ }
1342
+ function registerAuthTools(server, executor) {
1343
+ server.tool("auth_save", "Save an authentication profile", {
1344
+ name: z13.string().describe("Profile name"),
1345
+ url: z13.string().optional().describe("Login page URL (--url)"),
1346
+ username: z13.string().optional().describe("Username (--username)"),
1347
+ password: z13.string().optional().describe("Password (--password)"),
1348
+ ...GlobalOptionsSchema
1349
+ }, async (args) => {
1350
+ const { global, rest } = extractGlobalOptions(args);
1351
+ const result = await executor.execute(buildAuthSaveCommand(rest), global);
1352
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1353
+ });
1354
+ server.tool("auth_login", "Login using a saved auth profile", {
1355
+ name: z13.string().describe("Profile name"),
1356
+ ...GlobalOptionsSchema
1357
+ }, async (args) => {
1358
+ const { global, rest } = extractGlobalOptions(args);
1359
+ const result = await executor.execute(buildAuthLoginCommand(rest), global);
1360
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1361
+ });
1362
+ server.tool("auth_list", "List saved auth profiles", { ...GlobalOptionsSchema }, async (args) => {
1363
+ const { global } = extractGlobalOptions(args);
1364
+ const result = await executor.execute(buildAuthListCommand(), global);
1365
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1366
+ });
1367
+ server.tool("auth_show", "Show auth profile metadata", {
1368
+ name: z13.string().describe("Profile name"),
1369
+ ...GlobalOptionsSchema
1370
+ }, async (args) => {
1371
+ const { global, rest } = extractGlobalOptions(args);
1372
+ const result = await executor.execute(buildAuthShowCommand(rest), global);
1373
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1374
+ });
1375
+ server.tool("auth_delete", "Delete a saved auth profile", {
1376
+ name: z13.string().describe("Profile name"),
1377
+ ...GlobalOptionsSchema
1378
+ }, async (args) => {
1379
+ const { global, rest } = extractGlobalOptions(args);
1380
+ const result = await executor.execute(buildAuthDeleteCommand(rest), global);
1381
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1382
+ });
1383
+ }
1384
+
1385
+ // src/tools/batch.ts
1386
+ import { z as z14 } from "zod";
1387
+ function buildBatchCommand(params) {
1388
+ const commands = params.commands.map((c) => `"${c}"`).join(" ");
1389
+ const parts = [`batch ${commands}`];
1390
+ if (params.bail) parts.push("--bail");
1391
+ return parts.join(" ");
1392
+ }
1393
+ function registerBatchTools(server, executor) {
1394
+ server.tool("batch", "Execute multiple browser commands sequentially", {
1395
+ commands: z14.array(z14.string()).describe("Array of agent-browser commands to execute"),
1396
+ bail: z14.boolean().optional().describe("Stop on first error (--bail)"),
1397
+ ...GlobalOptionsSchema
1398
+ }, async (args) => {
1399
+ const { global, rest } = extractGlobalOptions(args);
1400
+ const result = await executor.execute(buildBatchCommand(rest), global);
1401
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1402
+ });
1403
+ }
1404
+
1405
+ // src/tools/sessions.ts
1406
+ import { z as z15 } from "zod";
1407
+ function buildSessionListCommand() {
1408
+ return "session list";
1409
+ }
1410
+ function buildStreamEnableCommand(params) {
1411
+ const parts = ["stream enable"];
1412
+ if (params.port) parts.push(`--port ${params.port}`);
1413
+ return parts.join(" ");
1414
+ }
1415
+ function buildStreamDisableCommand() {
1416
+ return "stream disable";
1417
+ }
1418
+ function buildStreamStatusCommand() {
1419
+ return "stream status";
1420
+ }
1421
+ function registerSessionTools(server, executor) {
1422
+ server.tool("session_list", "List active browser sessions", { ...GlobalOptionsSchema }, async (args) => {
1423
+ const { global } = extractGlobalOptions(args);
1424
+ const result = await executor.execute(buildSessionListCommand(), global);
1425
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1426
+ });
1427
+ server.tool("stream_enable", "Start runtime WebSocket streaming", {
1428
+ port: z15.number().optional().describe("WebSocket streaming port (--port)"),
1429
+ ...GlobalOptionsSchema
1430
+ }, async (args) => {
1431
+ const { global, rest } = extractGlobalOptions(args);
1432
+ const result = await executor.execute(buildStreamEnableCommand(rest), global);
1433
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1434
+ });
1435
+ server.tool("stream_disable", "Stop runtime WebSocket streaming", { ...GlobalOptionsSchema }, async (args) => {
1436
+ const { global } = extractGlobalOptions(args);
1437
+ const result = await executor.execute(buildStreamDisableCommand(), global);
1438
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1439
+ });
1440
+ server.tool("stream_status", "Show streaming status and active port", { ...GlobalOptionsSchema }, async (args) => {
1441
+ const { global } = extractGlobalOptions(args);
1442
+ const result = await executor.execute(buildStreamStatusCommand(), global);
1443
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1444
+ });
1445
+ }
1446
+
1447
+ // src/tools/dialog.ts
1448
+ import { z as z16 } from "zod";
1449
+ function buildDialogAcceptCommand(params) {
1450
+ if (params.text) return `dialog accept ${shellEscape(params.text)}`;
1451
+ return "dialog accept";
1452
+ }
1453
+ function buildDialogDismissCommand() {
1454
+ return "dialog dismiss";
1455
+ }
1456
+ function buildDialogStatusCommand() {
1457
+ return "dialog status";
1458
+ }
1459
+ function registerDialogTools(server, executor) {
1460
+ server.tool("dialog_accept", "Accept a dialog (alert/confirm/prompt)", {
1461
+ text: z16.string().optional().describe("Response text for prompt dialogs"),
1462
+ ...GlobalOptionsSchema
1463
+ }, async (args) => {
1464
+ const { global, rest } = extractGlobalOptions(args);
1465
+ const result = await executor.execute(buildDialogAcceptCommand(rest), global);
1466
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1467
+ });
1468
+ server.tool("dialog_dismiss", "Dismiss a dialog", { ...GlobalOptionsSchema }, async (args) => {
1469
+ const { global } = extractGlobalOptions(args);
1470
+ const result = await executor.execute(buildDialogDismissCommand(), global);
1471
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1472
+ });
1473
+ server.tool("dialog_status", "Check if a dialog is currently open", { ...GlobalOptionsSchema }, async (args) => {
1474
+ const { global } = extractGlobalOptions(args);
1475
+ const result = await executor.execute(buildDialogStatusCommand(), global);
1476
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1477
+ });
1478
+ }
1479
+
1480
+ // src/tools/confirmation.ts
1481
+ import { z as z17 } from "zod";
1482
+ function buildConfirmCommand(params) {
1483
+ return `confirm ${shellEscape(params.id)}`;
1484
+ }
1485
+ function buildDenyCommand(params) {
1486
+ return `deny ${shellEscape(params.id)}`;
1487
+ }
1488
+ function registerConfirmationTools(server, executor) {
1489
+ server.tool("confirm", "Approve a pending confirmation action", {
1490
+ id: z17.string().describe("Confirmation ID to approve"),
1491
+ ...GlobalOptionsSchema
1492
+ }, async (args) => {
1493
+ const { global, rest } = extractGlobalOptions(args);
1494
+ const result = await executor.execute(buildConfirmCommand(rest), global);
1495
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1496
+ });
1497
+ server.tool("deny", "Deny a pending confirmation action", {
1498
+ id: z17.string().describe("Confirmation ID to deny"),
1499
+ ...GlobalOptionsSchema
1500
+ }, async (args) => {
1501
+ const { global, rest } = extractGlobalOptions(args);
1502
+ const result = await executor.execute(buildDenyCommand(rest), global);
1503
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1504
+ });
1505
+ }
1506
+
1507
+ // src/tools/state.ts
1508
+ import { z as z18 } from "zod";
1509
+ function buildStateSaveCommand(params) {
1510
+ return `state save ${shellEscape(params.path)}`;
1511
+ }
1512
+ function buildStateLoadCommand(params) {
1513
+ return `state load ${shellEscape(params.path)}`;
1514
+ }
1515
+ function buildStateListCommand() {
1516
+ return "state list";
1517
+ }
1518
+ function buildStateShowCommand(params) {
1519
+ return `state show ${shellEscape(params.file)}`;
1520
+ }
1521
+ function buildStateRenameCommand(params) {
1522
+ return `state rename ${shellEscape(params.oldName)} ${shellEscape(params.newName)}`;
1523
+ }
1524
+ function buildStateClearCommand(params) {
1525
+ if (params.all) return "state clear --all";
1526
+ if (params.name) return `state clear ${shellEscape(params.name)}`;
1527
+ return "state clear";
1528
+ }
1529
+ function buildStateCleanCommand(params) {
1530
+ const parts = ["state clean"];
1531
+ if (params.olderThan) parts.push(`--older-than ${params.olderThan}`);
1532
+ return parts.join(" ");
1533
+ }
1534
+ function registerStateTools(server, executor) {
1535
+ server.tool("state_save", "Save browser auth state (cookies + storage) to a file", {
1536
+ path: z18.string().describe("Output file path for saved state"),
1537
+ ...GlobalOptionsSchema
1538
+ }, async (args) => {
1539
+ const { global, rest } = extractGlobalOptions(args);
1540
+ const result = await executor.execute(buildStateSaveCommand(rest), global);
1541
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1542
+ });
1543
+ server.tool("state_load", "Load browser auth state from a file", {
1544
+ path: z18.string().describe("State file path to load"),
1545
+ ...GlobalOptionsSchema
1546
+ }, async (args) => {
1547
+ const { global, rest } = extractGlobalOptions(args);
1548
+ const result = await executor.execute(buildStateLoadCommand(rest), global);
1549
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1550
+ });
1551
+ server.tool("state_list", "List saved state files", { ...GlobalOptionsSchema }, async (args) => {
1552
+ const { global } = extractGlobalOptions(args);
1553
+ const result = await executor.execute(buildStateListCommand(), global);
1554
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1555
+ });
1556
+ server.tool("state_show", "Show state file summary", {
1557
+ file: z18.string().describe("State file to inspect"),
1558
+ ...GlobalOptionsSchema
1559
+ }, async (args) => {
1560
+ const { global, rest } = extractGlobalOptions(args);
1561
+ const result = await executor.execute(buildStateShowCommand(rest), global);
1562
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1563
+ });
1564
+ server.tool("state_rename", "Rename a state file", {
1565
+ oldName: z18.string().describe("Current state file name"),
1566
+ newName: z18.string().describe("New state file name"),
1567
+ ...GlobalOptionsSchema
1568
+ }, async (args) => {
1569
+ const { global, rest } = extractGlobalOptions(args);
1570
+ const result = await executor.execute(buildStateRenameCommand(rest), global);
1571
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1572
+ });
1573
+ server.tool("state_clear", "Clear saved states", {
1574
+ name: z18.string().optional().describe("Session name to clear (omit for current session)"),
1575
+ all: z18.boolean().optional().describe("Clear all saved states (--all)"),
1576
+ ...GlobalOptionsSchema
1577
+ }, async (args) => {
1578
+ const { global, rest } = extractGlobalOptions(args);
1579
+ const result = await executor.execute(buildStateClearCommand(rest), global);
1580
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1581
+ });
1582
+ server.tool("state_clean", "Delete old state files", {
1583
+ olderThan: z18.number().optional().describe("Delete states older than N days (--older-than)"),
1584
+ ...GlobalOptionsSchema
1585
+ }, async (args) => {
1586
+ const { global, rest } = extractGlobalOptions(args);
1587
+ const result = await executor.execute(buildStateCleanCommand(rest), global);
1588
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1589
+ });
1590
+ }
1591
+
1592
+ // src/tools/dashboard.ts
1593
+ import { z as z19 } from "zod";
1594
+ function buildDashboardStartCommand(params) {
1595
+ const parts = ["dashboard start"];
1596
+ if (params.port) parts.push(`--port ${params.port}`);
1597
+ return parts.join(" ");
1598
+ }
1599
+ function buildDashboardStopCommand() {
1600
+ return "dashboard stop";
1601
+ }
1602
+ function registerDashboardTools(server, executor) {
1603
+ server.tool("dashboard_start", "Start the observability dashboard server", {
1604
+ port: z19.number().optional().describe("Dashboard port (default: 4848) (--port)"),
1605
+ ...GlobalOptionsSchema
1606
+ }, async (args) => {
1607
+ const { global, rest } = extractGlobalOptions(args);
1608
+ const result = await executor.execute(buildDashboardStartCommand(rest), global);
1609
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1610
+ });
1611
+ server.tool("dashboard_stop", "Stop the dashboard server", { ...GlobalOptionsSchema }, async (args) => {
1612
+ const { global } = extractGlobalOptions(args);
1613
+ const result = await executor.execute(buildDashboardStopCommand(), global);
1614
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1615
+ });
1616
+ }
1617
+
1618
+ // src/tools/react.ts
1619
+ import { z as z20 } from "zod";
1620
+ function buildReactTreeCommand() {
1621
+ return "react tree";
1622
+ }
1623
+ function buildReactInspectCommand(params) {
1624
+ return `react inspect ${shellEscape(params.fiberId)}`;
1625
+ }
1626
+ function buildReactRendersCommand(params) {
1627
+ return `react renders ${params.action}`;
1628
+ }
1629
+ function buildReactSuspenseCommand(params) {
1630
+ const parts = ["react suspense"];
1631
+ if (params.onlyDynamic) parts.push("--only-dynamic");
1632
+ return parts.join(" ");
1633
+ }
1634
+ function registerReactTools(server, executor) {
1635
+ server.tool("react_tree", "Show full React component tree (requires --enable react-devtools)", { ...GlobalOptionsSchema }, async (args) => {
1636
+ const { global } = extractGlobalOptions(args);
1637
+ const result = await executor.execute(buildReactTreeCommand(), global);
1638
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1639
+ });
1640
+ server.tool("react_inspect", "Inspect a single React component by fiber ID", {
1641
+ fiberId: z20.string().describe("React fiber ID to inspect"),
1642
+ ...GlobalOptionsSchema
1643
+ }, async (args) => {
1644
+ const { global, rest } = extractGlobalOptions(args);
1645
+ const result = await executor.execute(buildReactInspectCommand(rest), global);
1646
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1647
+ });
1648
+ server.tool("react_renders", "Start or stop React fiber render recording", {
1649
+ action: z20.enum(["start", "stop"]).describe("Start or stop render recording"),
1650
+ ...GlobalOptionsSchema
1651
+ }, async (args) => {
1652
+ const { global, rest } = extractGlobalOptions(args);
1653
+ const result = await executor.execute(buildReactRendersCommand(rest), global);
1654
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1655
+ });
1656
+ server.tool("react_suspense", "List React Suspense boundaries", {
1657
+ onlyDynamic: z20.boolean().optional().describe("Hide static boundaries (--only-dynamic)"),
1658
+ ...GlobalOptionsSchema
1659
+ }, async (args) => {
1660
+ const { global, rest } = extractGlobalOptions(args);
1661
+ const result = await executor.execute(buildReactSuspenseCommand(rest), global);
1662
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1663
+ });
1664
+ }
1665
+
1666
+ // src/tools/misc.ts
1667
+ import { z as z21 } from "zod";
1668
+ function buildDoctorCommand(params) {
1669
+ const parts = ["doctor"];
1670
+ if (params.fix) parts.push("--fix");
1671
+ return parts.join(" ");
1672
+ }
1673
+ function buildChatCommand(params) {
1674
+ const parts = ["chat"];
1675
+ if (params.message) parts.push(shellEscape(params.message));
1676
+ if (params.model) parts.push(`--model ${shellEscape(params.model)}`);
1677
+ return parts.join(" ");
1678
+ }
1679
+ function buildPushstateCommand(params) {
1680
+ return `pushstate ${shellEscape(params.url)}`;
1681
+ }
1682
+ function buildProfilesCommand() {
1683
+ return "profiles";
1684
+ }
1685
+ function buildSessionCommand() {
1686
+ return "session";
1687
+ }
1688
+ function buildVitalsCommand(params) {
1689
+ const parts = ["vitals"];
1690
+ if (params.url) parts.push(shellEscape(params.url));
1691
+ return parts.join(" ");
1692
+ }
1693
+ function buildAddinitscriptCommand(params) {
1694
+ return `addinitscript ${shellEscape(params.script)}`;
1695
+ }
1696
+ function buildRemoveinitscriptCommand(params) {
1697
+ return `removeinitscript ${shellEscape(params.identifier)}`;
1698
+ }
1699
+ function registerMiscTools(server, executor) {
1700
+ server.tool("doctor", "Diagnose agent-browser installation and configuration", {
1701
+ fix: z21.boolean().optional().describe("Auto-fix issues (--fix)"),
1702
+ ...GlobalOptionsSchema
1703
+ }, async (args) => {
1704
+ const { global, rest } = extractGlobalOptions(args);
1705
+ const result = await executor.execute(buildDoctorCommand(rest), global);
1706
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1707
+ });
1708
+ server.tool("chat", "Send a natural language instruction to the AI agent", {
1709
+ message: z21.string().describe("Natural language instruction"),
1710
+ model: z21.string().optional().describe("AI model name (--model)"),
1711
+ ...GlobalOptionsSchema
1712
+ }, async (args) => {
1713
+ const { global, rest } = extractGlobalOptions(args);
1714
+ const result = await executor.execute(buildChatCommand(rest), global);
1715
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1716
+ });
1717
+ server.tool("pushstate", "SPA client-side navigation via history.pushState", {
1718
+ url: z21.string().describe("URL to push to browser history"),
1719
+ ...GlobalOptionsSchema
1720
+ }, async (args) => {
1721
+ const { global, rest } = extractGlobalOptions(args);
1722
+ const result = await executor.execute(buildPushstateCommand(rest), global);
1723
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1724
+ });
1725
+ server.tool("profiles", "List available Chrome profiles", { ...GlobalOptionsSchema }, async (args) => {
1726
+ const { global } = extractGlobalOptions(args);
1727
+ const result = await executor.execute(buildProfilesCommand(), global);
1728
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1729
+ });
1730
+ server.tool("session", "Show current session name", { ...GlobalOptionsSchema }, async (args) => {
1731
+ const { global } = extractGlobalOptions(args);
1732
+ const result = await executor.execute(buildSessionCommand(), global);
1733
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1734
+ });
1735
+ server.tool("vitals", "Measure Web Vitals (LCP/CLS/TTFB/FCP/INP)", {
1736
+ url: z21.string().optional().describe("URL to measure (optional, uses current page)"),
1737
+ ...GlobalOptionsSchema
1738
+ }, async (args) => {
1739
+ const { global, rest } = extractGlobalOptions(args);
1740
+ const result = await executor.execute(buildVitalsCommand(rest), global);
1741
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1742
+ });
1743
+ server.tool("addinitscript", "Register an init script at runtime", {
1744
+ script: z21.string().describe("JavaScript code for the init script"),
1745
+ ...GlobalOptionsSchema
1746
+ }, async (args) => {
1747
+ const { global, rest } = extractGlobalOptions(args);
1748
+ const result = await executor.execute(buildAddinitscriptCommand(rest), global);
1749
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1750
+ });
1751
+ server.tool("removeinitscript", "Remove a previously registered init script", {
1752
+ identifier: z21.string().describe("Init script identifier to remove"),
1753
+ ...GlobalOptionsSchema
1754
+ }, async (args) => {
1755
+ const { global, rest } = extractGlobalOptions(args);
1756
+ const result = await executor.execute(buildRemoveinitscriptCommand(rest), global);
1757
+ return { content: [{ type: "text", text: result.stdout || "OK" }], ...result.error ? { isError: true } : {} };
1758
+ });
1759
+ }
1760
+
1761
+ // src/tools/index.ts
1762
+ function registerAllTools(server, executor) {
1763
+ registerNavigationTools(server, executor);
1764
+ registerInteractionTools(server, executor);
1765
+ registerQueryTools(server, executor);
1766
+ registerVisualTools(server, executor);
1767
+ registerMouseTools(server, executor);
1768
+ registerKeyboardTools(server, executor);
1769
+ registerBrowserSettingsTools(server, executor);
1770
+ registerNetworkTools(server, executor);
1771
+ registerStorageTools(server, executor);
1772
+ registerTabTools(server, executor);
1773
+ registerDebugTools(server, executor);
1774
+ registerAuthTools(server, executor);
1775
+ registerBatchTools(server, executor);
1776
+ registerSessionTools(server, executor);
1777
+ registerDialogTools(server, executor);
1778
+ registerConfirmationTools(server, executor);
1779
+ registerStateTools(server, executor);
1780
+ registerDashboardTools(server, executor);
1781
+ registerReactTools(server, executor);
1782
+ registerMiscTools(server, executor);
1783
+ }
1784
+
1785
+ // src/server.ts
1786
+ function createMcpServerWithTools(executor) {
1787
+ const server = new McpServer(
1788
+ { name: "agent-browser", version: "0.1.0" },
1789
+ { capabilities: { tools: {} } }
1790
+ );
1791
+ registerAllTools(server, executor);
1792
+ return server;
1793
+ }
1794
+ async function startServer(port, executor) {
1795
+ const cliExecutor = executor ?? new CliExecutor();
1796
+ const sessions = /* @__PURE__ */ new Map();
1797
+ const httpServer = createServer(async (req, res) => {
1798
+ const url = new URL(req.url ?? "/", `http://localhost:${port}`);
1799
+ if (url.pathname !== "/mcp") {
1800
+ res.writeHead(404, { "Content-Type": "application/json" });
1801
+ res.end(JSON.stringify({ error: "Not found. Use POST /mcp for MCP requests." }));
1802
+ return;
1803
+ }
1804
+ try {
1805
+ const sessionId = req.headers["mcp-session-id"];
1806
+ if (sessionId && sessions.has(sessionId)) {
1807
+ const session = sessions.get(sessionId);
1808
+ if (req.method === "POST") {
1809
+ const body = await getRequestBody(req);
1810
+ await session.transport.handleRequest(req, res, body);
1811
+ } else {
1812
+ await session.transport.handleRequest(req, res);
1813
+ }
1814
+ } else if (req.method === "POST") {
1815
+ let newSessionId;
1816
+ const transport = new StreamableHTTPServerTransport({
1817
+ sessionIdGenerator: () => {
1818
+ const id = randomUUID();
1819
+ newSessionId = id;
1820
+ return id;
1821
+ }
1822
+ });
1823
+ const server = createMcpServerWithTools(cliExecutor);
1824
+ await server.connect(transport);
1825
+ const body = await getRequestBody(req);
1826
+ await transport.handleRequest(req, res, body);
1827
+ if (newSessionId) {
1828
+ sessions.set(newSessionId, { transport, server });
1829
+ }
1830
+ transport.onclose = () => {
1831
+ if (newSessionId) {
1832
+ sessions.delete(newSessionId);
1833
+ }
1834
+ };
1835
+ } else if (req.method === "GET") {
1836
+ res.writeHead(400, { "Content-Type": "application/json" });
1837
+ res.end(JSON.stringify({ error: "Valid session ID required for GET requests" }));
1838
+ } else if (req.method === "DELETE") {
1839
+ res.writeHead(200);
1840
+ res.end();
1841
+ }
1842
+ } catch (error) {
1843
+ const errMsg = error instanceof Error ? `${error.message}
1844
+ ${error.stack}` : String(error);
1845
+ console.error("[MCP] Request handling error:", errMsg);
1846
+ if (!res.headersSent) {
1847
+ res.writeHead(500, { "Content-Type": "text/plain" });
1848
+ res.end(errMsg);
1849
+ }
1850
+ }
1851
+ });
1852
+ const close = async () => {
1853
+ await cliExecutor.close();
1854
+ for (const [, session] of sessions) {
1855
+ await session.transport.close();
1856
+ }
1857
+ sessions.clear();
1858
+ httpServer.close();
1859
+ };
1860
+ return new Promise((resolve) => {
1861
+ httpServer.listen(port, () => {
1862
+ resolve({ httpServer, executor: cliExecutor, close });
1863
+ });
1864
+ });
1865
+ }
1866
+
1867
+ // src/index.ts
1868
+ var DEFAULT_PORT = 12347;
1869
+ function parsePort() {
1870
+ const args = process.argv.slice(2);
1871
+ const portIndex = args.indexOf("--port");
1872
+ if (portIndex !== -1 && args[portIndex + 1]) {
1873
+ const port = parseInt(args[portIndex + 1], 10);
1874
+ if (!isNaN(port) && port > 0 && port < 65536) return port;
1875
+ console.error(`Invalid port: ${args[portIndex + 1]}`);
1876
+ process.exit(1);
1877
+ }
1878
+ const envPort = process.env.PORT;
1879
+ if (envPort) {
1880
+ const port = parseInt(envPort, 10);
1881
+ if (!isNaN(port) && port > 0 && port < 65536) return port;
1882
+ }
1883
+ return DEFAULT_PORT;
1884
+ }
1885
+ async function main() {
1886
+ const port = parsePort();
1887
+ const instance = await startServer(port);
1888
+ console.log(`Agent Browser MCP server running on http://localhost:${port}/mcp`);
1889
+ const shutdown = async () => {
1890
+ console.log("\nShutting down...");
1891
+ await instance.close();
1892
+ process.exit(0);
1893
+ };
1894
+ process.on("SIGINT", shutdown);
1895
+ process.on("SIGTERM", shutdown);
1896
+ }
1897
+ main().catch((err) => {
1898
+ console.error("Failed to start server:", err);
1899
+ process.exit(1);
1900
+ });
1901
+ //# sourceMappingURL=index.js.map