@browserstack/mcp-server 1.2.14 → 1.2.15-beta.2

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 (170) hide show
  1. package/dist/lib/percy-api/auth.d.ts +41 -0
  2. package/dist/lib/percy-api/auth.js +96 -0
  3. package/dist/lib/percy-api/cache.d.ts +28 -0
  4. package/dist/lib/percy-api/cache.js +48 -0
  5. package/dist/lib/percy-api/client.d.ts +69 -0
  6. package/dist/lib/percy-api/client.js +275 -0
  7. package/dist/lib/percy-api/errors.d.ts +15 -0
  8. package/dist/lib/percy-api/errors.js +52 -0
  9. package/dist/lib/percy-api/formatter.d.ts +16 -0
  10. package/dist/lib/percy-api/formatter.js +344 -0
  11. package/dist/lib/percy-api/percy-auth.d.ts +43 -0
  12. package/dist/lib/percy-api/percy-auth.js +137 -0
  13. package/dist/lib/percy-api/percy-error-handler.d.ts +24 -0
  14. package/dist/lib/percy-api/percy-error-handler.js +302 -0
  15. package/dist/lib/percy-api/percy-session.d.ts +42 -0
  16. package/dist/lib/percy-api/percy-session.js +87 -0
  17. package/dist/lib/percy-api/polling.d.ts +26 -0
  18. package/dist/lib/percy-api/polling.js +42 -0
  19. package/dist/lib/percy-api/types.d.ts +56 -0
  20. package/dist/lib/percy-api/types.js +76 -0
  21. package/dist/server-factory.js +4 -0
  22. package/dist/tools/percy-mcp/advanced/branchline-operations.d.ts +16 -0
  23. package/dist/tools/percy-mcp/advanced/branchline-operations.js +81 -0
  24. package/dist/tools/percy-mcp/advanced/manage-variants.d.ts +16 -0
  25. package/dist/tools/percy-mcp/advanced/manage-variants.js +155 -0
  26. package/dist/tools/percy-mcp/advanced/manage-visual-monitoring.d.ts +16 -0
  27. package/dist/tools/percy-mcp/advanced/manage-visual-monitoring.js +171 -0
  28. package/dist/tools/percy-mcp/auth/auth-status.d.ts +3 -0
  29. package/dist/tools/percy-mcp/auth/auth-status.js +131 -0
  30. package/dist/tools/percy-mcp/core/approve-build.d.ts +14 -0
  31. package/dist/tools/percy-mcp/core/approve-build.js +97 -0
  32. package/dist/tools/percy-mcp/core/get-build-items.d.ts +13 -0
  33. package/dist/tools/percy-mcp/core/get-build-items.js +65 -0
  34. package/dist/tools/percy-mcp/core/get-build.d.ts +10 -0
  35. package/dist/tools/percy-mcp/core/get-build.js +16 -0
  36. package/dist/tools/percy-mcp/core/get-comparison.d.ts +11 -0
  37. package/dist/tools/percy-mcp/core/get-comparison.js +59 -0
  38. package/dist/tools/percy-mcp/core/get-snapshot.d.ts +10 -0
  39. package/dist/tools/percy-mcp/core/get-snapshot.js +40 -0
  40. package/dist/tools/percy-mcp/core/list-builds.d.ts +14 -0
  41. package/dist/tools/percy-mcp/core/list-builds.js +45 -0
  42. package/dist/tools/percy-mcp/core/list-projects.d.ts +12 -0
  43. package/dist/tools/percy-mcp/core/list-projects.js +51 -0
  44. package/dist/tools/percy-mcp/creation/create-app-snapshot.d.ts +12 -0
  45. package/dist/tools/percy-mcp/creation/create-app-snapshot.js +29 -0
  46. package/dist/tools/percy-mcp/creation/create-build.d.ts +19 -0
  47. package/dist/tools/percy-mcp/creation/create-build.js +68 -0
  48. package/dist/tools/percy-mcp/creation/create-comparison.d.ts +18 -0
  49. package/dist/tools/percy-mcp/creation/create-comparison.js +90 -0
  50. package/dist/tools/percy-mcp/creation/create-snapshot.d.ts +17 -0
  51. package/dist/tools/percy-mcp/creation/create-snapshot.js +99 -0
  52. package/dist/tools/percy-mcp/creation/finalize-build.d.ts +12 -0
  53. package/dist/tools/percy-mcp/creation/finalize-build.js +33 -0
  54. package/dist/tools/percy-mcp/creation/finalize-comparison.d.ts +10 -0
  55. package/dist/tools/percy-mcp/creation/finalize-comparison.js +16 -0
  56. package/dist/tools/percy-mcp/creation/finalize-snapshot.d.ts +12 -0
  57. package/dist/tools/percy-mcp/creation/finalize-snapshot.js +33 -0
  58. package/dist/tools/percy-mcp/creation/upload-resource.d.ts +15 -0
  59. package/dist/tools/percy-mcp/creation/upload-resource.js +43 -0
  60. package/dist/tools/percy-mcp/creation/upload-tile.d.ts +11 -0
  61. package/dist/tools/percy-mcp/creation/upload-tile.js +53 -0
  62. package/dist/tools/percy-mcp/diagnostics/analyze-logs-realtime.d.ts +13 -0
  63. package/dist/tools/percy-mcp/diagnostics/analyze-logs-realtime.js +65 -0
  64. package/dist/tools/percy-mcp/diagnostics/get-build-logs.d.ts +17 -0
  65. package/dist/tools/percy-mcp/diagnostics/get-build-logs.js +74 -0
  66. package/dist/tools/percy-mcp/diagnostics/get-network-logs.d.ts +5 -0
  67. package/dist/tools/percy-mcp/diagnostics/get-network-logs.js +21 -0
  68. package/dist/tools/percy-mcp/diagnostics/get-suggestions.d.ts +7 -0
  69. package/dist/tools/percy-mcp/diagnostics/get-suggestions.js +24 -0
  70. package/dist/tools/percy-mcp/index.d.ts +36 -0
  71. package/dist/tools/percy-mcp/index.js +1137 -0
  72. package/dist/tools/percy-mcp/intelligence/get-ai-analysis.d.ts +15 -0
  73. package/dist/tools/percy-mcp/intelligence/get-ai-analysis.js +166 -0
  74. package/dist/tools/percy-mcp/intelligence/get-ai-quota.d.ts +9 -0
  75. package/dist/tools/percy-mcp/intelligence/get-ai-quota.js +73 -0
  76. package/dist/tools/percy-mcp/intelligence/get-build-summary.d.ts +11 -0
  77. package/dist/tools/percy-mcp/intelligence/get-build-summary.js +78 -0
  78. package/dist/tools/percy-mcp/intelligence/get-rca.d.ts +6 -0
  79. package/dist/tools/percy-mcp/intelligence/get-rca.js +153 -0
  80. package/dist/tools/percy-mcp/intelligence/suggest-prompt.d.ts +15 -0
  81. package/dist/tools/percy-mcp/intelligence/suggest-prompt.js +86 -0
  82. package/dist/tools/percy-mcp/intelligence/trigger-ai-recompute.d.ts +16 -0
  83. package/dist/tools/percy-mcp/intelligence/trigger-ai-recompute.js +64 -0
  84. package/dist/tools/percy-mcp/management/create-project.d.ts +14 -0
  85. package/dist/tools/percy-mcp/management/create-project.js +52 -0
  86. package/dist/tools/percy-mcp/management/get-usage-stats.d.ts +12 -0
  87. package/dist/tools/percy-mcp/management/get-usage-stats.js +61 -0
  88. package/dist/tools/percy-mcp/management/manage-browser-targets.d.ts +12 -0
  89. package/dist/tools/percy-mcp/management/manage-browser-targets.js +136 -0
  90. package/dist/tools/percy-mcp/management/manage-comments.d.ts +14 -0
  91. package/dist/tools/percy-mcp/management/manage-comments.js +147 -0
  92. package/dist/tools/percy-mcp/management/manage-ignored-regions.d.ts +18 -0
  93. package/dist/tools/percy-mcp/management/manage-ignored-regions.js +182 -0
  94. package/dist/tools/percy-mcp/management/manage-project-settings.d.ts +16 -0
  95. package/dist/tools/percy-mcp/management/manage-project-settings.js +97 -0
  96. package/dist/tools/percy-mcp/management/manage-tokens.d.ts +14 -0
  97. package/dist/tools/percy-mcp/management/manage-tokens.js +90 -0
  98. package/dist/tools/percy-mcp/management/manage-webhooks.d.ts +15 -0
  99. package/dist/tools/percy-mcp/management/manage-webhooks.js +180 -0
  100. package/dist/tools/percy-mcp/v2/auth-status.d.ts +3 -0
  101. package/dist/tools/percy-mcp/v2/auth-status.js +80 -0
  102. package/dist/tools/percy-mcp/v2/clone-build.d.ts +24 -0
  103. package/dist/tools/percy-mcp/v2/clone-build.js +539 -0
  104. package/dist/tools/percy-mcp/v2/create-app-build.d.ts +28 -0
  105. package/dist/tools/percy-mcp/v2/create-app-build.js +442 -0
  106. package/dist/tools/percy-mcp/v2/create-build.d.ts +16 -0
  107. package/dist/tools/percy-mcp/v2/create-build.js +601 -0
  108. package/dist/tools/percy-mcp/v2/create-project.d.ts +8 -0
  109. package/dist/tools/percy-mcp/v2/create-project.js +33 -0
  110. package/dist/tools/percy-mcp/v2/discover-urls.d.ts +7 -0
  111. package/dist/tools/percy-mcp/v2/discover-urls.js +38 -0
  112. package/dist/tools/percy-mcp/v2/figma-baseline.d.ts +7 -0
  113. package/dist/tools/percy-mcp/v2/figma-baseline.js +18 -0
  114. package/dist/tools/percy-mcp/v2/figma-build.d.ts +7 -0
  115. package/dist/tools/percy-mcp/v2/figma-build.js +39 -0
  116. package/dist/tools/percy-mcp/v2/figma-link.d.ts +6 -0
  117. package/dist/tools/percy-mcp/v2/figma-link.js +27 -0
  118. package/dist/tools/percy-mcp/v2/get-ai-summary.d.ts +5 -0
  119. package/dist/tools/percy-mcp/v2/get-ai-summary.js +109 -0
  120. package/dist/tools/percy-mcp/v2/get-build-detail.d.ts +22 -0
  121. package/dist/tools/percy-mcp/v2/get-build-detail.js +567 -0
  122. package/dist/tools/percy-mcp/v2/get-builds.d.ts +8 -0
  123. package/dist/tools/percy-mcp/v2/get-builds.js +63 -0
  124. package/dist/tools/percy-mcp/v2/get-comparison.d.ts +5 -0
  125. package/dist/tools/percy-mcp/v2/get-comparison.js +94 -0
  126. package/dist/tools/percy-mcp/v2/get-devices.d.ts +5 -0
  127. package/dist/tools/percy-mcp/v2/get-devices.js +33 -0
  128. package/dist/tools/percy-mcp/v2/get-insights.d.ts +7 -0
  129. package/dist/tools/percy-mcp/v2/get-insights.js +52 -0
  130. package/dist/tools/percy-mcp/v2/get-projects.d.ts +6 -0
  131. package/dist/tools/percy-mcp/v2/get-projects.js +41 -0
  132. package/dist/tools/percy-mcp/v2/get-snapshot.d.ts +5 -0
  133. package/dist/tools/percy-mcp/v2/get-snapshot.js +96 -0
  134. package/dist/tools/percy-mcp/v2/get-test-case-history.d.ts +5 -0
  135. package/dist/tools/percy-mcp/v2/get-test-case-history.js +20 -0
  136. package/dist/tools/percy-mcp/v2/get-test-cases.d.ts +6 -0
  137. package/dist/tools/percy-mcp/v2/get-test-cases.js +36 -0
  138. package/dist/tools/percy-mcp/v2/index.d.ts +35 -0
  139. package/dist/tools/percy-mcp/v2/index.js +544 -0
  140. package/dist/tools/percy-mcp/v2/list-integrations.d.ts +5 -0
  141. package/dist/tools/percy-mcp/v2/list-integrations.js +41 -0
  142. package/dist/tools/percy-mcp/v2/manage-domains.d.ts +8 -0
  143. package/dist/tools/percy-mcp/v2/manage-domains.js +33 -0
  144. package/dist/tools/percy-mcp/v2/manage-insights-email.d.ts +8 -0
  145. package/dist/tools/percy-mcp/v2/manage-insights-email.js +49 -0
  146. package/dist/tools/percy-mcp/v2/manage-usage-alerts.d.ts +10 -0
  147. package/dist/tools/percy-mcp/v2/manage-usage-alerts.js +43 -0
  148. package/dist/tools/percy-mcp/v2/migrate-integrations.d.ts +6 -0
  149. package/dist/tools/percy-mcp/v2/migrate-integrations.js +20 -0
  150. package/dist/tools/percy-mcp/v2/preview-comparison.d.ts +5 -0
  151. package/dist/tools/percy-mcp/v2/preview-comparison.js +17 -0
  152. package/dist/tools/percy-mcp/v2/search-build-items.d.ts +12 -0
  153. package/dist/tools/percy-mcp/v2/search-build-items.js +45 -0
  154. package/dist/tools/percy-mcp/workflows/auto-triage.d.ts +7 -0
  155. package/dist/tools/percy-mcp/workflows/auto-triage.js +82 -0
  156. package/dist/tools/percy-mcp/workflows/clone-build.d.ts +22 -0
  157. package/dist/tools/percy-mcp/workflows/clone-build.js +414 -0
  158. package/dist/tools/percy-mcp/workflows/create-percy-build.d.ts +32 -0
  159. package/dist/tools/percy-mcp/workflows/create-percy-build.js +434 -0
  160. package/dist/tools/percy-mcp/workflows/debug-failed-build.d.ts +5 -0
  161. package/dist/tools/percy-mcp/workflows/debug-failed-build.js +122 -0
  162. package/dist/tools/percy-mcp/workflows/diff-explain.d.ts +6 -0
  163. package/dist/tools/percy-mcp/workflows/diff-explain.js +147 -0
  164. package/dist/tools/percy-mcp/workflows/pr-visual-report.d.ts +8 -0
  165. package/dist/tools/percy-mcp/workflows/pr-visual-report.js +184 -0
  166. package/dist/tools/percy-mcp/workflows/run-tests.d.ts +17 -0
  167. package/dist/tools/percy-mcp/workflows/run-tests.js +107 -0
  168. package/dist/tools/percy-mcp/workflows/snapshot-urls.d.ts +18 -0
  169. package/dist/tools/percy-mcp/workflows/snapshot-urls.js +197 -0
  170. package/package.json +4 -3
