@browserstack/mcp-server 2.2.2-beta.2 → 2.3.0-beta.1

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 (36) hide show
  1. package/capability/appautomate.capability-index.json +3233 -0
  2. package/capability/automate.capability-index.json +2068 -0
  3. package/dist/tools/accessibility.js +3 -2
  4. package/dist/tools/appautomate-utils/appium-sdk/constants.d.ts +1 -1
  5. package/dist/tools/appautomate-utils/appium-sdk/constants.js +3 -3
  6. package/dist/tools/appautomate-utils/native-execution/constants.d.ts +1 -1
  7. package/dist/tools/appautomate-utils/native-execution/constants.js +20 -4
  8. package/dist/tools/appautomate.js +3 -3
  9. package/dist/tools/applive.js +4 -4
  10. package/dist/tools/ask-browserstack/register.js +13 -6
  11. package/dist/tools/capability-registry/bind.js +56 -0
  12. package/dist/tools/capability-registry/config.d.ts +1 -25
  13. package/dist/tools/capability-registry/config.js +40 -1
  14. package/dist/tools/capability-registry/discovery.d.ts +1 -1
  15. package/dist/tools/capability-registry/egress.js +21 -3
  16. package/dist/tools/capability-registry/index-loader.d.ts +33 -7
  17. package/dist/tools/capability-registry/index-loader.js +99 -26
  18. package/dist/tools/capability-registry/register.d.ts +1 -1
  19. package/dist/tools/capability-registry/register.js +111 -19
  20. package/dist/tools/capability-registry/resolve.js +42 -1
  21. package/dist/tools/capability-registry/types.d.ts +86 -0
  22. package/dist/tools/get-failure-logs.js +1 -1
  23. package/dist/tools/live.js +2 -2
  24. package/dist/tools/rca-agent-utils/constants.js +2 -2
  25. package/dist/tools/rca-agent.js +1 -1
  26. package/dist/tools/sdk-utils/common/constants.d.ts +1 -1
  27. package/dist/tools/sdk-utils/common/constants.js +1 -1
  28. package/dist/tools/sdk-utils/common/schema.js +1 -1
  29. package/dist/tools/selfheal.js +16 -2
  30. package/dist/tools/testmanagement-utils/create-testcase.js +3 -3
  31. package/dist/tools/testmanagement-utils/list-testcases.js +1 -1
  32. package/dist/tools/testmanagement-utils/update-testcase.js +3 -3
  33. package/dist/tools/testmanagement.js +16 -12
  34. package/dist/tools/tool-handoff.d.ts +2 -2
  35. package/dist/tools/tool-handoff.js +16 -10
  36. package/package.json +1 -1
@@ -15,14 +15,14 @@ const LiveArgsShape = {
15
15
  .describe("Desktop OS ('Windows' or 'OS X') or mobile OS ('android','ios','winphone')"),
16
16
  desiredOSVersion: z
17
17
  .string()
18
- .describe("Version number or 'latest'/'oldest'; macOS takes names, e.g. 'Sequoia'."),
18
+ .describe("The OS version must be specified as a version number (e.g., '10', '14.0') or as a keyword such as 'latest' or 'oldest'. Normalize variations like 'newest' or 'most recent' to 'latest', and terms like 'earliest' or 'first' to 'oldest'. For macOS, version names (e.g., 'Sequoia') must be used instead of numeric versions."),
19
19
  desiredBrowser: z
20
20
  .enum(["chrome", "firefox", "safari", "edge", "ie"])
21
21
  .describe("Browser for desktop (Chrome, IE, Firefox, Safari, Edge)"),
22
22
  desiredBrowserVersion: z
23
23
  .string()
24
24
  .optional()
25
- .describe("Desktop browser version, or 'latest' / 'oldest'."),
25
+ .describe("Browser version for desktop (e.g. '133.2', 'latest'). If the user says 'latest', 'newest', or similar, normalize it to 'latest'. Likewise, convert terms like 'earliest' or 'oldest' to 'oldest'."),
26
26
  desiredDevice: z.string().optional().describe("Device name for mobile"),
27
27
  };
