@browserstack/mcp-server 1.2.15-beta.1 → 1.2.15-beta.3

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 (172) 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/build-items.d.ts +31 -0
  4. package/dist/lib/percy-api/build-items.js +61 -0
  5. package/dist/lib/percy-api/cache.d.ts +28 -0
  6. package/dist/lib/percy-api/cache.js +48 -0
  7. package/dist/lib/percy-api/client.d.ts +69 -0
  8. package/dist/lib/percy-api/client.js +275 -0
  9. package/dist/lib/percy-api/errors.d.ts +15 -0
  10. package/dist/lib/percy-api/errors.js +52 -0
  11. package/dist/lib/percy-api/formatter.d.ts +16 -0
  12. package/dist/lib/percy-api/formatter.js +344 -0
  13. package/dist/lib/percy-api/percy-auth.d.ts +43 -0
  14. package/dist/lib/percy-api/percy-auth.js +142 -0
  15. package/dist/lib/percy-api/percy-error-handler.d.ts +24 -0
  16. package/dist/lib/percy-api/percy-error-handler.js +302 -0
  17. package/dist/lib/percy-api/percy-session.d.ts +42 -0
  18. package/dist/lib/percy-api/percy-session.js +87 -0
  19. package/dist/lib/percy-api/polling.d.ts +26 -0
  20. package/dist/lib/percy-api/polling.js +42 -0
  21. package/dist/lib/percy-api/types.d.ts +56 -0
  22. package/dist/lib/percy-api/types.js +76 -0
  23. package/dist/server-factory.js +4 -0
  24. package/dist/tools/percy-mcp/advanced/branchline-operations.d.ts +16 -0
  25. package/dist/tools/percy-mcp/advanced/branchline-operations.js +81 -0
  26. package/dist/tools/percy-mcp/advanced/manage-variants.d.ts +16 -0
  27. package/dist/tools/percy-mcp/advanced/manage-variants.js +155 -0
  28. package/dist/tools/percy-mcp/advanced/manage-visual-monitoring.d.ts +16 -0
  29. package/dist/tools/percy-mcp/advanced/manage-visual-monitoring.js +171 -0
  30. package/dist/tools/percy-mcp/auth/auth-status.d.ts +3 -0
  31. package/dist/tools/percy-mcp/auth/auth-status.js +131 -0
  32. package/dist/tools/percy-mcp/core/approve-build.d.ts +14 -0
  33. package/dist/tools/percy-mcp/core/approve-build.js +97 -0
  34. package/dist/tools/percy-mcp/core/get-build-items.d.ts +13 -0
  35. package/dist/tools/percy-mcp/core/get-build-items.js +65 -0
  36. package/dist/tools/percy-mcp/core/get-build.d.ts +10 -0
  37. package/dist/tools/percy-mcp/core/get-build.js +16 -0
  38. package/dist/tools/percy-mcp/core/get-comparison.d.ts +11 -0
  39. package/dist/tools/percy-mcp/core/get-comparison.js +59 -0
  40. package/dist/tools/percy-mcp/core/get-snapshot.d.ts +10 -0
  41. package/dist/tools/percy-mcp/core/get-snapshot.js +40 -0
  42. package/dist/tools/percy-mcp/core/list-builds.d.ts +14 -0
  43. package/dist/tools/percy-mcp/core/list-builds.js +45 -0
  44. package/dist/tools/percy-mcp/core/list-projects.d.ts +12 -0
  45. package/dist/tools/percy-mcp/core/list-projects.js +51 -0
  46. package/dist/tools/percy-mcp/creation/create-app-snapshot.d.ts +12 -0
  47. package/dist/tools/percy-mcp/creation/create-app-snapshot.js +29 -0
  48. package/dist/tools/percy-mcp/creation/create-build.d.ts +19 -0
  49. package/dist/tools/percy-mcp/creation/create-build.js +68 -0
  50. package/dist/tools/percy-mcp/creation/create-comparison.d.ts +18 -0
  51. package/dist/tools/percy-mcp/creation/create-comparison.js +90 -0
  52. package/dist/tools/percy-mcp/creation/create-snapshot.d.ts +17 -0
  53. package/dist/tools/percy-mcp/creation/create-snapshot.js +99 -0
  54. package/dist/tools/percy-mcp/creation/finalize-build.d.ts +12 -0
  55. package/dist/tools/percy-mcp/creation/finalize-build.js +33 -0
  56. package/dist/tools/percy-mcp/creation/finalize-comparison.d.ts +10 -0
  57. package/dist/tools/percy-mcp/creation/finalize-comparison.js +16 -0
  58. package/dist/tools/percy-mcp/creation/finalize-snapshot.d.ts +12 -0
  59. package/dist/tools/percy-mcp/creation/finalize-snapshot.js +33 -0
  60. package/dist/tools/percy-mcp/creation/upload-resource.d.ts +15 -0
  61. package/dist/tools/percy-mcp/creation/upload-resource.js +43 -0
  62. package/dist/tools/percy-mcp/creation/upload-tile.d.ts +11 -0
  63. package/dist/tools/percy-mcp/creation/upload-tile.js +53 -0
  64. package/dist/tools/percy-mcp/diagnostics/analyze-logs-realtime.d.ts +13 -0
  65. package/dist/tools/percy-mcp/diagnostics/analyze-logs-realtime.js +65 -0
  66. package/dist/tools/percy-mcp/diagnostics/get-build-logs.d.ts +17 -0
  67. package/dist/tools/percy-mcp/diagnostics/get-build-logs.js +74 -0
  68. package/dist/tools/percy-mcp/diagnostics/get-network-logs.d.ts +5 -0
  69. package/dist/tools/percy-mcp/diagnostics/get-network-logs.js +21 -0
  70. package/dist/tools/percy-mcp/diagnostics/get-suggestions.d.ts +7 -0
  71. package/dist/tools/percy-mcp/diagnostics/get-suggestions.js +24 -0
  72. package/dist/tools/percy-mcp/index.d.ts +36 -0
  73. package/dist/tools/percy-mcp/index.js +1137 -0
  74. package/dist/tools/percy-mcp/intelligence/get-ai-analysis.d.ts +15 -0
  75. package/dist/tools/percy-mcp/intelligence/get-ai-analysis.js +166 -0
  76. package/dist/tools/percy-mcp/intelligence/get-ai-quota.d.ts +9 -0
  77. package/dist/tools/percy-mcp/intelligence/get-ai-quota.js +73 -0
  78. package/dist/tools/percy-mcp/intelligence/get-build-summary.d.ts +11 -0
  79. package/dist/tools/percy-mcp/intelligence/get-build-summary.js +78 -0
  80. package/dist/tools/percy-mcp/intelligence/get-rca.d.ts +6 -0
  81. package/dist/tools/percy-mcp/intelligence/get-rca.js +153 -0
  82. package/dist/tools/percy-mcp/intelligence/suggest-prompt.d.ts +15 -0
  83. package/dist/tools/percy-mcp/intelligence/suggest-prompt.js +86 -0
  84. package/dist/tools/percy-mcp/intelligence/trigger-ai-recompute.d.ts +16 -0
  85. package/dist/tools/percy-mcp/intelligence/trigger-ai-recompute.js +64 -0
  86. package/dist/tools/percy-mcp/management/create-project.d.ts +14 -0
  87. package/dist/tools/percy-mcp/management/create-project.js +52 -0
  88. package/dist/tools/percy-mcp/management/get-usage-stats.d.ts +12 -0
  89. package/dist/tools/percy-mcp/management/get-usage-stats.js +61 -0
  90. package/dist/tools/percy-mcp/management/manage-browser-targets.d.ts +12 -0
  91. package/dist/tools/percy-mcp/management/manage-browser-targets.js +136 -0
  92. package/dist/tools/percy-mcp/management/manage-comments.d.ts +14 -0
  93. package/dist/tools/percy-mcp/management/manage-comments.js +147 -0
  94. package/dist/tools/percy-mcp/management/manage-ignored-regions.d.ts +18 -0
  95. package/dist/tools/percy-mcp/management/manage-ignored-regions.js +182 -0
  96. package/dist/tools/percy-mcp/management/manage-project-settings.d.ts +16 -0
  97. package/dist/tools/percy-mcp/management/manage-project-settings.js +97 -0
  98. package/dist/tools/percy-mcp/management/manage-tokens.d.ts +14 -0
  99. package/dist/tools/percy-mcp/management/manage-tokens.js +90 -0
  100. package/dist/tools/percy-mcp/management/manage-webhooks.d.ts +15 -0
  101. package/dist/tools/percy-mcp/management/manage-webhooks.js +180 -0
  102. package/dist/tools/percy-mcp/v2/auth-status.d.ts +3 -0
  103. package/dist/tools/percy-mcp/v2/auth-status.js +80 -0
  104. package/dist/tools/percy-mcp/v2/clone-build.d.ts +24 -0
  105. package/dist/tools/percy-mcp/v2/clone-build.js +539 -0
  106. package/dist/tools/percy-mcp/v2/create-app-build.d.ts +28 -0
  107. package/dist/tools/percy-mcp/v2/create-app-build.js +442 -0
  108. package/dist/tools/percy-mcp/v2/create-build.d.ts +16 -0
  109. package/dist/tools/percy-mcp/v2/create-build.js +601 -0
  110. package/dist/tools/percy-mcp/v2/create-project.d.ts +8 -0
  111. package/dist/tools/percy-mcp/v2/create-project.js +33 -0
  112. package/dist/tools/percy-mcp/v2/discover-urls.d.ts +7 -0
  113. package/dist/tools/percy-mcp/v2/discover-urls.js +38 -0
  114. package/dist/tools/percy-mcp/v2/figma-baseline.d.ts +7 -0
  115. package/dist/tools/percy-mcp/v2/figma-baseline.js +18 -0
  116. package/dist/tools/percy-mcp/v2/figma-build.d.ts +7 -0
  117. package/dist/tools/percy-mcp/v2/figma-build.js +39 -0
  118. package/dist/tools/percy-mcp/v2/figma-link.d.ts +6 -0
  119. package/dist/tools/percy-mcp/v2/figma-link.js +27 -0
  120. package/dist/tools/percy-mcp/v2/get-ai-summary.d.ts +5 -0
  121. package/dist/tools/percy-mcp/v2/get-ai-summary.js +109 -0
  122. package/dist/tools/percy-mcp/v2/get-build-detail.d.ts +22 -0
  123. package/dist/tools/percy-mcp/v2/get-build-detail.js +566 -0
  124. package/dist/tools/percy-mcp/v2/get-builds.d.ts +8 -0
  125. package/dist/tools/percy-mcp/v2/get-builds.js +63 -0
  126. package/dist/tools/percy-mcp/v2/get-comparison.d.ts +5 -0
  127. package/dist/tools/percy-mcp/v2/get-comparison.js +95 -0
  128. package/dist/tools/percy-mcp/v2/get-devices.d.ts +5 -0
  129. package/dist/tools/percy-mcp/v2/get-devices.js +33 -0
  130. package/dist/tools/percy-mcp/v2/get-insights.d.ts +7 -0
  131. package/dist/tools/percy-mcp/v2/get-insights.js +52 -0
  132. package/dist/tools/percy-mcp/v2/get-projects.d.ts +6 -0
  133. package/dist/tools/percy-mcp/v2/get-projects.js +41 -0
  134. package/dist/tools/percy-mcp/v2/get-snapshot.d.ts +5 -0
  135. package/dist/tools/percy-mcp/v2/get-snapshot.js +93 -0
  136. package/dist/tools/percy-mcp/v2/get-test-case-history.d.ts +5 -0
  137. package/dist/tools/percy-mcp/v2/get-test-case-history.js +20 -0
  138. package/dist/tools/percy-mcp/v2/get-test-cases.d.ts +6 -0
  139. package/dist/tools/percy-mcp/v2/get-test-cases.js +36 -0
  140. package/dist/tools/percy-mcp/v2/index.d.ts +35 -0
  141. package/dist/tools/percy-mcp/v2/index.js +544 -0
  142. package/dist/tools/percy-mcp/v2/list-integrations.d.ts +5 -0
  143. package/dist/tools/percy-mcp/v2/list-integrations.js +41 -0
  144. package/dist/tools/percy-mcp/v2/manage-domains.d.ts +8 -0
  145. package/dist/tools/percy-mcp/v2/manage-domains.js +33 -0
  146. package/dist/tools/percy-mcp/v2/manage-insights-email.d.ts +8 -0
  147. package/dist/tools/percy-mcp/v2/manage-insights-email.js +49 -0
  148. package/dist/tools/percy-mcp/v2/manage-usage-alerts.d.ts +10 -0
  149. package/dist/tools/percy-mcp/v2/manage-usage-alerts.js +43 -0
  150. package/dist/tools/percy-mcp/v2/migrate-integrations.d.ts +6 -0
  151. package/dist/tools/percy-mcp/v2/migrate-integrations.js +20 -0
  152. package/dist/tools/percy-mcp/v2/preview-comparison.d.ts +5 -0
  153. package/dist/tools/percy-mcp/v2/preview-comparison.js +17 -0
  154. package/dist/tools/percy-mcp/v2/search-build-items.d.ts +12 -0
  155. package/dist/tools/percy-mcp/v2/search-build-items.js +59 -0
  156. package/dist/tools/percy-mcp/workflows/auto-triage.d.ts +7 -0
  157. package/dist/tools/percy-mcp/workflows/auto-triage.js +83 -0
  158. package/dist/tools/percy-mcp/workflows/clone-build.d.ts +22 -0
  159. package/dist/tools/percy-mcp/workflows/clone-build.js +414 -0
  160. package/dist/tools/percy-mcp/workflows/create-percy-build.d.ts +32 -0
  161. package/dist/tools/percy-mcp/workflows/create-percy-build.js +434 -0
  162. package/dist/tools/percy-mcp/workflows/debug-failed-build.d.ts +5 -0
  163. package/dist/tools/percy-mcp/workflows/debug-failed-build.js +122 -0
  164. package/dist/tools/percy-mcp/workflows/diff-explain.d.ts +6 -0
  165. package/dist/tools/percy-mcp/workflows/diff-explain.js +148 -0
  166. package/dist/tools/percy-mcp/workflows/pr-visual-report.d.ts +8 -0
  167. package/dist/tools/percy-mcp/workflows/pr-visual-report.js +185 -0
  168. package/dist/tools/percy-mcp/workflows/run-tests.d.ts +17 -0
  169. package/dist/tools/percy-mcp/workflows/run-tests.js +107 -0
  170. package/dist/tools/percy-mcp/workflows/snapshot-urls.d.ts +18 -0
  171. package/dist/tools/percy-mcp/workflows/snapshot-urls.js +197 -0
  172. package/package.json +3 -2
