cbrowser 8.8.0 → 8.9.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 (62) hide show
  1. package/README.md +9 -2
  2. package/dist/analysis/bug-hunter.js +1 -4
  3. package/dist/analysis/bug-hunter.js.map +1 -1
  4. package/dist/analysis/chaos-testing.js +4 -8
  5. package/dist/analysis/chaos-testing.js.map +1 -1
  6. package/dist/analysis/index.js +4 -20
  7. package/dist/analysis/index.js.map +1 -1
  8. package/dist/analysis/natural-language.js +4 -10
  9. package/dist/analysis/natural-language.js.map +1 -1
  10. package/dist/analysis/persona-comparison.js +6 -10
  11. package/dist/analysis/persona-comparison.js.map +1 -1
  12. package/dist/browser.d.ts +5 -0
  13. package/dist/browser.d.ts.map +1 -1
  14. package/dist/browser.js +222 -131
  15. package/dist/browser.js.map +1 -1
  16. package/dist/cli.js +138 -131
  17. package/dist/cli.js.map +1 -1
  18. package/dist/cognitive/index.js +29 -40
  19. package/dist/cognitive/index.js.map +1 -1
  20. package/dist/config.js +50 -61
  21. package/dist/config.js.map +1 -1
  22. package/dist/daemon.js +28 -37
  23. package/dist/daemon.js.map +1 -1
  24. package/dist/index.js +10 -40
  25. package/dist/index.js.map +1 -1
  26. package/dist/mcp-server-remote.js +153 -156
  27. package/dist/mcp-server-remote.js.map +1 -1
  28. package/dist/mcp-server.js +146 -149
  29. package/dist/mcp-server.js.map +1 -1
  30. package/dist/performance/index.js +1 -17
  31. package/dist/performance/index.js.map +1 -1
  32. package/dist/performance/metrics.js +30 -39
  33. package/dist/performance/metrics.js.map +1 -1
  34. package/dist/personas.js +32 -46
  35. package/dist/personas.js.map +1 -1
  36. package/dist/testing/coverage.js +13 -23
  37. package/dist/testing/coverage.js.map +1 -1
  38. package/dist/testing/flaky-detection.js +4 -8
  39. package/dist/testing/flaky-detection.js.map +1 -1
  40. package/dist/testing/index.js +4 -20
  41. package/dist/testing/index.js.map +1 -1
  42. package/dist/testing/nl-test-suite.js +11 -19
  43. package/dist/testing/nl-test-suite.js.map +1 -1
  44. package/dist/testing/test-repair.js +9 -15
  45. package/dist/testing/test-repair.js.map +1 -1
  46. package/dist/types.js +3 -6
  47. package/dist/types.js.map +1 -1
  48. package/dist/version.d.ts +9 -0
  49. package/dist/version.d.ts.map +1 -0
  50. package/dist/version.js +60 -0
  51. package/dist/version.js.map +1 -0
  52. package/dist/visual/ab-comparison.js +16 -22
  53. package/dist/visual/ab-comparison.js.map +1 -1
  54. package/dist/visual/cross-browser.js +17 -24
  55. package/dist/visual/cross-browser.js.map +1 -1
  56. package/dist/visual/index.js +4 -20
  57. package/dist/visual/index.js.map +1 -1
  58. package/dist/visual/regression.js +46 -58
  59. package/dist/visual/regression.js.map +1 -1
  60. package/dist/visual/responsive.js +22 -29
  61. package/dist/visual/responsive.js.map +1 -1
  62. package/package.json +2 -1
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env node
2
- "use strict";
3
2
  /**
4
3
  * CBrowser MCP Server
5
4
  *
@@ -7,40 +6,38 @@
7
6
  * Run with: cbrowser mcp-server
8
7
  * Or: npx cbrowser mcp-server
9
8
  */
10
- Object.defineProperty(exports, "__esModule", { value: true });
11
- exports.startMcpServer = startMcpServer;
12
- const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
13
- const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
14
- const zod_1 = require("zod");
15
- const browser_js_1 = require("./browser.js");
16
- const config_js_1 = require("./config.js");
9
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
10
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
11
+ import { z } from "zod";
12
+ import { CBrowser } from "./browser.js";
13
+ import { ensureDirectories, getStatusInfo } from "./config.js";
17
14
  // Visual module imports
18
- const index_js_1 = require("./visual/index.js");
15
+ import { runVisualRegression, runCrossBrowserTest, runResponsiveTest, runABComparison, crossBrowserDiff, captureVisualBaseline, listVisualBaselines, } from "./visual/index.js";
19
16
  // Testing module imports
20
- const index_js_2 = require("./testing/index.js");
17
+ import { runNLTestSuite, parseNLTestSuite, dryRunNLTestSuite, repairTest, detectFlakyTests, generateCoverageMap, } from "./testing/index.js";
21
18
  // Analysis module imports
22
- const index_js_3 = require("./analysis/index.js");
19
+ import { huntBugs, runChaosTest, comparePersonas, findElementByIntent, } from "./analysis/index.js";
23
20
  // Persona imports for cognitive journey
24
- const personas_js_1 = require("./personas.js");
21
+ import { getPersona, listPersonas, getCognitiveProfile, createCognitivePersona, } from "./personas.js";
25
22
  // Performance module imports
