@_nazmiforreal/agent-browser-mcp 0.2.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.
Files changed (49) hide show
  1. package/.mcp.json +12 -0
  2. package/AGENTS.md +100 -0
  3. package/README.md +502 -0
  4. package/dist/browsers/discover.d.ts +13 -0
  5. package/dist/browsers/discover.d.ts.map +1 -0
  6. package/dist/browsers/discover.js +54 -0
  7. package/dist/browsers/discover.js.map +1 -0
  8. package/dist/browsers/env.d.ts +10 -0
  9. package/dist/browsers/env.d.ts.map +1 -0
  10. package/dist/browsers/env.js +72 -0
  11. package/dist/browsers/env.js.map +1 -0
  12. package/dist/browsers/index.d.ts +5 -0
  13. package/dist/browsers/index.d.ts.map +1 -0
  14. package/dist/browsers/index.js +5 -0
  15. package/dist/browsers/index.js.map +1 -0
  16. package/dist/browsers/installer.d.ts +13 -0
  17. package/dist/browsers/installer.d.ts.map +1 -0
  18. package/dist/browsers/installer.js +59 -0
  19. package/dist/browsers/installer.js.map +1 -0
  20. package/dist/browsers/registry.d.ts +14 -0
  21. package/dist/browsers/registry.d.ts.map +1 -0
  22. package/dist/browsers/registry.js +119 -0
  23. package/dist/browsers/registry.js.map +1 -0
  24. package/dist/cli.d.ts +3 -0
  25. package/dist/cli.d.ts.map +1 -0
  26. package/dist/cli.js +153 -0
  27. package/dist/cli.js.map +1 -0
  28. package/dist/index.d.ts +3 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +25 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/tools/browser.d.ts +3 -0
  33. package/dist/tools/browser.d.ts.map +1 -0
  34. package/dist/tools/browser.js +885 -0
  35. package/dist/tools/browser.js.map +1 -0
  36. package/dist/tools/executor.d.ts +9 -0
  37. package/dist/tools/executor.d.ts.map +1 -0
  38. package/dist/tools/executor.js +1067 -0
  39. package/dist/tools/executor.js.map +1 -0
  40. package/dist/tools/index.d.ts +3 -0
  41. package/dist/tools/index.d.ts.map +1 -0
  42. package/dist/tools/index.js +3 -0
  43. package/dist/tools/index.js.map +1 -0
  44. package/package.json +60 -0
  45. package/tests/browser-tools.test.ts +329 -0
  46. package/tests/executor.test.ts +356 -0
  47. package/tests/integration.test.ts +467 -0
  48. package/tests/server.test.ts +224 -0
  49. package/vitest.config.ts +15 -0