@@ -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,59 @@
1
+ import { percyGet } from "../../../lib/percy-api/percy-auth.js";
2
+ import { fetchAllBuildItems, formatDiffPercent, CHANGED_CATEGORY_PARAMS, } from "../../../lib/percy-api/build-items.js";
3
+ export async function percySearchBuildItems(args, config) {
4
+ const params = {
5
+ "filter[build-id]": args.build_id,
6
+ };
7
+ if (args.category === "changed") {
8
+ // The API resolves the changed category through subcategories; without
9
+ // them filter[category]=changed matches nothing.
10
+ Object.assign(params, CHANGED_CATEGORY_PARAMS);
11
+ }
12
+ else if (args.category) {
13
+ params["filter[category]"] = args.category;
14
+ }
15
+ if (args.sort_by)
16
+ params["filter[sort_by]"] = args.sort_by;
17
+ // Array filters
18
+ if (args.browser_ids)
19
+ params["filter[browser_ids][]"] = args.browser_ids
20
+ .split(",")
21
+ .map((id) => id.trim());
22
+ if (args.widths)
23
+ params["filter[widths][]"] = args.widths.split(",").map((w) => w.trim());
24
+ if (args.os)
25
+ params["filter[os]"] = args.os;
26
+ if (args.device_name)
27
+ params["filter[device_name]"] = args.device_name;
28
+ let items;
29
+ let truncated = false;
30
+ if (args.limit) {
31
+ params["page[limit]"] = String(args.limit);
32
+ const response = await percyGet("/build-items", config, params);
33
+ items = response?.data || [];
34
+ }
35
+ else {
36
+ ({ items, truncated } = await fetchAllBuildItems(config, params));
37
+ }
38
+ if (!items.length) {
39
+ return {
40
+ content: [
41
+ { type: "text", text: "No items match the specified filters." },
42
+ ],
43
+ };
44
+ }
45
+ let output = `## Build Items (${items.length})\n\n`;
46
+ output += `| # | Name | Diff | Review | Items |\n|---|---|---|---|---|\n`;
47
+ items.forEach((item, i) => {
48
+ const attrs = item.attributes || item;
49
+ const name = attrs.coverSnapshotName || attrs["cover-snapshot-name"] || "?";
50
+ const diff = formatDiffPercent(attrs.maxDiffRatio ?? attrs["max-diff-ratio"]);
51
+ const review = attrs.reviewState || attrs["review-state"] || "?";
52
+ const count = attrs.itemCount || attrs["item-count"] || 1;
53
+ output += `| ${i + 1} | ${name} | ${diff} | ${review} | ${count} |\n`;
54
+ });
55
+ if (truncated) {
56
+ output += `\n⚠️ Result may be incomplete — pagination could not be fully exhausted.\n`;
57
+ }
58
+ return { content: [{ type: "text", text: output }] };
59
+ }
@@ -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,83 @@
1
+ import { PercyClient } from "../../../lib/percy-api/client.js";
2
+ import { formatDiffPercent } from "../../../lib/percy-api/build-items.js";
3
+ export async function percyAutoTriage(args, config) {
4
+ const client = new PercyClient(config);
5
+ const noiseThreshold = args.noise_threshold ?? 0.005; // 0.5%
6
+ const reviewThreshold = args.review_threshold ?? 0.15; // 15%
7
+ // Get all changed build items (limit to 90 = 3 pages max)
8
+ const items = await client.get("/build-items", {
9
+ "filter[build-id]": args.build_id,
10
+ "filter[category]": "changed",
11
+ "page[limit]": "30",
12
+ });
13
+ const itemList = Array.isArray(items) ? items : [];
14
+ const critical = [];
15
+ const reviewRequired = [];
16
+ const autoApprovable = [];
17
+ const noise = [];
18
+ for (const item of itemList) {
19
+ const name = item.name || item.snapshotName || "Unknown";
20
+ const diffRatio = item.diffRatio ?? item.maxDiffRatio ?? 0;
21
+ const potentialBugs = item.totalPotentialBugs || 0;
22
+ const aiIgnored = item.aiDiffRatio !== undefined && item.aiDiffRatio === 0 && diffRatio > 0;
23
+ const entry = { name, diffRatio, potentialBugs };
24
+ if (potentialBugs > 0) {
25
+ critical.push(entry);
26
+ }
27
+ else if (aiIgnored) {
28
+ autoApprovable.push({ ...entry, reason: "AI-filtered (IntelliIgnore)" });
29
+ }
30
+ else if (diffRatio > reviewThreshold) {
31
+ reviewRequired.push(entry);
32
+ }
33
+ else if (diffRatio <= noiseThreshold) {
34
+ noise.push(entry);
35
+ }
36
+ else {
37
+ autoApprovable.push({ ...entry, reason: "Low diff ratio" });
38
+ }
39
+ }
40
+ let output = `## Auto-Triage — Build #${args.build_id}\n\n`;
41
+ output += `**Total changed:** ${itemList.length} | `;
42
+ output += `Critical: ${critical.length} | Review: ${reviewRequired.length} | `;
43
+ output += `Auto-approvable: ${autoApprovable.length} | Noise: ${noise.length}\n\n`;
44
+ if (critical.length > 0) {
45
+ output += `### CRITICAL — Potential Bugs (${critical.length})\n`;
46
+ critical.forEach((e, i) => {
47
+ output += `${i + 1}. **${e.name}** — ${formatDiffPercent(e.diffRatio)} diff, ${e.potentialBugs} bug(s)\n`;
48
+ });
49
+ output += "\n";
50
+ }
51
+ if (reviewRequired.length > 0) {
52
+ output += `### REVIEW REQUIRED (${reviewRequired.length})\n`;
53
+ reviewRequired.forEach((e, i) => {
54
+ output += `${i + 1}. **${e.name}** — ${formatDiffPercent(e.diffRatio)} diff\n`;
55
+ });
56
+ output += "\n";
57
+ }
58
+ if (autoApprovable.length > 0) {
59
+ output += `### AUTO-APPROVABLE (${autoApprovable.length})\n`;
60
+ autoApprovable.forEach((e, i) => {
61
+ output += `${i + 1}. ${e.name} — ${e.reason}\n`;
62
+ });
63
+ output += "\n";
64
+ }
65
+ if (noise.length > 0) {
66
+ output += `### NOISE (${noise.length})\n`;
67
+ output += noise.map((e) => e.name).join(", ") + "\n\n";
68
+ }
69
+ output += `### Recommended Action\n\n`;
70
+ if (critical.length > 0) {
71
+ output += `Investigate ${critical.length} critical item(s) before approving.\n`;
72
+ }
73
+ else if (reviewRequired.length > 0) {
74
+ output += `Review ${reviewRequired.length} item(s) manually. ${autoApprovable.length + noise.length} can be auto-approved.\n`;
75
+ }
76
+ else {
77
+ output += `All changes are auto-approvable or noise. Safe to approve.\n`;
78
+ }
79
+ if (itemList.length >= 30) {
80
+ output += `\n> Note: Results limited to first 30 changed snapshots. Build may have more.\n`;
81
+ }
82
+ return { content: [{ type: "text", text: output }] };
83
+ }
@@ -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 {};