26
- const index_js_4 = require("./performance/index.js");
27
- // Version constant - keep in sync with package.json
28
- const VERSION = "8.7.0";
23
+ import { capturePerformanceBaseline, detectPerformanceRegression, listPerformanceBaselines, } from "./performance/index.js";
24
+ // Version from package.json - single source of truth
25
+ import { VERSION } from "./version.js";
29
26
  // Shared browser instance
30
27
  let browser = null;
31
28
  async function getBrowser() {
32
29
  if (!browser) {
33
- browser = new browser_js_1.CBrowser({
30
+ browser = new CBrowser({
34
31
  headless: true,
35
32
  persistent: true,
36
33
  });
37
34
  }
38
35
  return browser;
39
36
  }
40
- async function startMcpServer() {
37
+ export async function startMcpServer() {
41
38
  // Auto-initialize all data directories on server start
42
- (0, config_js_1.ensureDirectories)();
43
- const server = new mcp_js_1.McpServer({
39
+ ensureDirectories();
40
+ const server = new McpServer({
44
41
  name: "cbrowser",
45
42
  version: VERSION,
46
43
  });
@@ -48,7 +45,7 @@ async function startMcpServer() {
48
45
  // Navigation Tools
49
46
  // =========================================================================
50
47
  server.tool("navigate", "Navigate to a URL and take a screenshot", {
51
- url: zod_1.z.string().url().describe("The URL to navigate to"),
48
+ url: z.string().url().describe("The URL to navigate to"),
52
49
  }, async ({ url }) => {
53
50
  const b = await getBrowser();
54
51
  const result = await b.navigate(url);
@@ -71,9 +68,9 @@ async function startMcpServer() {
71
68
  // Interaction Tools
72
69
  // =========================================================================
73
70
  server.tool("click", "Click an element on the page using text, selector, or description. Use verbose=true for detailed debug info on failure.", {
74
- selector: zod_1.z.string().describe("Element to click (text content, CSS selector, or description)"),
75
- force: zod_1.z.boolean().optional().describe("Bypass safety checks for destructive actions"),
76
- verbose: zod_1.z.boolean().optional().describe("Return available elements and AI suggestions on failure"),
71
+ selector: z.string().describe("Element to click (text content, CSS selector, or description)"),
72
+ force: z.boolean().optional().describe("Bypass safety checks for destructive actions"),
73
+ verbose: z.boolean().optional().describe("Return available elements and AI suggestions on failure"),
77
74
  }, async ({ selector, force, verbose }) => {
78
75
  const b = await getBrowser();
79
76
  const result = await b.click(selector, { force, verbose });
@@ -95,9 +92,9 @@ async function startMcpServer() {
95
92
  };
96
93
  });
97
94
  server.tool("smart_click", "Click with auto-retry and self-healing selectors", {
98
- selector: zod_1.z.string().describe("Element to click"),
99
- maxRetries: zod_1.z.number().optional().default(3).describe("Maximum retry attempts"),
100
- dismissOverlays: zod_1.z.boolean().optional().default(false).describe("Dismiss overlays before clicking"),
95
+ selector: z.string().describe("Element to click"),
96
+ maxRetries: z.number().optional().default(3).describe("Maximum retry attempts"),
97
+ dismissOverlays: z.boolean().optional().default(false).describe("Dismiss overlays before clicking"),
101
98
  }, async ({ selector, maxRetries, dismissOverlays }) => {
102
99
  const b = await getBrowser();
103
100
  const result = await b.smartClick(selector, { maxRetries, dismissOverlays });
@@ -117,8 +114,8 @@ async function startMcpServer() {
117
114
  };
118
115
  });
119
116
  server.tool("dismiss_overlay", "Detect and dismiss modal overlays (cookie consent, age verification, newsletter popups). Constitutional Yellow zone.", {
120
- type: zod_1.z.enum(["auto", "cookie", "age-verify", "newsletter", "custom"]).optional().default("auto").describe("Overlay type to detect"),
121
- customSelector: zod_1.z.string().optional().describe("Custom CSS selector for overlay close button"),
117
+ type: z.enum(["auto", "cookie", "age-verify", "newsletter", "custom"]).optional().default("auto").describe("Overlay type to detect"),
118
+ customSelector: z.string().optional().describe("Custom CSS selector for overlay close button"),
122
119
  }, async ({ type, customSelector }) => {
123
120
  const b = await getBrowser();
124
121
  const result = await b.dismissOverlay({ type, customSelector });
@@ -138,9 +135,9 @@ async function startMcpServer() {
138
135
  };
139
136
  });
140
137
  server.tool("fill", "Fill a form field with text. Use verbose=true for detailed debug info on failure.", {
141
- selector: zod_1.z.string().describe("Input field to fill (name, placeholder, label, or selector)"),
142
- value: zod_1.z.string().describe("Value to enter"),
143
- verbose: zod_1.z.boolean().optional().describe("Return available inputs and AI suggestions on failure"),
138
+ selector: z.string().describe("Input field to fill (name, placeholder, label, or selector)"),
139
+ value: z.string().describe("Value to enter"),
140
+ verbose: z.boolean().optional().describe("Return available inputs and AI suggestions on failure"),
144
141
  }, async ({ selector, value, verbose }) => {
145
142
  const b = await getBrowser();
146
143
  const result = await b.fill(selector, value, { verbose });
@@ -164,7 +161,7 @@ async function startMcpServer() {
164
161
  // Extraction Tools
165
162
  // =========================================================================
166
163
  server.tool("screenshot", "Take a screenshot of the current page", {
167
- path: zod_1.z.string().optional().describe("Optional path to save the screenshot"),
164
+ path: z.string().optional().describe("Optional path to save the screenshot"),
168
165
  }, async ({ path }) => {
169
166
  const b = await getBrowser();
170
167
  const file = await b.screenshot(path);
@@ -178,7 +175,7 @@ async function startMcpServer() {
178
175
  };
179
176
  });
180
177
  server.tool("extract", "Extract data from the page", {
181
- what: zod_1.z.enum(["links", "headings", "forms", "images", "text"]).describe("What to extract"),
178
+ what: z.enum(["links", "headings", "forms", "images", "text"]).describe("What to extract"),
182
179
  }, async ({ what }) => {
183
180
  const b = await getBrowser();
184
181
  const result = await b.extract(what);
@@ -195,7 +192,7 @@ async function startMcpServer() {
195
192
  // Assertion Tools
196
193
  // =========================================================================
197
194
  server.tool("assert", "Assert a condition using natural language", {
198
- assertion: zod_1.z.string().describe("Natural language assertion like \"page contains 'Welcome'\" or \"title is 'Home'\""),
195
+ assertion: z.string().describe("Natural language assertion like \"page contains 'Welcome'\" or \"title is 'Home'\""),
199
196
  }, async ({ assertion }) => {
200
197
  const b = await getBrowser();
201
198
  const result = await b.assert(assertion);
@@ -237,7 +234,7 @@ async function startMcpServer() {
237
234
  };
238
235
  });
239
236
  server.tool("generate_tests", "Generate test scenarios for a page", {
240
- url: zod_1.z.string().url().optional().describe("URL to analyze (uses current page if not provided)"),
237
+ url: z.string().url().optional().describe("URL to analyze (uses current page if not provided)"),
241
238
  }, async ({ url }) => {
242
239
  const b = await getBrowser();
243
240
  const result = await b.generateTests(url);
@@ -261,7 +258,7 @@ async function startMcpServer() {
261
258
  // Session Tools
262
259
  // =========================================================================
263
260
  server.tool("save_session", "Save browser session (cookies, storage) for later use", {
264
- name: zod_1.z.string().describe("Name for the saved session"),
261
+ name: z.string().describe("Name for the saved session"),
265
262
  }, async ({ name }) => {
266
263
  const b = await getBrowser();
267
264
  await b.saveSession(name);
@@ -275,7 +272,7 @@ async function startMcpServer() {
275
272
  };
276
273
  });
277
274
  server.tool("load_session", "Load a previously saved session", {
278
- name: zod_1.z.string().describe("Name of the session to load"),
275
+ name: z.string().describe("Name of the session to load"),
279
276
  }, async ({ name }) => {
280
277
  const b = await getBrowser();
281
278
  const loaded = await b.loadSession(name);
@@ -301,7 +298,7 @@ async function startMcpServer() {
301
298
  };
302
299
  });
303
300
  server.tool("delete_session", "Delete a saved session by name", {
304
- name: zod_1.z.string().describe("Name of the session to delete"),
301
+ name: z.string().describe("Name of the session to delete"),
305
302
  }, async ({ name }) => {
306
303
  const b = await getBrowser();
307
304
  const deleted = b.deleteSession(name);
@@ -333,10 +330,10 @@ async function startMcpServer() {
333
330
  // Visual Testing Tools (v7.0.0+)
334
331
  // =========================================================================
335
332
  server.tool("visual_baseline", "Capture a visual baseline for a URL", {
336
- url: zod_1.z.string().url().describe("URL to capture baseline for"),
337
- name: zod_1.z.string().describe("Name for the baseline"),
333
+ url: z.string().url().describe("URL to capture baseline for"),
334
+ name: z.string().describe("Name for the baseline"),
338
335
  }, async ({ url, name }) => {
339
- const result = await (0, index_js_1.captureVisualBaseline)(url, name, {});
336
+ const result = await captureVisualBaseline(url, name, {});
340
337
  return {
341
338
  content: [
342
339
  {
@@ -352,10 +349,10 @@ async function startMcpServer() {
352
349
  };
353
350
  });
354
351
  server.tool("visual_regression", "Run AI visual regression test against a baseline", {
355
- url: zod_1.z.string().url().describe("URL to test"),
356
- baselineName: zod_1.z.string().describe("Name of baseline to compare against"),
352
+ url: z.string().url().describe("URL to test"),
353
+ baselineName: z.string().describe("Name of baseline to compare against"),
357
354
  }, async ({ url, baselineName }) => {
358
- const result = await (0, index_js_1.runVisualRegression)(url, baselineName);
355
+ const result = await runVisualRegression(url, baselineName);
359
356
  return {
360
357
  content: [
361
358
  {
@@ -371,10 +368,10 @@ async function startMcpServer() {
371
368
  };
372
369
  });
373
370
  server.tool("cross_browser_test", "Test page rendering across multiple browsers", {
374
- url: zod_1.z.string().url().describe("URL to test"),
375
- browsers: zod_1.z.array(zod_1.z.enum(["chromium", "firefox", "webkit"])).optional().describe("Browsers to test"),
371
+ url: z.string().url().describe("URL to test"),
372
+ browsers: z.array(z.enum(["chromium", "firefox", "webkit"])).optional().describe("Browsers to test"),
376
373
  }, async ({ url, browsers }) => {
377
- const result = await (0, index_js_1.runCrossBrowserTest)(url, { browsers });
374
+ const result = await runCrossBrowserTest(url, { browsers });
378
375
  return {
379
376
  content: [
380
377
  {
@@ -394,10 +391,10 @@ async function startMcpServer() {
394
391
  };
395
392
  });
396
393
  server.tool("cross_browser_diff", "Quick diff of page metrics across browsers", {
397
- url: zod_1.z.string().url().describe("URL to compare"),
398
- browsers: zod_1.z.array(zod_1.z.enum(["chromium", "firefox", "webkit"])).optional().describe("Browsers to compare"),
394
+ url: z.string().url().describe("URL to compare"),
395
+ browsers: z.array(z.enum(["chromium", "firefox", "webkit"])).optional().describe("Browsers to compare"),
399
396
  }, async ({ url, browsers }) => {
400
- const result = await (0, index_js_1.crossBrowserDiff)(url, browsers);
397
+ const result = await crossBrowserDiff(url, browsers);
401
398
  return {
402
399
  content: [
403
400
  {
@@ -416,10 +413,10 @@ async function startMcpServer() {
416
413
  };
417
414
  });
418
415
  server.tool("responsive_test", "Test page across different viewport sizes", {
419
- url: zod_1.z.string().url().describe("URL to test"),
420
- viewports: zod_1.z.array(zod_1.z.string()).optional().describe("Viewport presets (mobile, tablet, desktop, etc.)"),
416
+ url: z.string().url().describe("URL to test"),
417
+ viewports: z.array(z.string()).optional().describe("Viewport presets (mobile, tablet, desktop, etc.)"),
421
418
  }, async ({ url, viewports }) => {
422
- const result = await (0, index_js_1.runResponsiveTest)(url, { viewports });
419
+ const result = await runResponsiveTest(url, { viewports });
423
420
  return {
424
421
  content: [
425
422
  {
@@ -435,13 +432,13 @@ async function startMcpServer() {
435
432
  };
436
433
  });
437
434
  server.tool("ab_comparison", "Compare two URLs visually (staging vs production)", {
438
- urlA: zod_1.z.string().url().describe("First URL (e.g., staging)"),
439
- urlB: zod_1.z.string().url().describe("Second URL (e.g., production)"),
440
- labelA: zod_1.z.string().optional().describe("Label for first URL"),
441
- labelB: zod_1.z.string().optional().describe("Label for second URL"),
435
+ urlA: z.string().url().describe("First URL (e.g., staging)"),
436
+ urlB: z.string().url().describe("Second URL (e.g., production)"),
437
+ labelA: z.string().optional().describe("Label for first URL"),
438
+ labelB: z.string().optional().describe("Label for second URL"),
442
439
  }, async ({ urlA, urlB, labelA, labelB }) => {
443
440
  const labels = labelA && labelB ? { a: labelA, b: labelB } : undefined;
444
- const result = await (0, index_js_1.runABComparison)(urlA, urlB, { labels });
441
+ const result = await runABComparison(urlA, urlB, { labels });
445
442
  return {
446
443
  content: [
447
444
  {
@@ -460,9 +457,9 @@ async function startMcpServer() {
460
457
  // Testing Tools (v6.0.0+)
461
458
  // =========================================================================
462
459
  server.tool("nl_test_file", "Run natural language test suite from a file. Returns step-level results with enriched error info, partial matches, and suggestions.", {
463
- filepath: zod_1.z.string().describe("Path to the test file"),
464
- dryRun: zod_1.z.boolean().optional().describe("Parse and display steps without executing"),
465
- fuzzyMatch: zod_1.z.boolean().optional().describe("Use case-insensitive fuzzy matching for assertions"),
460
+ filepath: z.string().describe("Path to the test file"),
461
+ dryRun: z.boolean().optional().describe("Parse and display steps without executing"),
462
+ fuzzyMatch: z.boolean().optional().describe("Use case-insensitive fuzzy matching for assertions"),
466
463
  }, async ({ filepath, dryRun, fuzzyMatch }) => {
467
464
  const fs = await import("fs");
468
465
  if (!fs.existsSync(filepath)) {
@@ -470,12 +467,12 @@ async function startMcpServer() {
470
467
  }
471
468
  const fileContent = fs.readFileSync(filepath, "utf-8");
472
469
  const suiteName = filepath.split("/").pop()?.replace(/\.[^.]+$/, "") || "Test Suite";
473
- const suite = (0, index_js_2.parseNLTestSuite)(fileContent, suiteName);
470
+ const suite = parseNLTestSuite(fileContent, suiteName);
474
471
  if (dryRun) {
475
- const dryResult = (0, index_js_2.dryRunNLTestSuite)(suite);
472
+ const dryResult = dryRunNLTestSuite(suite);
476
473
  return { content: [{ type: "text", text: JSON.stringify(dryResult, null, 2) }] };
477
474
  }
478
- const result = await (0, index_js_2.runNLTestSuite)(suite, { fuzzyMatch: fuzzyMatch || false });
475
+ const result = await runNLTestSuite(suite, { fuzzyMatch: fuzzyMatch || false });
479
476
  return {
480
477
  content: [
481
478
  {
@@ -508,17 +505,17 @@ async function startMcpServer() {
508
505
  };
509
506
  });
510
507
  server.tool("nl_test_inline", "Run natural language tests from inline content. Returns step-level results with enriched error info, partial matches, and suggestions.", {
511
- content: zod_1.z.string().describe("Test content with instructions like 'go to https://...' and 'click login'"),
512
- name: zod_1.z.string().optional().describe("Name for the test suite"),
513
- dryRun: zod_1.z.boolean().optional().describe("Parse and display steps without executing"),
514
- fuzzyMatch: zod_1.z.boolean().optional().describe("Use case-insensitive fuzzy matching for assertions"),
508
+ content: z.string().describe("Test content with instructions like 'go to https://...' and 'click login'"),
509
+ name: z.string().optional().describe("Name for the test suite"),
510
+ dryRun: z.boolean().optional().describe("Parse and display steps without executing"),
511
+ fuzzyMatch: z.boolean().optional().describe("Use case-insensitive fuzzy matching for assertions"),
515
512
  }, async ({ content, name, dryRun, fuzzyMatch }) => {
516
- const suite = (0, index_js_2.parseNLTestSuite)(content, name || "Inline Test");
513
+ const suite = parseNLTestSuite(content, name || "Inline Test");
517
514
  if (dryRun) {
518
- const dryResult = (0, index_js_2.dryRunNLTestSuite)(suite);
515
+ const dryResult = dryRunNLTestSuite(suite);
519
516
  return { content: [{ type: "text", text: JSON.stringify(dryResult, null, 2) }] };
520
517
  }
521
- const result = await (0, index_js_2.runNLTestSuite)(suite, { fuzzyMatch: fuzzyMatch || false });
518
+ const result = await runNLTestSuite(suite, { fuzzyMatch: fuzzyMatch || false });
522
519
  return {
523
520
  content: [
524
521
  {
@@ -551,9 +548,9 @@ async function startMcpServer() {
551
548
  };
552
549
  });
553
550
  server.tool("repair_test", "AI-powered test repair for broken tests", {
554
- testName: zod_1.z.string().describe("Name for the test"),
555
- steps: zod_1.z.array(zod_1.z.string()).describe("Test step instructions"),
556
- autoApply: zod_1.z.boolean().optional().describe("Automatically apply repairs"),
551
+ testName: z.string().describe("Name for the test"),
552
+ steps: z.array(z.string()).describe("Test step instructions"),
553
+ autoApply: z.boolean().optional().describe("Automatically apply repairs"),
557
554
  }, async ({ testName, steps, autoApply }) => {
558
555
  const testCase = {
559
556
  name: testName,
@@ -562,7 +559,7 @@ async function startMcpServer() {
562
559
  action: "unknown",
563
560
  })),
564
561
  };
565
- const result = await (0, index_js_2.repairTest)(testCase, { autoApply: autoApply || false });
562
+ const result = await repairTest(testCase, { autoApply: autoApply || false });
566
563
  return {
567
564
  content: [
568
565
  {
@@ -583,12 +580,12 @@ async function startMcpServer() {
583
580
  };
584
581
  });
585
582
  server.tool("detect_flaky_tests", "Detect flaky/unreliable tests by running multiple times", {
586
- testContent: zod_1.z.string().describe("Test content to analyze"),
587
- runs: zod_1.z.number().optional().default(5).describe("Number of times to run each test"),
588
- threshold: zod_1.z.number().optional().default(20).describe("Flakiness threshold percentage"),
583
+ testContent: z.string().describe("Test content to analyze"),
584
+ runs: z.number().optional().default(5).describe("Number of times to run each test"),
585
+ threshold: z.number().optional().default(20).describe("Flakiness threshold percentage"),
589
586
  }, async ({ testContent, runs, threshold }) => {
590
- const suite = (0, index_js_2.parseNLTestSuite)(testContent, "Flaky Test Analysis");
591
- const result = await (0, index_js_2.detectFlakyTests)(suite, { runs, flakinessThreshold: threshold });
587
+ const suite = parseNLTestSuite(testContent, "Flaky Test Analysis");
588
+ const result = await detectFlakyTests(suite, { runs, flakinessThreshold: threshold });
592
589
  return {
593
590
  content: [
594
591
  {
@@ -612,11 +609,11 @@ async function startMcpServer() {
612
609
  };
613
610
  });
614
611
  server.tool("coverage_map", "Generate test coverage map for a site", {
615
- baseUrl: zod_1.z.string().url().describe("Base URL to analyze"),
616
- testFiles: zod_1.z.array(zod_1.z.string()).describe("Array of test file paths"),
617
- maxPages: zod_1.z.number().optional().default(100).describe("Maximum pages to crawl"),
612
+ baseUrl: z.string().url().describe("Base URL to analyze"),
613
+ testFiles: z.array(z.string()).describe("Array of test file paths"),
614
+ maxPages: z.number().optional().default(100).describe("Maximum pages to crawl"),
618
615
  }, async ({ baseUrl, testFiles, maxPages }) => {
619
- const result = await (0, index_js_2.generateCoverageMap)(baseUrl, testFiles, { maxPages });
616
+ const result = await generateCoverageMap(baseUrl, testFiles, { maxPages });
620
617
  return {
621
618
  content: [
622
619
  {
@@ -640,12 +637,12 @@ async function startMcpServer() {
640
637
  // Analysis Tools (v4.0.0+)
641
638
  // =========================================================================
642
639
  server.tool("hunt_bugs", "Autonomous bug hunting - crawl and find issues. Returns bugs with severity, selector, and actionable recommendation for each issue found.", {
643
- url: zod_1.z.string().url().describe("Starting URL to hunt from"),
644
- maxPages: zod_1.z.number().optional().default(10).describe("Maximum pages to visit"),
645
- timeout: zod_1.z.number().optional().default(60000).describe("Timeout in milliseconds"),
640
+ url: z.string().url().describe("Starting URL to hunt from"),
641
+ maxPages: z.number().optional().default(10).describe("Maximum pages to visit"),
642
+ timeout: z.number().optional().default(60000).describe("Timeout in milliseconds"),
646
643
  }, async ({ url, maxPages, timeout }) => {
647
644
  const b = await getBrowser();
648
- const result = await (0, index_js_3.huntBugs)(b, url, { maxPages, timeout });
645
+ const result = await huntBugs(b, url, { maxPages, timeout });
649
646
  return {
650
647
  content: [
651
648
  {
@@ -668,13 +665,13 @@ async function startMcpServer() {
668
665
  };
669
666
  });
670
667
  server.tool("chaos_test", "Inject failures and test resilience", {
671
- url: zod_1.z.string().url().describe("URL to test"),
672
- networkLatency: zod_1.z.number().optional().describe("Simulate network latency (ms)"),
673
- offline: zod_1.z.boolean().optional().describe("Simulate offline mode"),
674
- blockUrls: zod_1.z.array(zod_1.z.string()).optional().describe("URL patterns to block"),
668
+ url: z.string().url().describe("URL to test"),
669
+ networkLatency: z.number().optional().describe("Simulate network latency (ms)"),
670
+ offline: z.boolean().optional().describe("Simulate offline mode"),
671
+ blockUrls: z.array(z.string()).optional().describe("URL patterns to block"),
675
672
  }, async ({ url, networkLatency, offline, blockUrls }) => {
676
673
  const b = await getBrowser();
677
- const result = await (0, index_js_3.runChaosTest)(b, url, { networkLatency, offline, blockUrls });
674
+ const result = await runChaosTest(b, url, { networkLatency, offline, blockUrls });
678
675
  return {
679
676
  content: [
680
677
  {
@@ -689,11 +686,11 @@ async function startMcpServer() {
689
686
  };
690
687
  });
691
688
  server.tool("compare_personas", "Compare how different user personas experience a journey", {
692
- url: zod_1.z.string().url().describe("Starting URL"),
693
- goal: zod_1.z.string().describe("Goal to accomplish"),
694
- personas: zod_1.z.array(zod_1.z.string()).describe("Persona names to compare"),
689
+ url: z.string().url().describe("Starting URL"),
690
+ goal: z.string().describe("Goal to accomplish"),
691
+ personas: z.array(z.string()).describe("Persona names to compare"),
695
692
  }, async ({ url, goal, personas }) => {
696
- const result = await (0, index_js_3.comparePersonas)({
693
+ const result = await comparePersonas({
697
694
  startUrl: url,
698
695
  goal,
699
696
  personas,
@@ -713,11 +710,11 @@ async function startMcpServer() {
713
710
  };
714
711
  });
715
712
  server.tool("find_element_by_intent", "AI-powered semantic element finding with ARIA-first selector strategy. Prioritizes aria-label > role > semantic HTML > ID > name > class. Returns selectorType, accessibilityScore (0-1), and alternatives. Use verbose=true for enriched failure responses.", {
716
- intent: zod_1.z.string().describe("Natural language description like 'the cheapest product' or 'login form'"),
717
- verbose: zod_1.z.boolean().optional().describe("Include alternative matches with confidence scores and AI suggestions"),
713
+ intent: z.string().describe("Natural language description like 'the cheapest product' or 'login form'"),
714
+ verbose: z.boolean().optional().describe("Include alternative matches with confidence scores and AI suggestions"),
718
715
  }, async ({ intent, verbose }) => {
719
716
  const b = await getBrowser();
720
- const result = await (0, index_js_3.findElementByIntent)(b, intent, { verbose });
717
+ const result = await findElementByIntent(b, intent, { verbose });
721
718
  if (result && result.confidence > 0) {
722
719
  return {
723
720
  content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
@@ -732,25 +729,25 @@ async function startMcpServer() {
732
729
  // Cognitive Simulation Tools (v8.3.0)
733
730
  // =========================================================================
734
731
  server.tool("cognitive_journey_init", "Initialize a cognitive user journey simulation. Returns the persona's cognitive profile, initial state, and abandonment thresholds. The actual simulation is driven by the LLM using browser tools (navigate, click, fill, screenshot) while tracking cognitive state.", {
735
- persona: zod_1.z.string().describe("Persona name (e.g., 'first-timer', 'elderly-user', 'power-user') or custom description"),
736
- goal: zod_1.z.string().describe("What the simulated user is trying to accomplish"),
737
- startUrl: zod_1.z.string().url().describe("Starting URL for the journey"),
738
- customTraits: zod_1.z.object({
739
- patience: zod_1.z.number().min(0).max(1).optional(),
740
- riskTolerance: zod_1.z.number().min(0).max(1).optional(),
741
- comprehension: zod_1.z.number().min(0).max(1).optional(),
742
- persistence: zod_1.z.number().min(0).max(1).optional(),
743
- curiosity: zod_1.z.number().min(0).max(1).optional(),
744
- workingMemory: zod_1.z.number().min(0).max(1).optional(),
745
- readingTendency: zod_1.z.number().min(0).max(1).optional(),
732
+ persona: z.string().describe("Persona name (e.g., 'first-timer', 'elderly-user', 'power-user') or custom description"),
733
+ goal: z.string().describe("What the simulated user is trying to accomplish"),
734
+ startUrl: z.string().url().describe("Starting URL for the journey"),
735
+ customTraits: z.object({
736
+ patience: z.number().min(0).max(1).optional(),
737
+ riskTolerance: z.number().min(0).max(1).optional(),
738
+ comprehension: z.number().min(0).max(1).optional(),
739
+ persistence: z.number().min(0).max(1).optional(),
740
+ curiosity: z.number().min(0).max(1).optional(),
741
+ workingMemory: z.number().min(0).max(1).optional(),
742
+ readingTendency: z.number().min(0).max(1).optional(),
746
743
  }).optional().describe("Override specific cognitive traits"),
747
744
  }, async ({ persona: personaName, goal, startUrl, customTraits }) => {
748
745
  // Get or create persona
749
- const existingPersona = (0, personas_js_1.getPersona)(personaName);
746
+ const existingPersona = getPersona(personaName);
750
747
  let personaObj;
751
748
  if (!existingPersona) {
752
749
  // Create from description
753
- personaObj = (0, personas_js_1.createCognitivePersona)(personaName, personaName, customTraits || {});
750
+ personaObj = createCognitivePersona(personaName, personaName, customTraits || {});
754
751
  }
755
752
  else if (customTraits) {
756
753
  // Merge custom traits with defaults
@@ -776,7 +773,7 @@ async function startMcpServer() {
776
773
  personaObj = existingPersona;
777
774
  }
778
775
  // Get cognitive profile
779
- const profile = (0, personas_js_1.getCognitiveProfile)(personaObj);
776
+ const profile = getCognitiveProfile(personaObj);
780
777
  // Initial cognitive state
781
778
  const initialState = {
782
779
  patienceRemaining: 1.0,
@@ -869,27 +866,27 @@ Begin the simulation now. Narrate your thoughts as this persona.
869
866
  };
870
867
  });
871
868
  server.tool("cognitive_journey_update_state", "Update the cognitive state during a journey simulation. Call this after each action to track mental state.", {
872
- currentState: zod_1.z.object({
873
- patienceRemaining: zod_1.z.number(),
874
- confusionLevel: zod_1.z.number(),
875
- frustrationLevel: zod_1.z.number(),
876
- goalProgress: zod_1.z.number(),
877
- confidenceLevel: zod_1.z.number(),
878
- currentMood: zod_1.z.enum(["neutral", "hopeful", "confused", "frustrated", "defeated", "relieved"]),
879
- stepCount: zod_1.z.number(),
880
- timeElapsed: zod_1.z.number(),
869
+ currentState: z.object({
870
+ patienceRemaining: z.number(),
871
+ confusionLevel: z.number(),
872
+ frustrationLevel: z.number(),
873
+ goalProgress: z.number(),
874
+ confidenceLevel: z.number(),
875
+ currentMood: z.enum(["neutral", "hopeful", "confused", "frustrated", "defeated", "relieved"]),
876
+ stepCount: z.number(),
877
+ timeElapsed: z.number(),
881
878
  }).describe("Current cognitive state"),
882
- actionResult: zod_1.z.object({
883
- success: zod_1.z.boolean(),
884
- wasConfusing: zod_1.z.boolean().optional(),
885
- progressMade: zod_1.z.boolean().optional(),
886
- wentBack: zod_1.z.boolean().optional(),
879
+ actionResult: z.object({
880
+ success: z.boolean(),
881
+ wasConfusing: z.boolean().optional(),
882
+ progressMade: z.boolean().optional(),
883
+ wentBack: z.boolean().optional(),
887
884
  }).describe("Result of the last action"),
888
- personaTraits: zod_1.z.object({
889
- patience: zod_1.z.number(),
890
- riskTolerance: zod_1.z.number(),
891
- comprehension: zod_1.z.number(),
892
- persistence: zod_1.z.number(),
885
+ personaTraits: z.object({
886
+ patience: z.number(),
887
+ riskTolerance: z.number(),
888
+ comprehension: z.number(),
889
+ persistence: z.number(),
893
890
  }).describe("Persona traits affecting state changes"),
894
891
  }, async ({ currentState, actionResult, personaTraits }) => {
895
892
  // Calculate new state based on action result
@@ -979,12 +976,12 @@ Begin the simulation now. Narrate your thoughts as this persona.
979
976
  };
980
977
  });
981
978
  server.tool("list_cognitive_personas", "List all available personas with their cognitive traits", {}, async () => {
982
- const names = (0, personas_js_1.listPersonas)();
979
+ const names = listPersonas();
983
980
  const personas = names.map(name => {
984
- const p = (0, personas_js_1.getPersona)(name);
981
+ const p = getPersona(name);
985
982
  if (!p)
986
983
  return null;
987
- const profile = (0, personas_js_1.getCognitiveProfile)(p);
984
+ const profile = getCognitiveProfile(p);
988
985
  return {
989
986
  name: p.name,
990
987
  description: p.description,
@@ -1007,11 +1004,11 @@ Begin the simulation now. Narrate your thoughts as this persona.
1007
1004
  // Performance Tools (v6.4.0+)
1008
1005
  // =========================================================================
1009
1006
  server.tool("perf_baseline", "Capture performance baseline for a URL", {
1010
- url: zod_1.z.string().url().describe("URL to capture baseline for"),
1011
- name: zod_1.z.string().describe("Name for the baseline"),
1012
- runs: zod_1.z.number().optional().default(3).describe("Number of runs to average"),
1007
+ url: z.string().url().describe("URL to capture baseline for"),
1008
+ name: z.string().describe("Name for the baseline"),
1009
+ runs: z.number().optional().default(3).describe("Number of runs to average"),
1013
1010
  }, async ({ url, name, runs }) => {
1014
- const result = await (0, index_js_4.capturePerformanceBaseline)(url, { name, runs });
1011
+ const result = await capturePerformanceBaseline(url, { name, runs });
1015
1012
  return {
1016
1013
  content: [
1017
1014
  {
@@ -1029,12 +1026,12 @@ Begin the simulation now. Narrate your thoughts as this persona.
1029
1026
  };
1030
1027
  });
1031
1028
  server.tool("perf_regression", "Detect performance regression against baseline with configurable sensitivity. Uses dual thresholds: both percentage AND absolute change must be exceeded. Profiles: strict (CI/CD, FCP 10%/50ms), normal (default, FCP 20%/100ms), lenient (dev, FCP 30%/200ms). Sub-50ms FCP variations ignored by default.", {
1032
- url: zod_1.z.string().url().describe("URL to test"),
1033
- baselineName: zod_1.z.string().describe("Name of baseline to compare against"),
1034
- sensitivity: zod_1.z.enum(["strict", "normal", "lenient"]).optional().default("normal").describe("Sensitivity profile: strict (CI/CD), normal (default), lenient (development)"),
1035
- thresholdLcp: zod_1.z.number().optional().describe("Override LCP threshold percentage"),
1029
+ url: z.string().url().describe("URL to test"),
1030
+ baselineName: z.string().describe("Name of baseline to compare against"),
1031
+ sensitivity: z.enum(["strict", "normal", "lenient"]).optional().default("normal").describe("Sensitivity profile: strict (CI/CD), normal (default), lenient (development)"),
1032
+ thresholdLcp: z.number().optional().describe("Override LCP threshold percentage"),
1036
1033
  }, async ({ url, baselineName, sensitivity, thresholdLcp }) => {
1037
- const result = await (0, index_js_4.detectPerformanceRegression)(url, baselineName, {
1034
+ const result = await detectPerformanceRegression(url, baselineName, {
1038
1035
  sensitivity,
1039
1036
  thresholds: thresholdLcp ? { lcp: thresholdLcp } : undefined,
1040
1037
  });
@@ -1055,8 +1052,8 @@ Begin the simulation now. Narrate your thoughts as this persona.
1055
1052
  };
1056
1053
  });
1057
1054
  server.tool("list_baselines", "List all saved baselines (visual and performance)", {}, async () => {
1058
- const visualBaselines = await (0, index_js_1.listVisualBaselines)();
1059
- const perfBaselines = await (0, index_js_4.listPerformanceBaselines)();
1055
+ const visualBaselines = await listVisualBaselines();
1056
+ const perfBaselines = await listPerformanceBaselines();
1060
1057
  return {
1061
1058
  content: [
1062
1059
  {
@@ -1073,7 +1070,7 @@ Begin the simulation now. Narrate your thoughts as this persona.
1073
1070
  // Diagnostics Tools
1074
1071
  // =========================================================================
1075
1072
  server.tool("status", "Get CBrowser environment status and diagnostics including data directories, installed browsers, configuration, and self-healing cache statistics", {}, async () => {
1076
- const info = await (0, config_js_1.getStatusInfo)(VERSION);
1073
+ const info = await getStatusInfo(VERSION);
1077
1074
  return {
1078
1075
  content: [
1079
1076
  {
@@ -1084,7 +1081,7 @@ Begin the simulation now. Narrate your thoughts as this persona.
1084
1081
  };
1085
1082
  });
1086
1083
  // Connect via stdio transport
1087
- const transport = new stdio_js_1.StdioServerTransport();
1084
+ const transport = new StdioServerTransport();
1088
1085
  await server.connect(transport);
1089
1086
  // Handle shutdown
1090
1087
  process.on("SIGINT", async () => {