@browserstack/mcp-server 1.2.36-beta.2 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/tools/accessibility.js +30 -0
- package/dist/tools/appautomate.js +20 -2
- package/dist/tools/applive.js +6 -0
- package/dist/tools/automate.js +6 -0
- package/dist/tools/bstack-sdk.js +7 -1
- package/dist/tools/build-insights.js +6 -0
- package/dist/tools/get-failure-logs.js +6 -0
- package/dist/tools/live.js +7 -1
- package/dist/tools/observability.js +6 -0
- package/dist/tools/percy-sdk.js +49 -7
- package/dist/tools/rca-agent.js +28 -4
- package/dist/tools/selfheal.js +12 -0
- package/dist/tools/testmanagement.js +119 -17
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -41,6 +41,8 @@ Click on the buttons below to install MCP in your respective IDE:
|
|
|
41
41
|
|
|
42
42
|
<a href="http://mcp.browserstack.com/one-click-setup?client=vscode"><img src="assets/one-click-vs-code.png" alt="Install in VS Code" width="160" height="80"></a> <a href="http://mcp.browserstack.com/one-click-setup?client=cursor"><img src="assets/one-click-cursor.png" alt="Install in Cursor" width="150" height="70"></a>
|
|
43
43
|
|
|
44
|
+
> **Note:** The hosted Remote MCP server (`mcp.browserstack.com`) is now fully stateless over Streamable HTTP — any Streamable-HTTP client (Claude, Cursor, VS Code, ChatGPT) connects with no configuration change.
|
|
45
|
+
|
|
44
46
|
#### Note : Ensure you are using Node version >= `18.0`
|
|
45
47
|
- Check your node version using `node --version`. Recommended version: `v22.15.0` (LTS)
|
|
46
48
|
- To Upgrade Node :
|
|
@@ -213,6 +213,12 @@ export default function addAccessibilityTools(server, config) {
|
|
|
213
213
|
query: z
|
|
214
214
|
.string()
|
|
215
215
|
.describe("Any accessibility, a11y, WCAG, or web accessibility question"),
|
|
216
|
+
}, {
|
|
217
|
+
title: "Accessibility Expert",
|
|
218
|
+
readOnlyHint: true,
|
|
219
|
+
openWorldHint: false,
|
|
220
|
+
destructiveHint: false,
|
|
221
|
+
idempotentHint: true,
|
|
216
222
|
}, async (args) => {
|
|
217
223
|
return await executeAccessibilityRAG(args, server, config);
|
|
218
224
|
});
|
|
@@ -227,6 +233,12 @@ export default function addAccessibilityTools(server, config) {
|
|
|
227
233
|
.boolean()
|
|
228
234
|
.optional()
|
|
229
235
|
.describe("Enable advanced accessibility rules in the scan settings"),
|
|
236
|
+
}, {
|
|
237
|
+
title: "Start Accessibility Scan",
|
|
238
|
+
readOnlyHint: false,
|
|
239
|
+
openWorldHint: false,
|
|
240
|
+
destructiveHint: false,
|
|
241
|
+
idempotentHint: false,
|
|
230
242
|
}, async (args, context) => {
|
|
231
243
|
return await executeAccessibilityScan(args, context, server, config);
|
|
232
244
|
});
|
|
@@ -256,6 +268,12 @@ export default function addAccessibilityTools(server, config) {
|
|
|
256
268
|
.string()
|
|
257
269
|
.optional()
|
|
258
270
|
.describe("CSS selector for submit button (required for form auth)"),
|
|
271
|
+
}, {
|
|
272
|
+
title: "Create Accessibility Auth Config",
|
|
273
|
+
readOnlyHint: false,
|
|
274
|
+
openWorldHint: false,
|
|
275
|
+
destructiveHint: false,
|
|
276
|
+
idempotentHint: false,
|
|
259
277
|
}, async (args) => {
|
|
260
278
|
try {
|
|
261
279
|
const creds = await elicitCredentialsIfSupported(server, { username: args.username, password: args.password }, [
|
|
@@ -287,6 +305,12 @@ export default function addAccessibilityTools(server, config) {
|
|
|
287
305
|
});
|
|
288
306
|
tools.getAccessibilityAuthConfig = server.tool("getAccessibilityAuthConfig", "Retrieve an existing authentication configuration by ID.", {
|
|
289
307
|
configId: z.number().describe("ID of the auth configuration to retrieve"),
|
|
308
|
+
}, {
|
|
309
|
+
title: "Get Accessibility Auth Config",
|
|
310
|
+
readOnlyHint: true,
|
|
311
|
+
openWorldHint: false,
|
|
312
|
+
destructiveHint: false,
|
|
313
|
+
idempotentHint: true,
|
|
290
314
|
}, async (args) => {
|
|
291
315
|
return await executeGetAuthConfig(args, server, config);
|
|
292
316
|
});
|
|
@@ -301,6 +325,12 @@ export default function addAccessibilityTools(server, config) {
|
|
|
301
325
|
.number()
|
|
302
326
|
.optional()
|
|
303
327
|
.describe("Character offset for pagination (default: 0)"),
|
|
328
|
+
}, {
|
|
329
|
+
title: "Fetch Accessibility Issues",
|
|
330
|
+
readOnlyHint: true,
|
|
331
|
+
openWorldHint: false,
|
|
332
|
+
destructiveHint: false,
|
|
333
|
+
idempotentHint: true,
|
|
304
334
|
}, async (args) => {
|
|
305
335
|
return await executeFetchAccessibilityIssues(args, server, config);
|
|
306
336
|
});
|
|
@@ -207,6 +207,12 @@ export default function addAppAutomationTools(server, config) {
|
|
|
207
207
|
appPath: z
|
|
208
208
|
.string()
|
|
209
209
|
.describe("The path to the .apk or .ipa file. Required for app installation."),
|
|
210
|
+
}, {
|
|
211
|
+
title: "Take App Screenshot",
|
|
212
|
+
readOnlyHint: false,
|
|
213
|
+
openWorldHint: false,
|
|
214
|
+
destructiveHint: false,
|
|
215
|
+
idempotentHint: false,
|
|
210
216
|
}, async (args) => {
|
|
211
217
|
try {
|
|
212
218
|
trackMCP("takeAppScreenshot", server.server.getClientVersion(), undefined, config);
|
|
@@ -226,7 +232,13 @@ export default function addAppAutomationTools(server, config) {
|
|
|
226
232
|
};
|
|
227
233
|
}
|
|
228
234
|
});
|
|
229
|
-
tools.runAppTestsOnBrowserStack = server.tool("runAppTestsOnBrowserStack", RUN_APP_AUTOMATE_DESCRIPTION, RUN_APP_AUTOMATE_SCHEMA,
|
|
235
|
+
tools.runAppTestsOnBrowserStack = server.tool("runAppTestsOnBrowserStack", RUN_APP_AUTOMATE_DESCRIPTION, RUN_APP_AUTOMATE_SCHEMA, {
|
|
236
|
+
title: "Run App Tests on BrowserStack",
|
|
237
|
+
readOnlyHint: false,
|
|
238
|
+
openWorldHint: false,
|
|
239
|
+
destructiveHint: false,
|
|
240
|
+
idempotentHint: false,
|
|
241
|
+
}, async (args) => {
|
|
230
242
|
try {
|
|
231
243
|
trackMCP("runAppTestsOnBrowserStack", server.server.getClientVersion(), undefined, config);
|
|
232
244
|
const devicesAsArrays = args.devices.map((device) => [device.platform, device.deviceName, device.osVersion]);
|
|
@@ -246,7 +258,13 @@ export default function addAppAutomationTools(server, config) {
|
|
|
246
258
|
};
|
|
247
259
|
}
|
|
248
260
|
});
|
|
249
|
-
tools.setupBrowserStackAppAutomateTests = server.tool("setupBrowserStackAppAutomateTests", SETUP_APP_AUTOMATE_DESCRIPTION, SETUP_APP_AUTOMATE_SCHEMA,
|
|
261
|
+
tools.setupBrowserStackAppAutomateTests = server.tool("setupBrowserStackAppAutomateTests", SETUP_APP_AUTOMATE_DESCRIPTION, SETUP_APP_AUTOMATE_SCHEMA, {
|
|
262
|
+
title: "Set Up App Automate Tests",
|
|
263
|
+
readOnlyHint: true,
|
|
264
|
+
openWorldHint: false,
|
|
265
|
+
destructiveHint: false,
|
|
266
|
+
idempotentHint: true,
|
|
267
|
+
}, async (args) => {
|
|
250
268
|
try {
|
|
251
269
|
return await setupAppAutomateHandler(args, config);
|
|
252
270
|
}
|
package/dist/tools/applive.js
CHANGED
|
@@ -67,6 +67,12 @@ export default function addAppLiveTools(server, config) {
|
|
|
67
67
|
appPath: z
|
|
68
68
|
.string()
|
|
69
69
|
.describe("The path to the .ipa or .apk file to install on the device. Always ask the user for the app path, do not assume it."),
|
|
70
|
+
}, {
|
|
71
|
+
title: "Run App Live Session",
|
|
72
|
+
readOnlyHint: false,
|
|
73
|
+
openWorldHint: false,
|
|
74
|
+
destructiveHint: false,
|
|
75
|
+
idempotentHint: false,
|
|
70
76
|
}, async (args) => {
|
|
71
77
|
try {
|
|
72
78
|
trackMCP("runAppLiveSession", server.server.getClientVersion(), undefined, config);
|
package/dist/tools/automate.js
CHANGED
|
@@ -58,6 +58,12 @@ export default function addAutomationTools(server, config) {
|
|
|
58
58
|
sessionType: z
|
|
59
59
|
.enum([SessionType.Automate, SessionType.AppAutomate])
|
|
60
60
|
.describe("Type of BrowserStack session"),
|
|
61
|
+
}, {
|
|
62
|
+
title: "Fetch Automation Screenshots",
|
|
63
|
+
readOnlyHint: true,
|
|
64
|
+
openWorldHint: false,
|
|
65
|
+
destructiveHint: false,
|
|
66
|
+
idempotentHint: true,
|
|
61
67
|
}, async (args) => {
|
|
62
68
|
try {
|
|
63
69
|
trackMCP("fetchAutomationScreenshots", server.server.getClientVersion(), undefined, config);
|
package/dist/tools/bstack-sdk.js
CHANGED
|
@@ -5,7 +5,13 @@ import { handleMCPError } from "../lib/utils.js";
|
|
|
5
5
|
import { trackMCP } from "../lib/instrumentation.js";
|
|
6
6
|
export function registerRunBrowserStackTestsTool(server, config) {
|
|
7
7
|
const tools = {};
|
|
8
|
-
tools.setupBrowserStackAutomateTests = server.tool("setupBrowserStackAutomateTests", RUN_ON_BROWSERSTACK_DESCRIPTION, RunTestsOnBrowserStackParamsShape,
|
|
8
|
+
tools.setupBrowserStackAutomateTests = server.tool("setupBrowserStackAutomateTests", RUN_ON_BROWSERSTACK_DESCRIPTION, RunTestsOnBrowserStackParamsShape, {
|
|
9
|
+
title: "Set Up Automate Tests",
|
|
10
|
+
readOnlyHint: true,
|
|
11
|
+
openWorldHint: false,
|
|
12
|
+
destructiveHint: false,
|
|
13
|
+
idempotentHint: true,
|
|
14
|
+
}, async (args) => {
|
|
9
15
|
try {
|
|
10
16
|
trackMCP("runTestsOnBrowserStack", server.server.getClientVersion(), config);
|
|
11
17
|
return await runTestsOnBrowserStackHandler(args, config);
|
|
@@ -54,6 +54,12 @@ export default function addBuildInsightsTools(server, config) {
|
|
|
54
54
|
const tools = {};
|
|
55
55
|
tools.fetchBuildInsights = server.tool("fetchBuildInsights", "Fetches insights about a BrowserStack build by combining build details and quality gate results.", {
|
|
56
56
|
buildId: z.string().describe("The build UUID of the BrowserStack build"),
|
|
57
|
+
}, {
|
|
58
|
+
title: "Fetch Build Insights",
|
|
59
|
+
readOnlyHint: true,
|
|
60
|
+
openWorldHint: false,
|
|
61
|
+
destructiveHint: false,
|
|
62
|
+
idempotentHint: true,
|
|
57
63
|
}, async (args) => {
|
|
58
64
|
try {
|
|
59
65
|
trackMCP("fetchBuildInsights", server.server.getClientVersion(), config);
|
|
@@ -119,6 +119,12 @@ export default function registerGetFailureLogs(server, config) {
|
|
|
119
119
|
AppAutomateLogType.CrashLogs,
|
|
120
120
|
]))
|
|
121
121
|
.describe("The types of logs to fetch."),
|
|
122
|
+
}, {
|
|
123
|
+
title: "Get Failure Logs",
|
|
124
|
+
readOnlyHint: true,
|
|
125
|
+
openWorldHint: false,
|
|
126
|
+
destructiveHint: false,
|
|
127
|
+
idempotentHint: true,
|
|
122
128
|
}, async (args) => {
|
|
123
129
|
try {
|
|
124
130
|
trackMCP("getFailureLogs", server.server.getClientVersion(), undefined, config);
|
package/dist/tools/live.js
CHANGED
|
@@ -88,7 +88,13 @@ async function runBrowserSession(rawArgs, config) {
|
|
|
88
88
|
}
|
|
89
89
|
export default function addBrowserLiveTools(server, config) {
|
|
90
90
|
const tools = {};
|
|
91
|
-
tools.runBrowserLiveSession = server.tool("runBrowserLiveSession", "Launch a BrowserStack Live session (desktop or mobile).", LiveArgsShape,
|
|
91
|
+
tools.runBrowserLiveSession = server.tool("runBrowserLiveSession", "Launch a BrowserStack Live session (desktop or mobile).", LiveArgsShape, {
|
|
92
|
+
title: "Run Browser Live Session",
|
|
93
|
+
readOnlyHint: false,
|
|
94
|
+
openWorldHint: true,
|
|
95
|
+
destructiveHint: false,
|
|
96
|
+
idempotentHint: false,
|
|
97
|
+
}, async (args) => {
|
|
92
98
|
try {
|
|
93
99
|
trackMCP("runBrowserLiveSession", server.server.getClientVersion(), undefined, config);
|
|
94
100
|
return await runBrowserSession(args, config);
|
|
@@ -39,6 +39,12 @@ export default function addObservabilityTools(server, config) {
|
|
|
39
39
|
projectName: z
|
|
40
40
|
.string()
|
|
41
41
|
.describe("Name of the project to get failures for. This is the 'projectName' key in the browserstack.yml file. If not sure, ask the user for the project name."),
|
|
42
|
+
}, {
|
|
43
|
+
title: "Get Failures in Last Run",
|
|
44
|
+
readOnlyHint: true,
|
|
45
|
+
openWorldHint: false,
|
|
46
|
+
destructiveHint: false,
|
|
47
|
+
idempotentHint: true,
|
|
42
48
|
}, async (args) => {
|
|
43
49
|
try {
|
|
44
50
|
trackMCP("getFailuresInLastRun", server.server.getClientVersion(), undefined, config);
|
package/dist/tools/percy-sdk.js
CHANGED
|
@@ -30,7 +30,13 @@ export function registerPercyTools(server, config) {
|
|
|
30
30
|
],
|
|
31
31
|
};
|
|
32
32
|
});
|
|
33
|
-
tools.percyVisualTestIntegrationAgent = server.tool("percyVisualTestIntegrationAgent", SIMULATE_PERCY_CHANGE_DESCRIPTION, SetUpPercyParamsShape,
|
|
33
|
+
tools.percyVisualTestIntegrationAgent = server.tool("percyVisualTestIntegrationAgent", SIMULATE_PERCY_CHANGE_DESCRIPTION, SetUpPercyParamsShape, {
|
|
34
|
+
title: "Percy Visual Test Integration Agent",
|
|
35
|
+
readOnlyHint: true,
|
|
36
|
+
openWorldHint: false,
|
|
37
|
+
destructiveHint: false,
|
|
38
|
+
idempotentHint: true,
|
|
39
|
+
}, async (args) => {
|
|
34
40
|
try {
|
|
35
41
|
trackMCP("VisualTestIntegrationAgent", server.server.getClientVersion(), config);
|
|
36
42
|
return simulatePercyChangeHandler(args, config);
|
|
@@ -39,7 +45,13 @@ export function registerPercyTools(server, config) {
|
|
|
39
45
|
return handleMCPError("VisualTestIntegrationAgent", server, config, error);
|
|
40
46
|
}
|
|
41
47
|
});
|
|
42
|
-
tools.setupPercyVisualTesting = server.tool("expandPercyVisualTesting", SETUP_PERCY_DESCRIPTION, SetUpPercyParamsShape,
|
|
48
|
+
tools.setupPercyVisualTesting = server.tool("expandPercyVisualTesting", SETUP_PERCY_DESCRIPTION, SetUpPercyParamsShape, {
|
|
49
|
+
title: "Expand Percy Visual Testing",
|
|
50
|
+
readOnlyHint: true,
|
|
51
|
+
openWorldHint: false,
|
|
52
|
+
destructiveHint: false,
|
|
53
|
+
idempotentHint: true,
|
|
54
|
+
}, async (args) => {
|
|
43
55
|
try {
|
|
44
56
|
trackMCP("setupPercyVisualTesting", server.server.getClientVersion(), config);
|
|
45
57
|
return setUpPercyHandler(args, config);
|
|
@@ -48,7 +60,13 @@ export function registerPercyTools(server, config) {
|
|
|
48
60
|
return handleMCPError("setupPercyVisualTesting", server, config, error);
|
|
49
61
|
}
|
|
50
62
|
});
|
|
51
|
-
tools.addPercySnapshotCommands = server.tool("addPercySnapshotCommands", PERCY_SNAPSHOT_COMMANDS_DESCRIPTION, UpdateTestFileWithInstructionsParams,
|
|
63
|
+
tools.addPercySnapshotCommands = server.tool("addPercySnapshotCommands", PERCY_SNAPSHOT_COMMANDS_DESCRIPTION, UpdateTestFileWithInstructionsParams, {
|
|
64
|
+
title: "Add Percy Snapshot Commands",
|
|
65
|
+
readOnlyHint: true,
|
|
66
|
+
openWorldHint: false,
|
|
67
|
+
destructiveHint: false,
|
|
68
|
+
idempotentHint: true,
|
|
69
|
+
}, async (args) => {
|
|
52
70
|
try {
|
|
53
71
|
trackMCP("addPercySnapshotCommands", server.server.getClientVersion(), config);
|
|
54
72
|
return await updateTestsWithPercyCommands(args);
|
|
@@ -57,7 +75,13 @@ export function registerPercyTools(server, config) {
|
|
|
57
75
|
return handleMCPError("addPercySnapshotCommands", server, config, error);
|
|
58
76
|
}
|
|
59
77
|
});
|
|
60
|
-
tools.listTestFiles = server.tool("listTestFiles", LIST_TEST_FILES_DESCRIPTION, {},
|
|
78
|
+
tools.listTestFiles = server.tool("listTestFiles", LIST_TEST_FILES_DESCRIPTION, {}, {
|
|
79
|
+
title: "List Test Files",
|
|
80
|
+
readOnlyHint: true,
|
|
81
|
+
openWorldHint: false,
|
|
82
|
+
destructiveHint: false,
|
|
83
|
+
idempotentHint: true,
|
|
84
|
+
}, async () => {
|
|
61
85
|
try {
|
|
62
86
|
trackMCP("listTestFiles", server.server.getClientVersion(), config);
|
|
63
87
|
return addListTestFiles();
|
|
@@ -66,7 +90,13 @@ export function registerPercyTools(server, config) {
|
|
|
66
90
|
return handleMCPError("listTestFiles", server, config, error);
|
|
67
91
|
}
|
|
68
92
|
});
|
|
69
|
-
tools.runPercyScan = server.tool("runPercyScan", "Run a Percy visual test scan. Example prompts : Run this Percy build/scan. Never run percy scan/build without this tool", RunPercyScanParamsShape,
|
|
93
|
+
tools.runPercyScan = server.tool("runPercyScan", "Run a Percy visual test scan. Example prompts : Run this Percy build/scan. Never run percy scan/build without this tool", RunPercyScanParamsShape, {
|
|
94
|
+
title: "Run Percy Scan",
|
|
95
|
+
readOnlyHint: true,
|
|
96
|
+
openWorldHint: false,
|
|
97
|
+
destructiveHint: false,
|
|
98
|
+
idempotentHint: true,
|
|
99
|
+
}, async (args) => {
|
|
70
100
|
try {
|
|
71
101
|
trackMCP("runPercyScan", server.server.getClientVersion(), config);
|
|
72
102
|
return runPercyScan(args);
|
|
@@ -75,7 +105,13 @@ export function registerPercyTools(server, config) {
|
|
|
75
105
|
return handleMCPError("runPercyScan", server, config, error);
|
|
76
106
|
}
|
|
77
107
|
});
|
|
78
|
-
tools.fetchPercyChanges = server.tool("fetchPercyChanges", "Retrieves and summarizes all visual changes detected by Percy AI between the latest and previous builds, helping quickly review what has changed in your project.", FetchPercyChangesParamsShape,
|
|
108
|
+
tools.fetchPercyChanges = server.tool("fetchPercyChanges", "Retrieves and summarizes all visual changes detected by Percy AI between the latest and previous builds, helping quickly review what has changed in your project.", FetchPercyChangesParamsShape, {
|
|
109
|
+
title: "Fetch Percy Changes",
|
|
110
|
+
readOnlyHint: true,
|
|
111
|
+
openWorldHint: false,
|
|
112
|
+
destructiveHint: false,
|
|
113
|
+
idempotentHint: true,
|
|
114
|
+
}, async (args) => {
|
|
79
115
|
try {
|
|
80
116
|
trackMCP("fetchPercyChanges", server.server.getClientVersion(), config);
|
|
81
117
|
return await fetchPercyChanges(args, config);
|
|
@@ -84,7 +120,13 @@ export function registerPercyTools(server, config) {
|
|
|
84
120
|
return handleMCPError("fetchPercyChanges", server, config, error);
|
|
85
121
|
}
|
|
86
122
|
});
|
|
87
|
-
tools.managePercyBuildApproval = server.tool("managePercyBuildApproval", "Approve or reject a Percy build", ManagePercyBuildApprovalParamsShape,
|
|
123
|
+
tools.managePercyBuildApproval = server.tool("managePercyBuildApproval", "Approve or reject a Percy build", ManagePercyBuildApprovalParamsShape, {
|
|
124
|
+
title: "Manage Percy Build Approval",
|
|
125
|
+
readOnlyHint: false,
|
|
126
|
+
openWorldHint: false,
|
|
127
|
+
destructiveHint: true,
|
|
128
|
+
idempotentHint: true,
|
|
129
|
+
}, async (args) => {
|
|
88
130
|
try {
|
|
89
131
|
trackMCP("managePercyBuildApproval", server.server.getClientVersion(), config);
|
|
90
132
|
return await approveOrDeclinePercyBuild(args, config);
|
package/dist/tools/rca-agent.js
CHANGED
|
@@ -130,7 +130,13 @@ export async function listTestIdsTool(args, config) {
|
|
|
130
130
|
}
|
|
131
131
|
export default function addRCATools(server, config) {
|
|
132
132
|
const tools = {};
|
|
133
|
-
tools.fetchRCA = server.tool("fetchRCA", "Fetch AI Root Cause Analysis for the current user's failed BrowserStack Automate/App-Automate tests. Suggests fixes only; never auto-apply, require explicit user approval.", FETCH_RCA_PARAMS,
|
|
133
|
+
tools.fetchRCA = server.tool("fetchRCA", "Fetch AI Root Cause Analysis for the current user's failed BrowserStack Automate/App-Automate tests. Suggests fixes only; never auto-apply, require explicit user approval.", FETCH_RCA_PARAMS, {
|
|
134
|
+
title: "Fetch Root Cause Analysis",
|
|
135
|
+
readOnlyHint: true,
|
|
136
|
+
openWorldHint: false,
|
|
137
|
+
destructiveHint: false,
|
|
138
|
+
idempotentHint: true,
|
|
139
|
+
}, async (args) => {
|
|
134
140
|
try {
|
|
135
141
|
trackMCP("fetchRCA", server.server.getClientVersion(), undefined, config);
|
|
136
142
|
return await fetchRCADataTool(args, config);
|
|
@@ -139,7 +145,13 @@ export default function addRCATools(server, config) {
|
|
|
139
145
|
return handleMCPError("fetchRCA", server, config, error);
|
|
140
146
|
}
|
|
141
147
|
});
|
|
142
|
-
tools.getBuildId = server.tool("getBuildId", "Get the BrowserStack build ID for a given project and build name, scoped to the current user's builds.", GET_BUILD_ID_PARAMS,
|
|
148
|
+
tools.getBuildId = server.tool("getBuildId", "Get the BrowserStack build ID for a given project and build name, scoped to the current user's builds.", GET_BUILD_ID_PARAMS, {
|
|
149
|
+
title: "Get Build ID",
|
|
150
|
+
readOnlyHint: true,
|
|
151
|
+
openWorldHint: false,
|
|
152
|
+
destructiveHint: false,
|
|
153
|
+
idempotentHint: true,
|
|
154
|
+
}, async (args) => {
|
|
143
155
|
try {
|
|
144
156
|
trackMCP("getBuildId", server.server.getClientVersion(), undefined, config);
|
|
145
157
|
return await getBuildIdTool(args, config);
|
|
@@ -148,7 +160,13 @@ export default function addRCATools(server, config) {
|
|
|
148
160
|
return handleMCPError("getBuildId", server, config, error);
|
|
149
161
|
}
|
|
150
162
|
});
|
|
151
|
-
tools.listBuildId = server.tool("listBuildId", "Get the latest build ID for a project and build name, across all users (no user filter).", GET_BUILD_ID_PARAMS,
|
|
163
|
+
tools.listBuildId = server.tool("listBuildId", "Get the latest build ID for a project and build name, across all users (no user filter).", GET_BUILD_ID_PARAMS, {
|
|
164
|
+
title: "List Build IDs",
|
|
165
|
+
readOnlyHint: true,
|
|
166
|
+
openWorldHint: false,
|
|
167
|
+
destructiveHint: false,
|
|
168
|
+
idempotentHint: true,
|
|
169
|
+
}, async (args) => {
|
|
152
170
|
try {
|
|
153
171
|
trackMCP("listBuildId", server.server.getClientVersion(), undefined, config);
|
|
154
172
|
return await listBuildIdTool(args, config);
|
|
@@ -157,7 +175,13 @@ export default function addRCATools(server, config) {
|
|
|
157
175
|
return handleMCPError("listBuildId", server, config, error);
|
|
158
176
|
}
|
|
159
177
|
});
|
|
160
|
-
tools.listTestIds = server.tool("listTestIds", "List test IDs from a BrowserStack Automate build, optionally filtered by status", LIST_TEST_IDS_PARAMS,
|
|
178
|
+
tools.listTestIds = server.tool("listTestIds", "List test IDs from a BrowserStack Automate build, optionally filtered by status", LIST_TEST_IDS_PARAMS, {
|
|
179
|
+
title: "List Test IDs",
|
|
180
|
+
readOnlyHint: true,
|
|
181
|
+
openWorldHint: false,
|
|
182
|
+
destructiveHint: false,
|
|
183
|
+
idempotentHint: true,
|
|
184
|
+
}, async (args) => {
|
|
161
185
|
try {
|
|
162
186
|
trackMCP("listTestIds", server.server.getClientVersion(), undefined, config);
|
|
163
187
|
return await listTestIdsTool(args, config);
|
package/dist/tools/selfheal.js
CHANGED
|
@@ -443,6 +443,12 @@ export default function addSelfHealTools(server, config) {
|
|
|
443
443
|
.string()
|
|
444
444
|
.describe("Build UUID. Fetches the build's self-healing report.")
|
|
445
445
|
.optional(),
|
|
446
|
+
}, {
|
|
447
|
+
title: "Fetch Self-Healed Selectors",
|
|
448
|
+
readOnlyHint: true,
|
|
449
|
+
openWorldHint: false,
|
|
450
|
+
destructiveHint: false,
|
|
451
|
+
idempotentHint: true,
|
|
446
452
|
}, async (args) => {
|
|
447
453
|
try {
|
|
448
454
|
trackMCP("fetchSelfHealedSelectors", server.server.getClientVersion(), undefined, config);
|
|
@@ -495,6 +501,12 @@ export default function addSelfHealTools(server, config) {
|
|
|
495
501
|
"(`session_id`, `original_locator`, `healed_locator`, " +
|
|
496
502
|
"`healing_thought`).", {
|
|
497
503
|
sessions: sessionsFieldSchema.describe("Sessions to plan edits for. See tool description for accepted shapes."),
|
|
504
|
+
}, {
|
|
505
|
+
title: "Prepare Self-Healing Plan",
|
|
506
|
+
readOnlyHint: true,
|
|
507
|
+
openWorldHint: false,
|
|
508
|
+
destructiveHint: false,
|
|
509
|
+
idempotentHint: true,
|
|
498
510
|
}, async (args) => {
|
|
499
511
|
try {
|
|
500
512
|
trackMCP("prepareSelfHealingPlan", server.server.getClientVersion(), undefined, config);
|
|
@@ -432,22 +432,124 @@ export async function getSubTestPlanTool(args, config, server) {
|
|
|
432
432
|
*/
|
|
433
433
|
export default function addTestManagementTools(server, config) {
|
|
434
434
|
const tools = {};
|
|
435
|
-
tools.createProjectOrFolder = server.tool("createProjectOrFolder", "Create a project and/or folder in BrowserStack Test Management.", CreateProjFoldSchema.shape,
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
tools.
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
tools.
|
|
450
|
-
|
|
451
|
-
|
|
435
|
+
tools.createProjectOrFolder = server.tool("createProjectOrFolder", "Create a project and/or folder in BrowserStack Test Management.", CreateProjFoldSchema.shape, {
|
|
436
|
+
title: "Create Project or Folder",
|
|
437
|
+
readOnlyHint: false,
|
|
438
|
+
openWorldHint: false,
|
|
439
|
+
destructiveHint: false,
|
|
440
|
+
idempotentHint: false,
|
|
441
|
+
}, (args) => createProjectOrFolderTool(args, config, server));
|
|
442
|
+
tools.createTestCase = server.tool("createTestCase", "Use this tool to create a test case in BrowserStack Test Management.", CreateTestCaseSchema.shape, {
|
|
443
|
+
title: "Create Test Case",
|
|
444
|
+
readOnlyHint: false,
|
|
445
|
+
openWorldHint: false,
|
|
446
|
+
destructiveHint: false,
|
|
447
|
+
idempotentHint: false,
|
|
448
|
+
}, (args) => createTestCaseTool(args, config, server));
|
|
449
|
+
tools.updateTestCase = server.tool("updateTestCase", "Update an existing test case in BrowserStack Test Management. Any subset of the following fields may be changed: name, description, preconditions, test_case_steps, owner, priority, case_type, automation_status, status, tags, issues, custom_fields. Only the supplied fields are modified.", UpdateTestCaseSchema.shape, {
|
|
450
|
+
title: "Update Test Case",
|
|
451
|
+
readOnlyHint: false,
|
|
452
|
+
openWorldHint: false,
|
|
453
|
+
destructiveHint: true,
|
|
454
|
+
idempotentHint: true,
|
|
455
|
+
}, (args) => updateTestCaseTool(args, config, server));
|
|
456
|
+
tools.listTestCases = server.tool("listTestCases", "List test cases in a project, optionally scoped to a specific folder. Omit folder_id to list all test cases in the project; provide folder_id (discoverable via listFolders) to list only that folder's cases. Supports filters: case_type, priority, pagination.", ListTestCasesSchema.shape, {
|
|
457
|
+
title: "List Test Cases",
|
|
458
|
+
readOnlyHint: true,
|
|
459
|
+
openWorldHint: false,
|
|
460
|
+
destructiveHint: false,
|
|
461
|
+
idempotentHint: true,
|
|
462
|
+
}, (args) => listTestCasesTool(args, config, server));
|
|
463
|
+
tools.listFolders = server.tool("listFolders", "List folders in a BrowserStack Test Management project, returning each folder's id and name (plus case counts and sub-folder counts). Pass parent_id to list sub-folders under a specific folder instead of top-level folders.", ListFoldersSchema.shape, {
|
|
464
|
+
title: "List Folders",
|
|
465
|
+
readOnlyHint: true,
|
|
466
|
+
openWorldHint: false,
|
|
467
|
+
destructiveHint: false,
|
|
468
|
+
idempotentHint: true,
|
|
469
|
+
}, (args) => listFoldersTool(args, config, server));
|
|
470
|
+
tools.listTestCaseTemplates = server.tool("listTestCaseTemplates", "List test-case templates with their numeric template_id. Use the id with createTestCase to apply a custom template (the 'template' slug only selects system templates).", ListTemplatesSchema.shape, {
|
|
471
|
+
title: "List Test Case Templates",
|
|
472
|
+
readOnlyHint: true,
|
|
473
|
+
openWorldHint: false,
|
|
474
|
+
destructiveHint: false,
|
|
475
|
+
idempotentHint: true,
|
|
476
|
+
}, (args) => listTemplatesTool(args, config, server));
|
|
477
|
+
tools.createTestRun = server.tool("createTestRun", "Create a test run in BrowserStack Test Management.", CreateTestRunSchema.shape, {
|
|
478
|
+
title: "Create Test Run",
|
|
479
|
+
readOnlyHint: false,
|
|
480
|
+
openWorldHint: false,
|
|
481
|
+
destructiveHint: false,
|
|
482
|
+
idempotentHint: false,
|
|
483
|
+
}, (args) => createTestRunTool(args, config, server));
|
|
484
|
+
tools.listTestRuns = server.tool("listTestRuns", "List test runs in a project with optional filters (date ranges, assignee, state, etc.)", ListTestRunsSchema.shape, {
|
|
485
|
+
title: "List Test Runs",
|
|
486
|
+
readOnlyHint: true,
|
|
487
|
+
openWorldHint: false,
|
|
488
|
+
destructiveHint: false,
|
|
489
|
+
idempotentHint: true,
|
|
490
|
+
}, (args) => listTestRunsTool(args, config, server));
|
|
491
|
+
tools.updateTestRun = server.tool("updateTestRun", "Update a test run's metadata and/or add test cases to it.", UpdateTestRunSchema.shape, {
|
|
492
|
+
title: "Update Test Run",
|
|
493
|
+
readOnlyHint: false,
|
|
494
|
+
openWorldHint: false,
|
|
495
|
+
destructiveHint: true,
|
|
496
|
+
idempotentHint: true,
|
|
497
|
+
}, (args) => updateTestRunTool(args, config, server));
|
|
498
|
+
tools.addTestResult = server.tool("addTestResult", "Add a test result to a specific test run via BrowserStack Test Management API.", AddTestResultSchema.shape, {
|
|
499
|
+
title: "Add Test Result",
|
|
500
|
+
readOnlyHint: false,
|
|
501
|
+
openWorldHint: false,
|
|
502
|
+
destructiveHint: false,
|
|
503
|
+
idempotentHint: false,
|
|
504
|
+
}, (args) => addTestResultTool(args, config, server));
|
|
505
|
+
tools.uploadProductRequirementFile = server.tool("uploadProductRequirementFile", "Upload files (e.g., PDRs, PDFs) to BrowserStack Test Management and retrieve a file mapping ID. This is utilized for generating test cases from files and is part of the Test Case Generator AI Agent in BrowserStack.", UploadFileSchema.shape, {
|
|
506
|
+
title: "Upload Product Requirement File",
|
|
507
|
+
readOnlyHint: false,
|
|
508
|
+
openWorldHint: false,
|
|
509
|
+
destructiveHint: false,
|
|
510
|
+
idempotentHint: false,
|
|
511
|
+
}, (args) => uploadProductRequirementFileTool(args, config, server));
|
|
512
|
+
tools.createTestCasesFromFile = server.tool("createTestCasesFromFile", "Generate test cases from a file in BrowserStack Test Management using the Test Case Generator AI Agent.", CreateTestCasesFromFileSchema.shape, {
|
|
513
|
+
title: "Create Test Cases from File",
|
|
514
|
+
readOnlyHint: false,
|
|
515
|
+
openWorldHint: false,
|
|
516
|
+
destructiveHint: false,
|
|
517
|
+
idempotentHint: false,
|
|
518
|
+
}, (args, context) => createTestCasesFromFileTool(args, context, config, server));
|
|
519
|
+
tools.createLCASteps = server.tool("createLCASteps", "Generate Low Code Automation (LCA) steps for a test case in BrowserStack Test Management using the Low Code Automation Agent.", CreateLCAStepsSchema.shape, {
|
|
520
|
+
title: "Create LCA Steps",
|
|
521
|
+
readOnlyHint: false,
|
|
522
|
+
openWorldHint: false,
|
|
523
|
+
destructiveHint: false,
|
|
524
|
+
idempotentHint: false,
|
|
525
|
+
}, (args, context) => createLCAStepsTool(args, context, config, server));
|
|
526
|
+
tools.listTestPlans = server.tool("listTestPlans", "List test plans in a BrowserStack Test Management project. Returns each plan's identifier (TP-*), name, status, description, dates, and active/closed test-run counts. Supports pagination.", ListTestPlansSchema.shape, {
|
|
527
|
+
title: "List Test Plans",
|
|
528
|
+
readOnlyHint: true,
|
|
529
|
+
openWorldHint: false,
|
|
530
|
+
destructiveHint: false,
|
|
531
|
+
idempotentHint: true,
|
|
532
|
+
}, (args) => listTestPlansTool(args, config, server));
|
|
533
|
+
tools.getTestPlan = server.tool("getTestPlan", "Fetch a test plan by identifier (TP-*) from BrowserStack Test Management. Returns plan metadata, the full list of linked test runs, total test-case count across runs, and a status summary — suitable for generating test documentation or QA status reports.", GetTestPlanSchema.shape, {
|
|
534
|
+
title: "Get Test Plan",
|
|
535
|
+
readOnlyHint: true,
|
|
536
|
+
openWorldHint: false,
|
|
537
|
+
destructiveHint: false,
|
|
538
|
+
idempotentHint: true,
|
|
539
|
+
}, (args) => getTestPlanTool(args, config, server));
|
|
540
|
+
tools.listSubTestPlans = server.tool("listSubTestPlans", "List sub-test-plans under a parent test plan (TP-*) in a Test Management project. Supports pagination.", ListSubTestPlansSchema.shape, {
|
|
541
|
+
title: "List Sub Test Plans",
|
|
542
|
+
readOnlyHint: true,
|
|
543
|
+
openWorldHint: false,
|
|
544
|
+
destructiveHint: false,
|
|
545
|
+
idempotentHint: true,
|
|
546
|
+
}, (args) => listSubTestPlansTool(args, config, server));
|
|
547
|
+
tools.getSubTestPlan = server.tool("getSubTestPlan", "Fetch a sub-test-plan (STP-*) under a parent plan (TP-*). Returns metadata and linked test runs.", GetSubTestPlanSchema.shape, {
|
|
548
|
+
title: "Get Sub Test Plan",
|
|
549
|
+
readOnlyHint: true,
|
|
550
|
+
openWorldHint: false,
|
|
551
|
+
destructiveHint: false,
|
|
552
|
+
idempotentHint: true,
|
|
553
|
+
}, (args) => getSubTestPlanTool(args, config, server));
|
|
452
554
|
return tools;
|
|
453
555
|
}
|