@@ -0,0 +1,49 @@
1
+ import { percyGet, percyPost, percyPatch, } from "../../../lib/percy-api/percy-auth.js";
2
+ export async function percyManageInsightsEmail(args, config) {
3
+ const action = args.action || "get";
4
+ if (action === "get") {
5
+ const response = await percyGet(`/organizations/${args.org_id}/insights-email-settings`, config);
6
+ const data = response?.data?.attributes || {};
7
+ let output = `## Insights Email Settings\n\n`;
8
+ output += `**Enabled:** ${data["is-enabled"] ?? data.isEnabled ?? "unknown"}\n`;
9
+ output += `**Recipients:** ${(data.emails || []).join(", ") || "none"}\n`;
10
+ return { content: [{ type: "text", text: output }] };
11
+ }
12
+ if (action === "create" || action === "update") {
13
+ const emailList = args.emails
14
+ ? args.emails.split(",").map((e) => e.trim())
15
+ : [];
16
+ const body = {
17
+ data: {
18
+ type: "insights-email-settings",
19
+ attributes: {
20
+ emails: emailList,
21
+ "is-enabled": args.enabled !== false,
22
+ },
23
+ },
24
+ };
25
+ if (action === "create") {
26
+ await percyPost(`/organizations/${args.org_id}/insights-email-settings`, config, body);
27
+ }
28
+ else {
29
+ await percyPatch(`/insights-email-settings/${args.org_id}`, config, body);
30
+ }
31
+ return {
32
+ content: [
33
+ {
34
+ type: "text",
35
+ text: `Insights email ${action}d. Recipients: ${emailList.join(", ")}`,
36
+ },
37
+ ],
38
+ };
39
+ }
40
+ return {
41
+ content: [
42
+ {
43
+ type: "text",
44
+ text: `Unknown action: ${action}. Use get, create, or update.`,
45
+ },
46
+ ],
47
+ isError: true,
48
+ };
49
+ }
@@ -0,0 +1,10 @@
1
+ import { BrowserStackConfig } from "../../../lib/types.js";
2
+ import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
3
+ export declare function percyManageUsageAlerts(args: {
4
+ org_id: string;
5
+ action?: string;
6
+ threshold?: number;
7
+ emails?: string;
8
+ enabled?: boolean;
9
+ product?: string;
10
+ }, config: BrowserStackConfig): Promise<CallToolResult>;
@@ -0,0 +1,43 @@
1
+ import { percyGet, percyPost, percyPatch, } from "../../../lib/percy-api/percy-auth.js";
2
+ export async function percyManageUsageAlerts(args, config) {
3
+ const action = args.action || "get";
4
+ if (action === "get") {
5
+ const response = await percyGet(`/organizations/${args.org_id}/usage_notification_settings`, config, {
6
+ "data[attributes][type]": args.product || "web",
7
+ });
8
+ const data = response?.data?.attributes || {};
9
+ let output = `## Usage Alert Settings\n\n`;
10
+ output += `**Enabled:** ${data["is-enabled"] ?? "unknown"}\n`;
11
+ output += `**Thresholds:** ${JSON.stringify(data.thresholds || {})}\n`;
12
+ output += `**Emails:** ${(data.emails || []).join(", ") || "none"}\n`;
13
+ return { content: [{ type: "text", text: output }] };
14
+ }
15
+ const emailList = args.emails
16
+ ? args.emails.split(",").map((e) => e.trim())
17
+ : [];
18
+ const body = {
19
+ data: {
20
+ type: "usage-notification-settings",
21
+ attributes: {
22
+ type: args.product || "web",
23
+ "is-enabled": args.enabled !== false,
24
+ thresholds: args.threshold ? { "snapshot-count": args.threshold } : {},
25
+ emails: emailList,
26
+ },
27
+ },
28
+ };
29
+ if (action === "create") {
30
+ await percyPost(`/organization/${args.org_id}/usage-notification-settings`, config, body);
31
+ }
32
+ else {
33
+ await percyPatch(`/usage-notification-settings/${args.org_id}`, config, body);
34
+ }
35
+ return {
36
+ content: [
37
+ {
38
+ type: "text",
39
+ text: `Usage alerts ${action}d. Threshold: ${args.threshold || "default"}`,
40
+ },
41
+ ],
42
+ };
43
+ }
@@ -0,0 +1,6 @@
1
+ import { BrowserStackConfig } from "../../../lib/types.js";
2
+ import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
3
+ export declare function percyMigrateIntegrations(args: {
4
+ source_org_id: string;
5
+ target_org_id: string;
6
+ }, config: BrowserStackConfig): Promise<CallToolResult>;
@@ -0,0 +1,20 @@
1
+ import { percyPost } from "../../../lib/percy-api/percy-auth.js";
2
+ export async function percyMigrateIntegrations(args, config) {
3
+ await percyPost("/integration-migrations/migrate", config, {
4
+ data: {
5
+ type: "integration-migrations",
6
+ attributes: {
7
+ "source-organization-id": args.source_org_id,
8
+ "target-organization-id": args.target_org_id,
9
+ },
10
+ },
11
+ });
12
+ return {
13
+ content: [
14
+ {
15
+ type: "text",
16
+ text: `## Integration Migration\n\nIntegrations migrated from org ${args.source_org_id} to ${args.target_org_id}.`,
17
+ },
18
+ ],
19
+ };
20
+ }
@@ -0,0 +1,5 @@
1
+ import { BrowserStackConfig } from "../../../lib/types.js";
2
+ import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
3
+ export declare function percyPreviewComparison(args: {
4
+ comparison_id: string;
5
+ }, config: BrowserStackConfig): Promise<CallToolResult>;
@@ -0,0 +1,17 @@
1
+ import { percyPost } from "../../../lib/percy-api/percy-auth.js";
2
+ export async function percyPreviewComparison(args, config) {
3
+ await percyPost("/comparison-previews", config, {
4
+ data: {
5
+ type: "comparison-previews",
6
+ attributes: { "comparison-id": args.comparison_id },
7
+ },
8
+ });
9
+ return {
10
+ content: [
11
+ {
12
+ type: "text",
13
+ text: `## Comparison Preview\n\nRecomputation triggered for comparison ${args.comparison_id}.\nThe diff will be re-processed with current AI and region settings.\nRefresh the build in Percy to see updated results.`,
14
+ },
15
+ ],
16
+ };
17
+ }
@@ -0,0 +1,12 @@
1
+ import { BrowserStackConfig } from "../../../lib/types.js";
2
+ import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
3
+ export declare function percySearchBuildItems(args: {
4
+ build_id: string;
5
+ category?: string;
6
+ browser_ids?: string;
7
+ widths?: string;
8
+ os?: string;
9
+ device_name?: string;
10
+ sort_by?: string;
11
+ limit?: number;
12
+ }, config: BrowserStackConfig): Promise<CallToolResult>;
@@ -0,0 +1,45 @@
1
+ import { percyGet } from "../../../lib/percy-api/percy-auth.js";
2
+ export async function percySearchBuildItems(args, config) {
3
+ const params = { "filter[build-id]": args.build_id };
4
+ if (args.category)
5
+ params["filter[category]"] = args.category;
6
+ if (args.sort_by)
7
+ params["filter[sort_by]"] = args.sort_by;
8
+ if (args.limit)
9
+ params["page[limit]"] = String(args.limit);
10
+ // Array filters
11
+ if (args.browser_ids)
12
+ args.browser_ids.split(",").forEach((id) => {
13
+ params[`filter[browser_ids][]`] = id.trim();
14
+ });
15
+ if (args.widths)
16
+ args.widths.split(",").forEach((w) => {
17
+ params[`filter[widths][]`] = w.trim();
18
+ });
19
+ if (args.os)
20
+ params["filter[os]"] = args.os;
21
+ if (args.device_name)
22
+ params["filter[device_name]"] = args.device_name;
23
+ const response = await percyGet("/build-items", config, params);
24
+ const items = response?.data || [];
25
+ if (!items.length) {
26
+ return {
27
+ content: [
28
+ { type: "text", text: "No items match the specified filters." },
29
+ ],
30
+ };
31
+ }
32
+ let output = `## Build Items (${items.length})\n\n`;
33
+ output += `| # | Name | Diff | Review | Items |\n|---|---|---|---|---|\n`;
34
+ items.forEach((item, i) => {
35
+ const attrs = item.attributes || item;
36
+ const name = attrs.coverSnapshotName || attrs["cover-snapshot-name"] || "?";
37
+ const diff = attrs.maxDiffRatio != null
38
+ ? `${(attrs.maxDiffRatio * 100).toFixed(1)}%`
39
+ : "—";
40
+ const review = attrs.reviewState || attrs["review-state"] || "?";
41
+ const count = attrs.itemCount || attrs["item-count"] || 1;
42
+ output += `| ${i + 1} | ${name} | ${diff} | ${review} | ${count} |\n`;
43
+ });
44
+ return { content: [{ type: "text", text: output }] };
45
+ }
@@ -0,0 +1,7 @@
1
+ import { BrowserStackConfig } from "../../../lib/types.js";
2
+ import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
3
+ export declare function percyAutoTriage(args: {
4
+ build_id: string;
5
+ noise_threshold?: number;
6
+ review_threshold?: number;
7
+ }, config: BrowserStackConfig): Promise<CallToolResult>;
@@ -0,0 +1,82 @@
1
+ import { PercyClient } from "../../../lib/percy-api/client.js";
2
+ export async function percyAutoTriage(args, config) {
3
+ const client = new PercyClient(config);
4
+ const noiseThreshold = args.noise_threshold ?? 0.005; // 0.5%
5
+ const reviewThreshold = args.review_threshold ?? 0.15; // 15%
6
+ // Get all changed build items (limit to 90 = 3 pages max)
7
+ const items = await client.get("/build-items", {
8
+ "filter[build-id]": args.build_id,
9
+ "filter[category]": "changed",
10
+ "page[limit]": "30",
11
+ });
12
+ const itemList = Array.isArray(items) ? items : [];
13
+ const critical = [];
14
+ const reviewRequired = [];
15
+ const autoApprovable = [];
16
+ const noise = [];
17
+ for (const item of itemList) {
18
+ const name = item.name || item.snapshotName || "Unknown";
19
+ const diffRatio = item.diffRatio ?? item.maxDiffRatio ?? 0;
20
+ const potentialBugs = item.totalPotentialBugs || 0;
21
+ const aiIgnored = item.aiDiffRatio !== undefined && item.aiDiffRatio === 0 && diffRatio > 0;
22
+ const entry = { name, diffRatio, potentialBugs };
23
+ if (potentialBugs > 0) {
24
+ critical.push(entry);
25
+ }
26
+ else if (aiIgnored) {
27
+ autoApprovable.push({ ...entry, reason: "AI-filtered (IntelliIgnore)" });
28
+ }
29
+ else if (diffRatio > reviewThreshold) {
30
+ reviewRequired.push(entry);
31
+ }
32
+ else if (diffRatio <= noiseThreshold) {
33
+ noise.push(entry);
34
+ }
35
+ else {
36
+ autoApprovable.push({ ...entry, reason: "Low diff ratio" });
37
+ }
38
+ }
39
+ let output = `## Auto-Triage — Build #${args.build_id}\n\n`;
40
+ output += `**Total changed:** ${itemList.length} | `;
41
+ output += `Critical: ${critical.length} | Review: ${reviewRequired.length} | `;
42
+ output += `Auto-approvable: ${autoApprovable.length} | Noise: ${noise.length}\n\n`;
43
+ if (critical.length > 0) {
44
+ output += `### CRITICAL — Potential Bugs (${critical.length})\n`;
45
+ critical.forEach((e, i) => {
46
+ output += `${i + 1}. **${e.name}** — ${(e.diffRatio * 100).toFixed(1)}% diff, ${e.potentialBugs} bug(s)\n`;
47
+ });
48
+ output += "\n";
49
+ }
50
+ if (reviewRequired.length > 0) {
51
+ output += `### REVIEW REQUIRED (${reviewRequired.length})\n`;
52
+ reviewRequired.forEach((e, i) => {
53
+ output += `${i + 1}. **${e.name}** — ${(e.diffRatio * 100).toFixed(1)}% diff\n`;
54
+ });
55
+ output += "\n";
56
+ }
57
+ if (autoApprovable.length > 0) {
58
+ output += `### AUTO-APPROVABLE (${autoApprovable.length})\n`;
59
+ autoApprovable.forEach((e, i) => {
60
+ output += `${i + 1}. ${e.name} — ${e.reason}\n`;
61
+ });
62
+ output += "\n";
63
+ }
64
+ if (noise.length > 0) {
65
+ output += `### NOISE (${noise.length})\n`;
66
+ output += noise.map((e) => e.name).join(", ") + "\n\n";
67
+ }
68
+ output += `### Recommended Action\n\n`;
69
+ if (critical.length > 0) {
70
+ output += `Investigate ${critical.length} critical item(s) before approving.\n`;
71
+ }
72
+ else if (reviewRequired.length > 0) {
73
+ output += `Review ${reviewRequired.length} item(s) manually. ${autoApprovable.length + noise.length} can be auto-approved.\n`;
74
+ }
75
+ else {
76
+ output += `All changes are auto-approvable or noise. Safe to approve.\n`;
77
+ }
78
+ if (itemList.length >= 30) {
79
+ output += `\n> Note: Results limited to first 30 changed snapshots. Build may have more.\n`;
80
+ }
81
+ return { content: [{ type: "text", text: output }] };
82
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * percy_clone_build — Clone snapshots from a source build to a new build,
3
+ * even across different projects.
4
+ *
5
+ * Flow:
6
+ * 1. Read build-items to get snapshot IDs
7
+ * 2. For each snapshot: fetch raw JSON:API with includes to get image URLs
8
+ * 3. Create target build + snapshots + comparisons with downloaded screenshots
9
+ * 4. Finalize
10
+ */
11
+ import { BrowserStackConfig } from "../../../lib/types.js";
12
+ import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
13
+ interface CloneBuildArgs {
14
+ source_build_id: string;
15
+ source_token?: string;
16
+ target_project_name: string;
17
+ target_token?: string;
18
+ branch?: string;
19
+ commit_sha?: string;
20
+ }
21
+ export declare function percyCloneBuild(args: CloneBuildArgs, config: BrowserStackConfig): Promise<CallToolResult>;
22
+ export {};