@@ -0,0 +1,1067 @@
1
+ import { spawn } from "child_process";
2
+ import { discoverActiveBrowser } from "../browsers/discover.js";
3
+ const AGENT_BROWSER_PATH = process.env.AGENT_BROWSER_PATH || "agent-browser";
4
+ let cachedBrowserPath = undefined;
5
+ function getExecutablePath() {
6
+ if (cachedBrowserPath !== undefined)
7
+ return cachedBrowserPath;
8
+ const envPath = process.env.AGENT_BROWSER_EXECUTABLE_PATH;
9
+ if (envPath) {
10
+ cachedBrowserPath = envPath;
11
+ return envPath;
12
+ }
13
+ const active = discoverActiveBrowser();
14
+ if (active) {
15
+ cachedBrowserPath = active.path;
16
+ process.env.AGENT_BROWSER_EXECUTABLE_PATH = active.path;
17
+ return active.path;
18
+ }
19
+ cachedBrowserPath = null;
20
+ return null;
21
+ }
22
+ /**
23
+ * Command mapping from MCP tool names to agent-browser CLI commands.
24
+ * The agent-browser CLI uses positional arguments.
25
+ */
26
+ const COMMAND_MAP = {
27
+ // Navigation
28
+ navigate: "open",
29
+ goto: "goto",
30
+ pushstate: "pushstate",
31
+ go_back: "back",
32
+ go_forward: "forward",
33
+ reload: "reload",
34
+ // Core Actions
35
+ click: "click",
36
+ dblclick: "dblclick",
37
+ fill: "fill",
38
+ type: "type",
39
+ hover: "hover",
40
+ focus: "focus",
41
+ check: "check",
42
+ uncheck: "uncheck",
43
+ select: "select",
44
+ drag: "drag",
45
+ upload: "upload",
46
+ download: "download",
47
+ tap: "tap",
48
+ swipe: "swipe",
49
+ // Keyboard
50
+ press: "press",
51
+ keydown: "keydown",
52
+ keyup: "keyup",
53
+ keyboard_type: "keyboard type",
54
+ keyboard_inserttext: "keyboard inserttext",
55
+ // Mouse
56
+ mouse_move: "mouse move",
57
+ mouse_down: "mouse down",
58
+ mouse_up: "mouse up",
59
+ mouse_wheel: "mouse wheel",
60
+ // Scroll
61
+ scroll: "scroll",
62
+ scroll_into_view: "scrollintoview",
63
+ // Get Info
64
+ get_text: "get text",
65
+ get_html: "get html",
66
+ get_value: "get value",
67
+ get_attribute: "get attr",
68
+ get_url: "get url",
69
+ get_title: "get title",
70
+ get_cdp_url: "get cdp-url",
71
+ get_count: "get count",
72
+ get_bounding_box: "get box",
73
+ get_styles: "get styles",
74
+ // State Checks
75
+ is_visible: "is visible",
76
+ is_enabled: "is enabled",
77
+ is_checked: "is checked",
78
+ // Find (Locators)
79
+ find_role: "find role",
80
+ find_text: "find text",
81
+ find_label: "find label",
82
+ find_placeholder: "find placeholder",
83
+ find_alt: "find alt",
84
+ find_title: "find title",
85
+ find_testid: "find testid",
86
+ find_first: "find first",
87
+ find_last: "find last",
88
+ find_nth: "find nth",
89
+ // Wait
90
+ wait: "wait",
91
+ wait_for_selector: "wait",
92
+ wait_for_url: "wait",
93
+ wait_for_load_state: "wait",
94
+ wait_for_function: "wait",
95
+ wait_for_text: "wait",
96
+ wait_for_download: "wait",
97
+ // Screenshot/PDF
98
+ screenshot: "screenshot",
99
+ pdf: "pdf",
100
+ // Snapshot
101
+ snapshot: "snapshot",
102
+ // Eval
103
+ evaluate: "eval",
104
+ evaluate_base64: "eval -b",
105
+ // Batch
106
+ batch: "batch",
107
+ // Clipboard
108
+ clipboard_read: "clipboard read",
109
+ clipboard_write: "clipboard write",
110
+ clipboard_copy: "clipboard copy",
111
+ clipboard_paste: "clipboard paste",
112
+ // Settings
113
+ set_viewport: "set viewport",
114
+ set_device: "set device",
115
+ set_geolocation: "set geo",
116
+ set_offline: "set offline",
117
+ set_headers: "set headers",
118
+ set_credentials: "set credentials",
119
+ set_media: "set media",
120
+ // Cookies
121
+ get_cookies: "cookies",
122
+ set_cookie: "cookies set",
123
+ set_cookies_from_file: "cookies set --curl",
124
+ clear_cookies: "cookies clear",
125
+ // Storage
126
+ storage_get_local: "storage local get",
127
+ storage_get_session: "storage session get",
128
+ storage_set_local: "storage local set",
129
+ storage_set_session: "storage session set",
130
+ storage_clear_local: "storage local clear",
131
+ storage_clear_session: "storage session clear",
132
+ // Network
133
+ network_route: "network route",
134
+ network_unroute: "network unroute",
135
+ network_requests: "network requests",
136
+ network_request_detail: "network request",
137
+ network_har_start: "network har start",
138
+ network_har_stop: "network har stop",
139
+ // Tabs
140
+ tab_list: "tab list",
141
+ tab_new: "tab new",
142
+ tab_switch: "tab",
143
+ tab_close: "tab close",
144
+ window_new: "window new",
145
+ // Frames
146
+ frame_switch: "frame",
147
+ frame_main: "frame main",
148
+ // Dialogs
149
+ dialog_accept: "dialog accept",
150
+ dialog_dismiss: "dialog dismiss",
151
+ dialog_status: "dialog status",
152
+ // Debug
153
+ trace_start: "trace start",
154
+ trace_stop: "trace stop",
155
+ profiler_start: "profiler start",
156
+ profiler_stop: "profiler stop",
157
+ get_console: "console",
158
+ get_errors: "errors",
159
+ highlight: "highlight",
160
+ inspect: "inspect",
161
+ // State Management
162
+ state_save: "state save",
163
+ state_load: "state load",
164
+ state_list: "state list",
165
+ state_show: "state show",
166
+ state_rename: "state rename",
167
+ state_clear: "state clear",
168
+ state_clean: "state clean",
169
+ // Recording
170
+ record_start: "record start",
171
+ record_stop: "record stop",
172
+ record_restart: "record restart",
173
+ // Auth Vault
174
+ auth_save: "auth save",
175
+ auth_login: "auth login",
176
+ auth_list: "auth list",
177
+ auth_delete: "auth delete",
178
+ auth_show: "auth show",
179
+ // Diff
180
+ diff_snapshot: "diff snapshot",
181
+ diff_screenshot: "diff screenshot",
182
+ diff_url: "diff url",
183
+ // React
184
+ react_tree: "react tree",
185
+ react_inspect: "react inspect",
186
+ react_renders_start: "react renders start",
187
+ react_renders_stop: "react renders stop",
188
+ react_suspense: "react suspense",
189
+ // Vitals
190
+ vitals: "vitals",
191
+ // Init Scripts
192
+ remove_init_script: "removeinitscript",
193
+ // Session
194
+ session_show: "session",
195
+ session_list: "session list",
196
+ // Streaming
197
+ stream_enable: "stream enable",
198
+ stream_disable: "stream disable",
199
+ stream_status: "stream status",
200
+ // Dashboard
201
+ dashboard_start: "dashboard start",
202
+ dashboard_stop: "dashboard stop",
203
+ // iOS
204
+ device_list: "device list",
205
+ // Confirm/Deny
206
+ confirm_action: "confirm",
207
+ deny_action: "deny",
208
+ // Connect CDP
209
+ connect: "connect",
210
+ // Session management (MCP-specific)
211
+ close_session: "close",
212
+ new_session: "session",
213
+ // Legacy/compat aliases
214
+ set_cookies: "cookies set",
215
+ wait_for_navigation: "wait",
216
+ get_network: "network requests",
217
+ };
218
+ /**
219
+ * Helper to check if a value is defined and non-empty for required args.
220
+ */
221
+ function isDefined(value) {
222
+ return value !== undefined && value !== null && value !== "";
223
+ }
224
+ /**
225
+ * Build positional arguments for each command based on agent-browser CLI syntax.
226
+ */
227
+ function buildPositionalArgs(command, options) {
228
+ const args = [];
229
+ switch (command) {
230
+ // Navigation: open <url>
231
+ case "navigate":
232
+ case "goto":
233
+ if (isDefined(options.url))
234
+ args.push(String(options.url));
235
+ break;
236
+ case "pushstate":
237
+ if (isDefined(options.url))
238
+ args.push(String(options.url));
239
+ break;
240
+ // Simple selector commands
241
+ case "click":
242
+ case "dblclick":
243
+ case "hover":
244
+ case "focus":
245
+ case "check":
246
+ case "uncheck":
247
+ case "tap":
248
+ case "highlight":
249
+ if (isDefined(options.selector))
250
+ args.push(String(options.selector));
251
+ break;
252
+ // Selector + value
253
+ case "fill":
254
+ if (isDefined(options.selector))
255
+ args.push(String(options.selector));
256
+ if (options.value !== undefined && options.value !== null) {
257
+ args.push(String(options.value));
258
+ }
259
+ break;
260
+ case "type":
261
+ if (isDefined(options.selector))
262
+ args.push(String(options.selector));
263
+ if (options.text !== undefined && options.text !== null) {
264
+ args.push(String(options.text));
265
+ }
266
+ break;
267
+ // Press: press <key>
268
+ case "press":
269
+ case "keydown":
270
+ case "keyup":
271
+ if (isDefined(options.key))
272
+ args.push(String(options.key));
273
+ break;
274
+ // Keyboard subactions
275
+ case "keyboard_type":
276
+ if (options.text !== undefined && options.text !== null) {
277
+ args.push(String(options.text));
278
+ }
279
+ break;
280
+ case "keyboard_inserttext":
281
+ if (options.text !== undefined && options.text !== null) {
282
+ args.push(String(options.text));
283
+ }
284
+ break;
285
+ // Scroll: scroll [direction] [amount] [--selector]
286
+ case "scroll":
287
+ if (isDefined(options.direction))
288
+ args.push(String(options.direction));
289
+ if (options.amount !== undefined && options.amount !== null) {
290
+ args.push(String(options.amount));
291
+ }
292
+ break;
293
+ case "scroll_into_view":
294
+ if (isDefined(options.selector))
295
+ args.push(String(options.selector));
296
+ break;
297
+ // Select: select <selector> <values...>
298
+ case "select":
299
+ if (isDefined(options.selector))
300
+ args.push(String(options.selector));
301
+ if (Array.isArray(options.values)) {
302
+ for (const v of options.values) {
303
+ if (isDefined(v))
304
+ args.push(String(v));
305
+ }
306
+ }
307
+ else if (isDefined(options.value)) {
308
+ args.push(String(options.value));
309
+ }
310
+ break;
311
+ // Drag: drag <source> <target>
312
+ case "drag":
313
+ if (isDefined(options.source))
314
+ args.push(String(options.source));
315
+ if (isDefined(options.target))
316
+ args.push(String(options.target));
317
+ break;
318
+ // Upload: upload <selector> <files...>
319
+ case "upload":
320
+ if (isDefined(options.selector))
321
+ args.push(String(options.selector));
322
+ if (Array.isArray(options.files)) {
323
+ for (const f of options.files) {
324
+ if (isDefined(f))
325
+ args.push(String(f));
326
+ }
327
+ }
328
+ else if (isDefined(options.file)) {
329
+ args.push(String(options.file));
330
+ }
331
+ break;
332
+ // Download: download <selector> <path>
333
+ case "download":
334
+ if (isDefined(options.selector))
335
+ args.push(String(options.selector));
336
+ if (isDefined(options.path))
337
+ args.push(String(options.path));
338
+ break;
339
+ // Swipe: swipe <direction> [distance]
340
+ case "swipe":
341
+ if (isDefined(options.direction))
342
+ args.push(String(options.direction));
343
+ if (options.distance !== undefined && options.distance !== null) {
344
+ args.push(String(options.distance));
345
+ }
346
+ break;
347
+ // Mouse subcommands
348
+ case "mouse_move":
349
+ if (options.x !== undefined && options.x !== null)
350
+ args.push(String(options.x));
351
+ if (options.y !== undefined && options.y !== null)
352
+ args.push(String(options.y));
353
+ break;
354
+ case "mouse_down":
355
+ case "mouse_up":
356
+ if (isDefined(options.button))
357
+ args.push(String(options.button));
358
+ break;
359
+ case "mouse_wheel":
360
+ if (options.deltaY !== undefined && options.deltaY !== null) {
361
+ args.push(String(options.deltaY));
362
+ }
363
+ if (options.deltaX !== undefined && options.deltaX !== null) {
364
+ args.push(String(options.deltaX));
365
+ }
366
+ break;
367
+ // Get text/html/value: get text|html|value <selector>
368
+ case "get_text":
369
+ case "get_html":
370
+ case "get_value":
371
+ case "get_count":
372
+ case "get_bounding_box":
373
+ case "get_styles":
374
+ if (isDefined(options.selector))
375
+ args.push(String(options.selector));
376
+ break;
377
+ // Get attribute: get attr <selector> <name>
378
+ case "get_attribute":
379
+ if (isDefined(options.selector))
380
+ args.push(String(options.selector));
381
+ if (isDefined(options.attribute))
382
+ args.push(String(options.attribute));
383
+ break;
384
+ // Is visible/enabled/checked: is <state> <selector>
385
+ case "is_visible":
386
+ case "is_enabled":
387
+ case "is_checked":
388
+ if (isDefined(options.selector))
389
+ args.push(String(options.selector));
390
+ break;
391
+ // Find locators: find <type> <value> [action] [--name] [--exact]
392
+ case "find_role":
393
+ case "find_text":
394
+ case "find_label":
395
+ case "find_placeholder":
396
+ case "find_alt":
397
+ case "find_title":
398
+ case "find_testid":
399
+ case "find_first":
400
+ case "find_last":
401
+ if (isDefined(options.value))
402
+ args.push(String(options.value));
403
+ if (isDefined(options.subaction))
404
+ args.push(String(options.subaction));
405
+ if (command === "find_role" && isDefined(options.name)) {
406
+ args.push("--name", String(options.name));
407
+ }
408
+ if (options.exact)
409
+ args.push("--exact");
410
+ break;
411
+ case "find_nth":
412
+ if (options.index !== undefined && options.index !== null) {
413
+ args.push(String(options.index));
414
+ }
415
+ if (isDefined(options.selector))
416
+ args.push(String(options.selector));
417
+ if (isDefined(options.subaction))
418
+ args.push(String(options.subaction));
419
+ break;
420
+ // Wait (default: selector or ms)
421
+ case "wait":
422
+ if (isDefined(options.target))
423
+ args.push(String(options.target));
424
+ break;
425
+ case "wait_for_selector":
426
+ if (isDefined(options.selector))
427
+ args.push(String(options.selector));
428
+ break;
429
+ // Screenshot: screenshot [selector] [path] [--full]
430
+ case "screenshot":
431
+ if (isDefined(options.selector))
432
+ args.push(String(options.selector));
433
+ if (isDefined(options.path))
434
+ args.push(String(options.path));
435
+ break;
436
+ // PDF: pdf <path>
437
+ case "pdf":
438
+ if (isDefined(options.path))
439
+ args.push(String(options.path));
440
+ break;
441
+ // Eval: eval <script>
442
+ case "evaluate":
443
+ if (isDefined(options.script))
444
+ args.push(String(options.script));
445
+ break;
446
+ case "evaluate_base64":
447
+ if (isDefined(options.script))
448
+ args.push(String(options.script));
449
+ break;
450
+ // Batch: batch [--bail] <commands...>
451
+ case "batch":
452
+ if (Array.isArray(options.commands)) {
453
+ for (const c of options.commands) {
454
+ if (isDefined(c))
455
+ args.push(String(c));
456
+ }
457
+ }
458
+ break;
459
+ // Clipboard write: clipboard write <text>
460
+ case "clipboard_write":
461
+ if (options.text !== undefined && options.text !== null) {
462
+ args.push(String(options.text));
463
+ }
464
+ break;
465
+ // Settings
466
+ case "set_viewport":
467
+ if (options.width !== undefined && options.width !== null)
468
+ args.push(String(options.width));
469
+ if (options.height !== undefined && options.height !== null)
470
+ args.push(String(options.height));
471
+ if (options.scale !== undefined && options.scale !== null)
472
+ args.push(String(options.scale));
473
+ break;
474
+ case "set_device":
475
+ if (isDefined(options.device))
476
+ args.push(String(options.device));
477
+ break;
478
+ case "set_geolocation":
479
+ if (options.latitude !== undefined && options.latitude !== null)
480
+ args.push(String(options.latitude));
481
+ if (options.longitude !== undefined && options.longitude !== null)
482
+ args.push(String(options.longitude));
483
+ break;
484
+ case "set_offline":
485
+ if (options.offline !== undefined && options.offline !== null) {
486
+ args.push(options.offline ? "on" : "off");
487
+ }
488
+ break;
489
+ case "set_headers":
490
+ if (isDefined(options.headers))
491
+ args.push(String(options.headers));
492
+ break;
493
+ case "set_credentials":
494
+ if (isDefined(options.username))
495
+ args.push(String(options.username));
496
+ if (isDefined(options.password))
497
+ args.push(String(options.password));
498
+ break;
499
+ case "set_media":
500
+ if (isDefined(options.colorScheme))
501
+ args.push(String(options.colorScheme));
502
+ if (options.reducedMotion)
503
+ args.push("reduced-motion");
504
+ break;
505
+ // Cookies
506
+ case "set_cookie":
507
+ if (isDefined(options.name))
508
+ args.push(String(options.name));
509
+ if (options.value !== undefined && options.value !== null) {
510
+ args.push(String(options.value));
511
+ }
512
+ break;
513
+ case "set_cookies":
514
+ if (Array.isArray(options.cookies) && options.cookies.length > 0) {
515
+ args.push(String(options.cookies[0].name));
516
+ args.push(String(options.cookies[0].value));
517
+ }
518
+ break;
519
+ case "set_cookies_from_file":
520
+ if (isDefined(options.file))
521
+ args.push(String(options.file));
522
+ break;
523
+ // Storage
524
+ case "storage_set_local":
525
+ case "storage_set_session":
526
+ if (isDefined(options.key))
527
+ args.push(String(options.key));
528
+ if (options.value !== undefined && options.value !== null) {
529
+ args.push(String(options.value));
530
+ }
531
+ break;
532
+ case "storage_get_local":
533
+ case "storage_get_session":
534
+ if (isDefined(options.key))
535
+ args.push(String(options.key));
536
+ break;
537
+ // Network
538
+ case "network_route":
539
+ if (isDefined(options.url))
540
+ args.push(String(options.url));
541
+ break;
542
+ case "network_unroute":
543
+ if (isDefined(options.url))
544
+ args.push(String(options.url));
545
+ break;
546
+ case "network_request_detail":
547
+ if (isDefined(options.requestId))
548
+ args.push(String(options.requestId));
549
+ break;
550
+ case "network_har_stop":
551
+ if (isDefined(options.path))
552
+ args.push(String(options.path));
553
+ break;
554
+ // Tabs
555
+ case "tab_new":
556
+ if (isDefined(options.url))
557
+ args.push(String(options.url));
558
+ break;
559
+ case "tab_switch":
560
+ if (isDefined(options.tabId))
561
+ args.push(String(options.tabId));
562
+ break;
563
+ case "tab_close":
564
+ if (isDefined(options.tabId))
565
+ args.push(String(options.tabId));
566
+ break;
567
+ // Frames
568
+ case "frame_switch":
569
+ if (isDefined(options.selector))
570
+ args.push(String(options.selector));
571
+ break;
572
+ // Dialogs
573
+ case "dialog_accept":
574
+ case "dialog_dismiss":
575
+ if (isDefined(options.promptText))
576
+ args.push(String(options.promptText));
577
+ break;
578
+ // Debug
579
+ case "trace_stop":
580
+ case "profiler_stop":
581
+ if (isDefined(options.path))
582
+ args.push(String(options.path));
583
+ break;
584
+ // State Management
585
+ case "state_save":
586
+ case "state_load":
587
+ case "state_show":
588
+ if (isDefined(options.path))
589
+ args.push(String(options.path));
590
+ break;
591
+ case "state_rename":
592
+ if (isDefined(options.oldName))
593
+ args.push(String(options.oldName));
594
+ if (isDefined(options.newName))
595
+ args.push(String(options.newName));
596
+ break;
597
+ case "state_clean":
598
+ if (options.days !== undefined && options.days !== null) {
599
+ args.push("--older-than", String(options.days));
600
+ }
601
+ break;
602
+ case "state_clear":
603
+ if (isDefined(options.sessionName))
604
+ args.push(String(options.sessionName));
605
+ break;
606
+ // Recording
607
+ case "record_start":
608
+ case "record_restart":
609
+ if (isDefined(options.path))
610
+ args.push(String(options.path));
611
+ if (isDefined(options.url))
612
+ args.push(String(options.url));
613
+ break;
614
+ // Auth
615
+ case "auth_save":
616
+ if (isDefined(options.name))
617
+ args.push(String(options.name));
618
+ if (isDefined(options.url))
619
+ args.push("--url", String(options.url));
620
+ if (isDefined(options.username))
621
+ args.push("--username", String(options.username));
622
+ if (isDefined(options.password))
623
+ args.push("--password", String(options.password));
624
+ if (isDefined(options.usernameSelector)) {
625
+ args.push("--username-selector", String(options.usernameSelector));
626
+ }
627
+ if (isDefined(options.passwordSelector)) {
628
+ args.push("--password-selector", String(options.passwordSelector));
629
+ }
630
+ if (isDefined(options.submitSelector)) {
631
+ args.push("--submit-selector", String(options.submitSelector));
632
+ }
633
+ break;
634
+ case "auth_login":
635
+ case "auth_delete":
636
+ case "auth_show":
637
+ if (isDefined(options.name))
638
+ args.push(String(options.name));
639
+ break;
640
+ // Diff
641
+ case "diff_snapshot":
642
+ if (isDefined(options.baseline))
643
+ args.push("--baseline", String(options.baseline));
644
+ if (isDefined(options.selector))
645
+ args.push("--selector", String(options.selector));
646
+ if (options.compact)
647
+ args.push("--compact");
648
+ if (options.depth !== undefined && options.depth !== null) {
649
+ args.push("--depth", String(options.depth));
650
+ }
651
+ break;
652
+ case "diff_screenshot":
653
+ if (isDefined(options.baseline))
654
+ args.push("--baseline", String(options.baseline));
655
+ if (isDefined(options.output))
656
+ args.push("--output", String(options.output));
657
+ if (options.threshold !== undefined && options.threshold !== null) {
658
+ args.push("--threshold", String(options.threshold));
659
+ }
660
+ if (isDefined(options.selector))
661
+ args.push("--selector", String(options.selector));
662
+ if (options.fullPage)
663
+ args.push("--full");
664
+ break;
665
+ case "diff_url":
666
+ if (isDefined(options.url1))
667
+ args.push(String(options.url1));
668
+ if (isDefined(options.url2))
669
+ args.push(String(options.url2));
670
+ if (options.screenshot)
671
+ args.push("--screenshot");
672
+ if (options.fullPage)
673
+ args.push("--full");
674
+ if (isDefined(options.waitUntil))
675
+ args.push("--wait-until", String(options.waitUntil));
676
+ if (isDefined(options.selector))
677
+ args.push("--selector", String(options.selector));
678
+ if (options.compact)
679
+ args.push("--compact");
680
+ if (options.depth !== undefined && options.depth !== null) {
681
+ args.push("--depth", String(options.depth));
682
+ }
683
+ break;
684
+ // React
685
+ case "react_inspect":
686
+ if (options.fiberId !== undefined && options.fiberId !== null) {
687
+ args.push(String(options.fiberId));
688
+ }
689
+ break;
690
+ // Vitals
691
+ case "vitals":
692
+ if (isDefined(options.url))
693
+ args.push(String(options.url));
694
+ break;
695
+ // Init Scripts
696
+ case "remove_init_script":
697
+ if (isDefined(options.identifier))
698
+ args.push(String(options.identifier));
699
+ break;
700
+ // Confirm/Deny
701
+ case "confirm_action":
702
+ case "deny_action":
703
+ if (isDefined(options.confirmationId))
704
+ args.push(String(options.confirmationId));
705
+ break;
706
+ // Connect CDP
707
+ case "connect":
708
+ if (isDefined(options.endpoint))
709
+ args.push(String(options.endpoint));
710
+ break;
711
+ // Streaming
712
+ case "stream_enable":
713
+ break;
714
+ // Dashboard
715
+ case "dashboard_start":
716
+ if (isDefined(options.port))
717
+ args.push("--port", String(options.port));
718
+ break;
719
+ // Commands with no positional args
720
+ case "go_back":
721
+ case "go_forward":
722
+ case "reload":
723
+ case "get_url":
724
+ case "get_title":
725
+ case "get_cdp_url":
726
+ case "snapshot":
727
+ case "get_cookies":
728
+ case "clear_cookies":
729
+ case "get_console":
730
+ case "get_errors":
731
+ case "inspect":
732
+ case "close_session":
733
+ case "tab_list":
734
+ case "frame_main":
735
+ case "dialog_status":
736
+ case "trace_start":
737
+ case "profiler_start":
738
+ case "state_list":
739
+ case "record_stop":
740
+ case "auth_list":
741
+ case "session_show":
742
+ case "session_list":
743
+ case "stream_disable":
744
+ case "stream_status":
745
+ case "dashboard_stop":
746
+ case "device_list":
747
+ case "react_tree":
748
+ case "react_renders_start":
749
+ case "react_renders_stop":
750
+ case "react_suspense":
751
+ case "clipboard_read":
752
+ case "clipboard_copy":
753
+ case "clipboard_paste":
754
+ case "storage_clear_local":
755
+ case "storage_clear_session":
756
+ case "window_new":
757
+ case "network_requests":
758
+ case "network_har_start":
759
+ case "get_storage_local":
760
+ case "get_storage_session":
761
+ case "wait_for_url":
762
+ case "wait_for_navigation":
763
+ case "wait_for_load_state":
764
+ case "wait_for_function":
765
+ case "wait_for_text":
766
+ case "wait_for_download":
767
+ case "get_network":
768
+ case "new_session":
769
+ break;
770
+ }
771
+ return args;
772
+ }
773
+ /**
774
+ * Build optional flags for commands that support them.
775
+ */
776
+ function buildOptionalFlags(command, options) {
777
+ const flags = [];
778
+ switch (command) {
779
+ case "screenshot":
780
+ if (options.fullPage)
781
+ flags.push("-f");
782
+ if (options.annotate)
783
+ flags.push("--annotate");
784
+ if (isDefined(options.format))
785
+ flags.push("--screenshot-format", String(options.format));
786
+ if (options.quality !== undefined && options.quality !== null) {
787
+ flags.push("--screenshot-quality", String(options.quality));
788
+ }
789
+ if (isDefined(options.screenshotDir)) {
790
+ flags.push("--screenshot-dir", String(options.screenshotDir));
791
+ }
792
+ break;
793
+ case "snapshot":
794
+ if (options.interactive)
795
+ flags.push("-i");
796
+ if (options.compact)
797
+ flags.push("-c");
798
+ if (options.cursor)
799
+ flags.push("-C");
800
+ if (options.urls)
801
+ flags.push("-u");
802
+ if (options.depth !== undefined && options.depth !== null) {
803
+ flags.push("-d", String(options.depth));
804
+ }
805
+ if (isDefined(options.selector)) {
806
+ flags.push("-s", String(options.selector));
807
+ }
808
+ break;
809
+ case "scroll":
810
+ if (isDefined(options.selector)) {
811
+ flags.push("--selector", String(options.selector));
812
+ }
813
+ break;
814
+ case "click":
815
+ if (options.newTab)
816
+ flags.push("--new-tab");
817
+ break;
818
+ case "batch":
819
+ if (options.bail)
820
+ flags.push("--bail");
821
+ break;
822
+ case "tab_new":
823
+ if (isDefined(options.label))
824
+ flags.push("--label", String(options.label));
825
+ break;
826
+ case "stream_enable":
827
+ if (options.port !== undefined && options.port !== null) {
828
+ flags.push("--port", String(options.port));
829
+ }
830
+ break;
831
+ case "wait":
832
+ if (isDefined(options.text))
833
+ flags.push("--text", String(options.text));
834
+ if (options.timeout !== undefined && options.timeout !== null) {
835
+ if (!isDefined(options.text) && command === "wait") {
836
+ // timeout alone doesn't need --timeout flag for raw wait
837
+ }
838
+ else {
839
+ flags.push("--timeout", String(options.timeout));
840
+ }
841
+ }
842
+ break;
843
+ case "wait_for_url":
844
+ case "wait_for_navigation":
845
+ if (isDefined(options.url))
846
+ flags.push("--url", String(options.url));
847
+ if (options.timeout !== undefined && options.timeout !== null) {
848
+ flags.push("--timeout", String(options.timeout));
849
+ }
850
+ break;
851
+ case "wait_for_text":
852
+ if (isDefined(options.text))
853
+ flags.push("--text", String(options.text));
854
+ if (options.timeout !== undefined && options.timeout !== null) {
855
+ flags.push("--timeout", String(options.timeout));
856
+ }
857
+ break;
858
+ case "wait_for_load_state":
859
+ if (isDefined(options.state))
860
+ flags.push("--load", String(options.state));
861
+ if (options.timeout !== undefined && options.timeout !== null) {
862
+ flags.push("--timeout", String(options.timeout));
863
+ }
864
+ break;
865
+ case "wait_for_function":
866
+ if (isDefined(options.expression))
867
+ flags.push("--fn", String(options.expression));
868
+ if (options.timeout !== undefined && options.timeout !== null) {
869
+ flags.push("--timeout", String(options.timeout));
870
+ }
871
+ break;
872
+ case "wait_for_download":
873
+ if (isDefined(options.path)) {
874
+ flags.push("--download", String(options.path));
875
+ }
876
+ else {
877
+ flags.push("--download");
878
+ }
879
+ if (options.timeout !== undefined && options.timeout !== null) {
880
+ flags.push("--timeout", String(options.timeout));
881
+ }
882
+ break;
883
+ case "profiler_start":
884
+ if (isDefined(options.categories)) {
885
+ flags.push("--categories", String(options.categories));
886
+ }
887
+ break;
888
+ case "get_console":
889
+ case "get_errors":
890
+ if (options.clear)
891
+ flags.push("--clear");
892
+ break;
893
+ case "network_requests":
894
+ case "get_network":
895
+ if (options.clear)
896
+ flags.push("--clear");
897
+ if (isDefined(options.filter))
898
+ flags.push("--filter", String(options.filter));
899
+ if (isDefined(options.type))
900
+ flags.push("--type", String(options.type));
901
+ if (isDefined(options.method))
902
+ flags.push("--method", String(options.method));
903
+ if (isDefined(options.status))
904
+ flags.push("--status", String(options.status));
905
+ break;
906
+ case "network_route":
907
+ if (options.abort)
908
+ flags.push("--abort");
909
+ if (isDefined(options.body))
910
+ flags.push("--body", String(options.body));
911
+ if (isDefined(options.resourceType)) {
912
+ flags.push("--resource-type", String(options.resourceType));
913
+ }
914
+ break;
915
+ case "set_cookie":
916
+ case "set_cookies":
917
+ if (isDefined(options.url))
918
+ flags.push("--url", String(options.url));
919
+ if (isDefined(options.domain))
920
+ flags.push("--domain", String(options.domain));
921
+ if (isDefined(options.path))
922
+ flags.push("--path", String(options.path));
923
+ if (options.httpOnly)
924
+ flags.push("--httpOnly");
925
+ if (options.secure)
926
+ flags.push("--secure");
927
+ if (isDefined(options.sameSite))
928
+ flags.push("--sameSite", String(options.sameSite));
929
+ if (options.expires !== undefined && options.expires !== null) {
930
+ flags.push("--expires", String(options.expires));
931
+ }
932
+ break;
933
+ case "set_cookies_from_file":
934
+ if (isDefined(options.domain))
935
+ flags.push("--domain", String(options.domain));
936
+ if (isDefined(options.url))
937
+ flags.push("--url", String(options.url));
938
+ break;
939
+ case "evaluate":
940
+ case "evaluate_base64":
941
+ if (options.stdin)
942
+ flags.push("--stdin");
943
+ break;
944
+ case "react_tree":
945
+ case "react_inspect":
946
+ case "react_renders_stop":
947
+ case "react_suspense":
948
+ if (options.json)
949
+ flags.push("--json");
950
+ if (options.onlyDynamic)
951
+ flags.push("--only-dynamic");
952
+ break;
953
+ case "vitals":
954
+ if (options.json)
955
+ flags.push("--json");
956
+ break;
957
+ case "state_clear":
958
+ if (options.all)
959
+ flags.push("--all");
960
+ break;
961
+ case "diff_snapshot":
962
+ if (isDefined(options.baseline))
963
+ flags.push("--baseline", String(options.baseline));
964
+ if (isDefined(options.selector))
965
+ flags.push("--selector", String(options.selector));
966
+ if (options.compact)
967
+ flags.push("--compact");
968
+ if (options.depth !== undefined && options.depth !== null) {
969
+ flags.push("--depth", String(options.depth));
970
+ }
971
+ break;
972
+ case "diff_screenshot":
973
+ if (isDefined(options.baseline))
974
+ flags.push("--baseline", String(options.baseline));
975
+ if (isDefined(options.output))
976
+ flags.push("--output", String(options.output));
977
+ if (options.threshold !== undefined && options.threshold !== null) {
978
+ flags.push("--threshold", String(options.threshold));
979
+ }
980
+ if (isDefined(options.selector))
981
+ flags.push("--selector", String(options.selector));
982
+ if (options.fullPage)
983
+ flags.push("--full");
984
+ break;
985
+ case "diff_url":
986
+ if (options.screenshot)
987
+ flags.push("--screenshot");
988
+ if (options.fullPage)
989
+ flags.push("--full");
990
+ if (isDefined(options.waitUntil))
991
+ flags.push("--wait-until", String(options.waitUntil));
992
+ if (isDefined(options.selector))
993
+ flags.push("--selector", String(options.selector));
994
+ if (options.compact)
995
+ flags.push("--compact");
996
+ if (options.depth !== undefined && options.depth !== null) {
997
+ flags.push("--depth", String(options.depth));
998
+ }
999
+ break;
1000
+ }
1001
+ return flags;
1002
+ }
1003
+ /**
1004
+ * Execute an agent-browser command and return the result.
1005
+ */
1006
+ export async function execBrowser(command, options = {}, sessionId) {
1007
+ const cliCommand = COMMAND_MAP[command];
1008
+ if (!cliCommand) {
1009
+ throw new Error(`Unknown command: ${command}`);
1010
+ }
1011
+ const commandParts = cliCommand.split(" ");
1012
+ const args = [...commandParts];
1013
+ const execPath = getExecutablePath();
1014
+ if (execPath) {
1015
+ args.push("--executable-path", execPath);
1016
+ }
1017
+ if (sessionId) {
1018
+ args.push("--session", sessionId);
1019
+ }
1020
+ const positionalArgs = buildPositionalArgs(command, options);
1021
+ args.push(...positionalArgs);
1022
+ const optionalFlags = buildOptionalFlags(command, options);
1023
+ args.push(...optionalFlags);
1024
+ if (process.env.DEBUG) {
1025
+ console.error(`[agent-browser-mcp] Executing: ${AGENT_BROWSER_PATH} ${args.join(" ")}`);
1026
+ }
1027
+ return new Promise((resolve, reject) => {
1028
+ const proc = spawn(AGENT_BROWSER_PATH, args, {
1029
+ env: {
1030
+ ...process.env,
1031
+ ...(sessionId && { AGENT_BROWSER_SESSION: sessionId }),
1032
+ },
1033
+ });
1034
+ let stdout = "";
1035
+ let stderr = "";
1036
+ proc.stdout.on("data", (data) => {
1037
+ stdout += data.toString();
1038
+ });
1039
+ proc.stderr.on("data", (data) => {
1040
+ stderr += data.toString();
1041
+ });
1042
+ proc.on("close", (code) => {
1043
+ if (code === 0) {
1044
+ resolve(stdout.trim() || "Command executed successfully");
1045
+ }
1046
+ else {
1047
+ reject(new Error(`agent-browser exited with code ${code}: ${stderr || stdout}`));
1048
+ }
1049
+ });
1050
+ proc.on("error", (err) => {
1051
+ reject(new Error(`Failed to execute agent-browser: ${err.message}`));
1052
+ });
1053
+ });
1054
+ }
1055
+ /**
1056
+ * Check if agent-browser is available.
1057
+ */
1058
+ export async function checkAgentBrowser() {
1059
+ try {
1060
+ await execBrowser("snapshot", {});
1061
+ return true;
1062
+ }
1063
+ catch {
1064
+ return false;
1065
+ }
1066
+ }
1067
+ //# sourceMappingURL=executor.js.map