28
28
  const LiveArgsSchema = z.object(LiveArgsShape);
@@ -8,7 +8,7 @@ export const FETCH_RCA_PARAMS = {
8
8
  testId: z
9
9
  .array(z.number().int())
10
10
  .max(3)
11
- .describe("Up to 3 numeric test ids from listTestIds (not session ids)."),
11
+ .describe("Array of integer test IDs to fetch RCA data for (maximum 3 IDs). These must be numeric test IDs, not session IDs or strings. If not provided, use the listTestIds tool to get all failed testcases. If more than 3 IDs are provided, only the first 3 will be processed."),
12
12
  };
13
13
  export const GET_BUILD_ID_PARAMS = {
14
14
  browserStackProjectName: z
@@ -21,7 +21,7 @@ export const GET_BUILD_ID_PARAMS = {
21
21
  export const LIST_TEST_IDS_PARAMS = {
22
22
  buildId: z
23
23
  .string()
24
- .describe("Build id; get it with getBuildId or listBuildId."),
24
+ .describe("The Browserstack Build ID of the test run. If not known, use the getBuildId tool to fetch it using project and build name"),
25
25
  status: z
26
26
  .nativeEnum(TestStatus)
27
27
  .describe("Filter tests by status. If not provided, all tests are returned. Example for RCA usecase always use failed status"),
@@ -131,7 +131,7 @@ export async function listTestIdsTool(args, config) {
131
131
  }
132
132
  export default function addRCATools(server, config) {
133
133
  const tools = {};
134
- tools.fetchRCA = server.tool("fetchRCA", "AI root cause for failed Automate/App Automate tests. Suggests fixes only; never auto-apply, require explicit user approval." +
134
+ 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." +
135
135
  NEEDS_TEST_IDS, FETCH_RCA_PARAMS, {
136
136
  title: "Fetch Root Cause Analysis",
137
137
  readOnlyHint: true,
@@ -2,7 +2,7 @@ export declare const IMPORTANT_SETUP_WARNING: string;
2
2
  export declare const SETUP_PERCY_DESCRIPTION = "Set up or expand Percy visual testing configuration with comprehensive coverage for existing projects that might have Percy integrated. This supports both Percy Web Standalone and Percy Automate. Example prompts: Expand percy coverage for this project {project_name}";
3
3
  export declare const LIST_TEST_FILES_DESCRIPTION = "Lists all test files for a given set of directories.";
4
4
  export declare const PERCY_SNAPSHOT_COMMANDS_DESCRIPTION = "Adds Percy snapshot commands to the specified test files.";
5
- export declare const RUN_ON_BROWSERSTACK_DESCRIPTION = "Set up and run web tests on BrowserStack Automate with the SDK (functional or integration). For Percy visual testing use the Percy tool.";
5
+ export declare const RUN_ON_BROWSERSTACK_DESCRIPTION = "Set up and run automated web-based tests on BrowserStack using the BrowserStack SDK. Use this tool for functional or integration test setup on BrowserStack only. For any visual testing or Percy integration, use the dedicated Percy setup tool. Example prompts: run this test on browserstack; set up this project for browserstack.";
6
6
  export declare const SIMULATE_PERCY_CHANGE_DESCRIPTION = "Integrate Percy visual testing into new projects and demonstrate visual change detection through a step-by-step simulation. This tool handles initial Percy integration, setup, and creates a working demonstration for new users. Primary tool for prompts like: \"Integrate percy for this project\", \"Integrate percy in this project {project_name}\"";
7
7
  export declare const PERCY_REPLACE_REGEX: RegExp;
8
8
  export declare const PERCY_SNAPSHOT_INSTRUCTION = "\nInvoke listTestFiles() with the provided directories from user to gather all test files in memory ---STEP---\nProcess files in STRICT sequential order using tool addPercySnapshotCommands() with below instructions:\n- Start with index 0\n- Then index 1 \n- Then index 2\n- Continue sequentially until the last index\n- DO NOT skip any index numbers\n- DO NOT jump to random indices like 10, 20, 30\n- DO NOT worry about time consuming and any constraints.\n- DO NOT STOP until you add commands in all the files or you reach end of the files.\n";
@@ -3,7 +3,7 @@ export const IMPORTANT_SETUP_WARNING = "IMPORTANT: DO NOT SKIP ANY STEP. All the
3
3
  export const SETUP_PERCY_DESCRIPTION = "Set up or expand Percy visual testing configuration with comprehensive coverage for existing projects that might have Percy integrated. This supports both Percy Web Standalone and Percy Automate. Example prompts: Expand percy coverage for this project {project_name}";
4
4
  export const LIST_TEST_FILES_DESCRIPTION = "Lists all test files for a given set of directories.";
5
5
  export const PERCY_SNAPSHOT_COMMANDS_DESCRIPTION = "Adds Percy snapshot commands to the specified test files.";
6
- export const RUN_ON_BROWSERSTACK_DESCRIPTION = "Set up and run web tests on BrowserStack Automate with the SDK (functional or integration). For Percy visual testing use the Percy tool.";
6
+ export const RUN_ON_BROWSERSTACK_DESCRIPTION = "Set up and run automated web-based tests on BrowserStack using the BrowserStack SDK. Use this tool for functional or integration test setup on BrowserStack only. For any visual testing or Percy integration, use the dedicated Percy setup tool. Example prompts: run this test on browserstack; set up this project for browserstack.";
7
7
  export const SIMULATE_PERCY_CHANGE_DESCRIPTION = `Integrate Percy visual testing into new projects and demonstrate visual change detection through a step-by-step simulation. This tool handles initial Percy integration, setup, and creates a working demonstration for new users. Primary tool for prompts like: "Integrate percy for this project", "Integrate percy in this project {project_name}"`;
8
8
  export const PERCY_REPLACE_REGEX = /Invoke listTestFiles\(\) with the provided directories[\s\S]*?- DO NOT STOP until you add commands in all the files or you reach end of the files\./;
9
9
  export const PERCY_SNAPSHOT_INSTRUCTION = `
@@ -63,7 +63,7 @@ export const RunTestsOnBrowserStackParamsShape = {
63
63
  .array(DeviceSchema)
64
64
  .max(3)
65
65
  .default([])
66
- .describe("Only devices the user asked for, e.g. [{ platform: 'windows', osVersion: '11', browser: 'chrome', browserVersion: 'latest' }]."),
66
+ .describe("Device objects array. Use the object format directly - no transformation needed. Add only when user explicitly requests devices. Examples: [{ platform: 'windows', osVersion: '11', browser: 'chrome', browserVersion: 'latest' }] or [{ platform: 'android', deviceName: 'Samsung Galaxy S24', osVersion: '14', browser: 'chrome' }]."),
67
67
  };
68
68
  export const SetUpPercySchema = z.object(SetUpPercyParamsShape);
69
69
  export const RunTestsOnBrowserStackSchema = z.object(RunTestsOnBrowserStackParamsShape);
@@ -417,7 +417,11 @@ export async function prepareSelfHealingPlanTool(args, config) {
417
417
  // Registers the fetchSelfHealSelector tool with the MCP server
418
418
  export default function addSelfHealTools(server, config) {
419
419
  const tools = {};
420
- tools.fetchSelfHealedSelectors = server.tool("fetchSelfHealedSelectors", "Fetch self-healed selectors and the test source. Pass exactly one of `sessionId` or `buildUuid`; give the pairs to prepareSelfHealingPlan." +
420
+ tools.fetchSelfHealedSelectors = server.tool("fetchSelfHealedSelectors", "Fetch BrowserStack self-healed selectors plus the test source code for " +
421
+ "the run. Provide exactly one of `sessionId` (single Automate / " +
422
+ "App-Automate session) or `buildUuid` (full self-healing report for a " +
423
+ "build). Pass the returned locator pairs to `prepareSelfHealingPlan` " +
424
+ "to plan edits." +
421
425
  NEEDS_SESSION_ID, {
422
426
  sessionId: z
423
427
  .string()
@@ -477,7 +481,17 @@ export default function addSelfHealTools(server, config) {
477
481
  // Flexible entry point for the `sessions` argument. See normalizers above
478
482
  // for the accepted alternate shapes.
479
483
  const sessionsFieldSchema = z.preprocess(normalizeSessionsInput, z.array(sessionPayloadSchema).min(1));
480
- tools.prepareSelfHealingPlan = server.tool("prepareSelfHealingPlan", "Build an edit plan from healed locator pairs plus test source; it does NOT modify files. `sessions`: [{sessionId, locators: [{original, healed}]}] or the raw healing report." +
484
+ tools.prepareSelfHealingPlan = server.tool("prepareSelfHealingPlan", "Build a self-healing edit plan that bundles locator pairs with test " +
485
+ "source code for the calling LLM to apply with its own editing tools. " +
486
+ "This tool does NOT modify files — it returns structured context so " +
487
+ "the LLM can edit only the relevant call sites (avoids blind " +
488
+ "find/replace across shared ids/classes). `sessions` accepts the " +
489
+ "canonical shape `[{sessionId, locators: [{original, healed, " +
490
+ "thought?}]}]`, a single session object, an envelope `{sessions: " +
491
+ "[...]}`, the raw report `{healing_logs: [...]}` (with " +
492
+ "`healed_selectors` aliasing `locators`), and snake_case keys " +
493
+ "(`session_id`, `original_locator`, `healed_locator`, " +
494
+ "`healing_thought`)." +
481
495
  NEEDS_SESSION_ID, {
482
496
  sessions: sessionsFieldSchema.describe("Sessions to plan edits for. See tool description for accepted shapes."),
483
497
  }, {
@@ -15,10 +15,10 @@ export const customFieldValueSchema = z.union([
15
15
  export const CreateTestCaseSchema = z.object({
16
16
  project_identifier: z
17
17
  .string()
18
- .describe("Project id (PR-*). If none, offer createProjectOrFolder."),
18
+ .describe("The ID of the BrowserStack project where the test case should be created. If no project identifier is provided, ask the user if they would like to create a new project using the createProjectOrFolder tool."),
19
19
  folder_id: z
20
20
  .string()
21
- .describe("Folder id. If none, offer createProjectOrFolder."),
21
+ .describe("The ID of the folder within the project where the test case should be created. If not provided, ask the user if they would like to create a new folder using the createProjectOrFolder tool."),
22
22
  name: z.string().describe("Name of the test case."),
23
23
  description: z
24
24
  .string()
@@ -66,7 +66,7 @@ export const CreateTestCaseSchema = z.object({
66
66
  priority: z
67
67
  .string()
68
68
  .optional()
69
- .describe("Priority, e.g. 'High' or 'medium'; values vary per project; default Medium."),
69
+ .describe("Priority of the test case. Accepts either display name (e.g. 'Critical', 'High', 'Medium', 'Low') or internal name (e.g. 'medium'). If omitted, the project default (usually 'Medium') is applied. Valid values are per-project and discoverable via the form-fields endpoint."),
70
70
  case_type: z
71
71
  .string()
72
72
  .optional()
@@ -13,7 +13,7 @@ export const ListTestCasesSchema = z.object({
13
13
  folder_id: z
14
14
  .string()
15
15
  .optional()
16
- .describe("Only this folder's cases (ids from listFolders). Omit for all."),
16
+ .describe("Optional. If provided, only return test cases in this folder. If omitted, returns all test cases in the project. Folder ids can be discovered via listFolders."),
17
17
  case_type: z
18
18
  .string()
19
19
  .optional()
@@ -37,15 +37,15 @@ export const UpdateTestCaseSchema = z.object({
37
37
  priority: z
38
38
  .string()
39
39
  .optional()
40
- .describe("Priority, e.g. 'High' or 'medium'; values vary per project."),
40
+ .describe("Updated priority. Accepts either display name (e.g. 'Medium', 'Critical', 'High', 'Low') or internal name (e.g. 'medium'). Valid values are per-project and discoverable via the form-fields endpoint."),
41
41
  case_type: z
42
42
  .string()
43
43
  .optional()
44
- .describe("Type, e.g. 'Functional' or 'smoke_sanity'; values vary per project."),
44
+ .describe("Updated test case type. Accepts either display name (e.g. 'Functional', 'Regression', 'Smoke & Sanity') or internal name (e.g. 'functional', 'smoke_sanity'). Valid values are per-project."),
45
45
  automation_status: z
46
46
  .string()
47
47
  .optional()
48
- .describe("e.g. not_automated, automated, automation_not_required, obsolete."),
48
+ .describe("Updated automation status. Use internal name such as 'not_automated', 'automated', 'automation_not_required', 'cannot_be_automated', or 'obsolete'."),
49
49
  status: z
50
50
  .string()
51
51
  .optional()
@@ -441,14 +441,15 @@ export default function addTestManagementTools(server, config) {
441
441
  destructiveHint: false,
442
442
  idempotentHint: false,
443
443
  }, (args) => createProjectOrFolderTool(args, config, server));
444
- tools.createTestCase = server.tool("createTestCase", "Create a test case in BrowserStack Test Management." + NEEDS_PROJECT_ID, CreateTestCaseSchema.shape, {
444
+ tools.createTestCase = server.tool("createTestCase", "Use this tool to create a test case in BrowserStack Test Management." +
445
+ NEEDS_PROJECT_ID, CreateTestCaseSchema.shape, {
445
446
  title: "Create Test Case",
446
447
  readOnlyHint: false,
447
448
  openWorldHint: false,
448
449
  destructiveHint: false,
449
450
  idempotentHint: false,
450
451
  }, (args) => createTestCaseTool(args, config, server));
451
- tools.updateTestCase = server.tool("updateTestCase", "Update an existing test case; only the supplied fields change." +
452
+ 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." +
452
453
  NEEDS_PROJECT_ID, UpdateTestCaseSchema.shape, {
453
454
  title: "Update Test Case",
454
455
  readOnlyHint: false,
@@ -456,7 +457,7 @@ export default function addTestManagementTools(server, config) {
456
457
  destructiveHint: true,
457
458
  idempotentHint: true,
458
459
  }, (args) => updateTestCaseTool(args, config, server));
459
- tools.listTestCases = server.tool("listTestCases", "List test cases in a project, optionally one folder (see listFolders). Filters: case_type, priority, paging." +
460
+ 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." +
460
461
  NEEDS_PROJECT_ID, ListTestCasesSchema.shape, {
461
462
  title: "List Test Cases",
462
463
  readOnlyHint: true,
@@ -464,7 +465,7 @@ export default function addTestManagementTools(server, config) {
464
465
  destructiveHint: false,
465
466
  idempotentHint: true,
466
467
  }, (args) => listTestCasesTool(args, config, server));
467
- tools.listFolders = server.tool("listFolders", "List folders (id, name, counts) in a project; parent_id lists sub-folders." +
468
+ 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." +
468
469
  NEEDS_PROJECT_ID, ListFoldersSchema.shape, {
469
470
  title: "List Folders",
470
471
  readOnlyHint: true,
@@ -486,21 +487,24 @@ export default function addTestManagementTools(server, config) {
486
487
  destructiveHint: false,
487
488
  idempotentHint: false,
488
489
  }, (args) => createTestRunTool(args, config, server));
489
- tools.listTestRuns = server.tool("listTestRuns", "List test runs with filters (dates, assignee, state)." + NEEDS_PROJECT_ID, ListTestRunsSchema.shape, {
490
+ tools.listTestRuns = server.tool("listTestRuns", "List test runs in a project with optional filters (date ranges, assignee, state, etc.)" +
491
+ NEEDS_PROJECT_ID, ListTestRunsSchema.shape, {
490
492
  title: "List Test Runs",
491
493
  readOnlyHint: true,
492
494
  openWorldHint: false,
493
495
  destructiveHint: false,
494
496
  idempotentHint: true,
495
497
  }, (args) => listTestRunsTool(args, config, server));
496
- tools.updateTestRun = server.tool("updateTestRun", "Update a test run or add test cases to it." + NEEDS_PROJECT_ID, UpdateTestRunSchema.shape, {
498
+ tools.updateTestRun = server.tool("updateTestRun", "Update a test run's metadata and/or add test cases to it." +
499
+ NEEDS_PROJECT_ID, UpdateTestRunSchema.shape, {
497
500
  title: "Update Test Run",
498
501
  readOnlyHint: false,
499
502
  openWorldHint: false,
500
503
  destructiveHint: true,
501
504
  idempotentHint: true,
502
505
  }, (args) => updateTestRunTool(args, config, server));
503
- tools.addTestResult = server.tool("addTestResult", "Add a test result to a test run." + NEEDS_PROJECT_ID, AddTestResultSchema.shape, {
506
+ tools.addTestResult = server.tool("addTestResult", "Add a test result to a specific test run via BrowserStack Test Management API." +
507
+ NEEDS_PROJECT_ID, AddTestResultSchema.shape, {
504
508
  title: "Add Test Result",
505
509
  readOnlyHint: false,
506
510
  openWorldHint: false,
@@ -522,7 +526,7 @@ export default function addTestManagementTools(server, config) {
522
526
  destructiveHint: false,
523
527
  idempotentHint: false,
524
528
  }, (args, context) => createTestCasesFromFileTool(args, context, config, server));
525
- tools.createLCASteps = server.tool("createLCASteps", "Generate Low Code Automation (LCA) steps for a test case." +
529
+ 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." +
526
530
  NEEDS_PROJECT_ID, CreateLCAStepsSchema.shape, {
527
531
  title: "Create LCA Steps",
528
532
  readOnlyHint: false,
@@ -530,7 +534,7 @@ export default function addTestManagementTools(server, config) {
530
534
  destructiveHint: false,
531
535
  idempotentHint: false,
532
536
  }, (args, context) => createLCAStepsTool(args, context, config, server));
533
- tools.listTestPlans = server.tool("listTestPlans", "List test plans (TP-*) with status, dates and run counts; paginated." +
537
+ 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." +
534
538
  NEEDS_PROJECT_ID +
535
539
  PLAN_WRITES_VIA_CAPABILITIES, ListTestPlansSchema.shape, {
536
540
  title: "List Test Plans",
@@ -539,7 +543,7 @@ export default function addTestManagementTools(server, config) {
539
543
  destructiveHint: false,
540
544
  idempotentHint: true,
541
545
  }, (args) => listTestPlansTool(args, config, server));
542
- tools.getTestPlan = server.tool("getTestPlan", "Get a test plan (TP-*): metadata, linked runs, case count and status summary." +
546
+ 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." +
543
547
  NEEDS_PROJECT_ID +
544
548
  NEEDS_TEST_PLAN_ID +
545
549
  PLAN_WRITES_VIA_CAPABILITIES, GetTestPlanSchema.shape, {
@@ -549,7 +553,7 @@ export default function addTestManagementTools(server, config) {
549
553
  destructiveHint: false,
550
554
  idempotentHint: true,
551
555
  }, (args) => getTestPlanTool(args, config, server));
552
- tools.listSubTestPlans = server.tool("listSubTestPlans", "List sub-plans under a test plan (TP-*); paginated." +
556
+ tools.listSubTestPlans = server.tool("listSubTestPlans", "List sub-test-plans under a parent test plan (TP-*) in a Test Management project. Supports pagination." +
553
557
  NEEDS_PROJECT_ID +
554
558
  NEEDS_TEST_PLAN_ID +
555
559
  PLAN_WRITES_VIA_CAPABILITIES, ListSubTestPlansSchema.shape, {
@@ -559,7 +563,7 @@ export default function addTestManagementTools(server, config) {
559
563
  destructiveHint: false,
560
564
  idempotentHint: true,
561
565
  }, (args) => listSubTestPlansTool(args, config, server));
562
- tools.getSubTestPlan = server.tool("getSubTestPlan", "Get a sub-plan (STP-*): metadata and linked runs." +
566
+ tools.getSubTestPlan = server.tool("getSubTestPlan", "Fetch a sub-test-plan (STP-*) under a parent plan (TP-*). Returns metadata and linked test runs." +
563
567
  NEEDS_PROJECT_ID +
564
568
  NEEDS_TEST_PLAN_ID +
565
569
  PLAN_WRITES_VIA_CAPABILITIES, GetSubTestPlanSchema.shape, {
@@ -23,7 +23,7 @@
23
23
  * twenty hand-written variants drift into twenty different signals.
24
24
  */
25
25
  /** No tool lists projects, so this genuinely has to go to the agent. */
26
- export declare const NEEDS_PROJECT_ID = " Needs a project id (PR-*); if you lack one, get it from the capability functions.";
26
+ export declare const NEEDS_PROJECT_ID: string;
27
27
  /** A sibling tool can produce the id — prefer it over the agent. */
28
28
  export declare function needsIdFrom(idLabel: string, sourceTool: string): string;
29
29
  /**
@@ -60,7 +60,7 @@ export declare const NEEDS_BUILD_ID: string;
60
60
  * this branch was open. This used to send the model to askBrowserStackAI for want of a tool;
61
61
  * pointing at the agent when a real tool exists is exactly what the header above forbids.
62
62
  */
63
- export declare const NEEDS_SESSION_ID = " Needs a session id: listSessions lists them; getBuildId or listBuildId finds the build.";
63
+ export declare const NEEDS_SESSION_ID: string;
64
64
  /** A completed scan's ids come from startAccessibilityScan, or from the agent. */
65
65
  export declare const NEEDS_A11Y_SCAN_ID: string;
66
66
  /** Auth-config ids are not listable by any tool here. */
@@ -23,7 +23,9 @@
23
23
  * twenty hand-written variants drift into twenty different signals.
24
24
  */
25
25
  /** No tool lists projects, so this genuinely has to go to the agent. */
26
- export const NEEDS_PROJECT_ID = " Needs a project id (PR-*); if you lack one, get it from the capability functions.";
26
+ export const NEEDS_PROJECT_ID = " Requires a project identifier (PR-*). No tool here lists projects, so if you do not " +
27
+ "have one, use the capability functions to list the Test Management projects, then " +
28
+ "retry this tool with the identifier they return.";
27
29
  /** A sibling tool can produce the id — prefer it over the agent. */
28
30
  export function needsIdFrom(idLabel, sourceTool) {
29
31
  return ` Requires ${idLabel}. Call ${sourceTool} first if you do not have it.`;
@@ -34,8 +36,9 @@ export function needsIdFrom(idLabel, sourceTool) {
34
36
  * tool read "Requires a project identifier ... call askBrowserStackAI", which routed
35
37
  * "create me a project" through the agent before letting the tool run.
36
38
  */
37
- export const PROJECT_ID_ONLY_FOR_FOLDER = " Creating a project needs no identifier; a folder inside an EXISTING project needs " +
38
- "its id (PR-*), from the capability functions.";
39
+ export const PROJECT_ID_ONLY_FOR_FOLDER = " Creating a project needs no identifier. Creating a folder inside an EXISTING project " +
40
+ "needs that project's identifier (PR-*); no tool here lists projects, so use the " +
41
+ "capability functions to look it up.";
39
42
  /** A test plan id (TP-*) comes from listTestPlans. */
40
43
  export const NEEDS_TEST_PLAN_ID = needsIdFrom("a test plan identifier (TP-*)", "listTestPlans");
41
44
  /**
@@ -55,8 +58,9 @@ export const NEEDS_TEST_PLAN_ID = needsIdFrom("a test plan identifier (TP-*)", "
55
58
  * completes on a client that can show a prompt. On one that cannot, the intended write is
56
59
  * refused rather than performed.
57
60
  */
58
- export const PLAN_WRITES_VIA_CAPABILITIES = " Creating a test plan or sub-plan, and linking or unlinking test runs, are not " +
59
- "available as tools here: use the capability functions (they ask you to confirm first).";
61
+ export const PLAN_WRITES_VIA_CAPABILITIES = " Creating a test plan or sub-plan, and linking or unlinking test runs on one, are not " +
62
+ "available as tools here: use the capability functions, which reach Test Management's " +
63
+ "own API for these operations. They ask you to confirm before changing anything.";
60
64
  /** A build id comes from either build-lookup tool. */
61
65
  export const NEEDS_BUILD_ID = needsIdFrom("a BrowserStack build id", "getBuildId or listBuildId");
62
66
  /**
@@ -64,12 +68,14 @@ export const NEEDS_BUILD_ID = needsIdFrom("a BrowserStack build id", "getBuildId
64
68
  * this branch was open. This used to send the model to askBrowserStackAI for want of a tool;
65
69
  * pointing at the agent when a real tool exists is exactly what the header above forbids.
66
70
  */
67
- export const NEEDS_SESSION_ID = " Needs a session id: listSessions lists them; getBuildId or listBuildId finds the build.";
71
+ export const NEEDS_SESSION_ID = " Requires a session id. listSessions lists them for a build; if you do not have the " +
72
+ "build either, getBuildId or listBuildId resolves one from a project and build name.";
68
73
  /** A completed scan's ids come from startAccessibilityScan, or from the agent. */
69
- export const NEEDS_A11Y_SCAN_ID = " Needs a completed scan's ids from startAccessibilityScan; past scans are not " +
70
- "listed, so start a new scan rather than guessing.";
74
+ export const NEEDS_A11Y_SCAN_ID = " Requires the ids of a completed scan, which are returned by startAccessibilityScan. " +
75
+ "No tool here lists past scans, so if you do not have the ids, start a new scan rather " +
76
+ "than guessing.";
71
77
  /** Auth-config ids are not listable by any tool here. */
72
- export const NEEDS_A11Y_CONFIG_ID = " Needs the id from createAccessibilityAuthConfig; configs are not listed, so create " +
73
- "one rather than guessing.";
78
+ export const NEEDS_A11Y_CONFIG_ID = " Requires the numeric id returned by createAccessibilityAuthConfig. No tool here lists " +
79
+ "existing configurations, so if you do not have the id, create one rather than guessing.";
74
80
  /** Test ids come from listTestIds, which itself needs a build id. */
75
81
  export const NEEDS_TEST_IDS = needsIdFrom("test ids", "listTestIds");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@browserstack/mcp-server",
3
- "version": "2.2.2-beta.2",
3
+ "version": "2.3.0-beta.1",
4
4
  "description": "BrowserStack's Official MCP Server",
5
5
  "mcpName": "io.github.browserstack/mcp-server",
6
6
  "main": "dist/index.js",