diff --git a/src/tools/accessibility.ts b/src/tools/accessibility.ts index e5d7caef..81b4e7b7 100644 --- a/src/tools/accessibility.ts +++ b/src/tools/accessibility.ts @@ -442,6 +442,13 @@ export default function addAccessibilityTools( "Any accessibility, a11y, WCAG, or web accessibility question", ), }, + { + title: "Accessibility Expert", + readOnlyHint: true, + openWorldHint: false, + destructiveHint: false, + idempotentHint: true, + }, async (args) => { return await executeAccessibilityRAG(args, server, config); }, @@ -462,6 +469,13 @@ export default function addAccessibilityTools( .optional() .describe("Enable advanced accessibility rules in the scan settings"), }, + { + title: "Start Accessibility Scan", + readOnlyHint: false, + openWorldHint: false, + destructiveHint: false, + idempotentHint: false, + }, async (args, context) => { return await executeAccessibilityScan(args, context, server, config); }, @@ -499,6 +513,13 @@ export default function addAccessibilityTools( .optional() .describe("CSS selector for submit button (required for form auth)"), }, + { + title: "Create Accessibility Auth Config", + readOnlyHint: false, + openWorldHint: false, + destructiveHint: false, + idempotentHint: false, + }, async (args) => { try { const creds = await elicitCredentialsIfSupported( @@ -558,6 +579,13 @@ export default function addAccessibilityTools( { configId: z.number().describe("ID of the auth configuration to retrieve"), }, + { + title: "Get Accessibility Auth Config", + readOnlyHint: true, + openWorldHint: false, + destructiveHint: false, + idempotentHint: true, + }, async (args) => { return await executeGetAuthConfig(args, server, config); }, @@ -578,6 +606,13 @@ export default function addAccessibilityTools( .optional() .describe("Character offset for pagination (default: 0)"), }, + { + title: "Fetch Accessibility Issues", + readOnlyHint: true, + openWorldHint: false, + destructiveHint: false, + idempotentHint: true, + }, async (args) => { return await executeFetchAccessibilityIssues(args, server, config); }, diff --git a/src/tools/appautomate.ts b/src/tools/appautomate.ts index edcb246c..36d05826 100644 --- a/src/tools/appautomate.ts +++ b/src/tools/appautomate.ts @@ -336,6 +336,13 @@ export default function addAppAutomationTools( "The path to the .apk or .ipa file. Required for app installation.", ), }, + { + title: "Take App Screenshot", + readOnlyHint: false, + openWorldHint: false, + destructiveHint: false, + idempotentHint: false, + }, async (args) => { try { trackMCP( @@ -371,6 +378,13 @@ export default function addAppAutomationTools( "runAppTestsOnBrowserStack", RUN_APP_AUTOMATE_DESCRIPTION, RUN_APP_AUTOMATE_SCHEMA, + { + title: "Run App Tests on BrowserStack", + readOnlyHint: false, + openWorldHint: false, + destructiveHint: false, + idempotentHint: false, + }, async (args) => { try { trackMCP( @@ -412,6 +426,13 @@ export default function addAppAutomationTools( "setupBrowserStackAppAutomateTests", SETUP_APP_AUTOMATE_DESCRIPTION, SETUP_APP_AUTOMATE_SCHEMA, + { + title: "Set Up App Automate Tests", + readOnlyHint: true, + openWorldHint: false, + destructiveHint: false, + idempotentHint: true, + }, async (args) => { try { return await setupAppAutomateHandler(args, config); diff --git a/src/tools/applive.ts b/src/tools/applive.ts index 920f174b..e188e06e 100644 --- a/src/tools/applive.ts +++ b/src/tools/applive.ts @@ -106,6 +106,13 @@ export default function addAppLiveTools( "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.", ), }, + { + title: "Run App Live Session", + readOnlyHint: false, + openWorldHint: false, + destructiveHint: false, + idempotentHint: false, + }, async (args) => { try { trackMCP( diff --git a/src/tools/automate.ts b/src/tools/automate.ts index 81914722..58378c70 100644 --- a/src/tools/automate.ts +++ b/src/tools/automate.ts @@ -84,6 +84,13 @@ export default function addAutomationTools( .enum([SessionType.Automate, SessionType.AppAutomate]) .describe("Type of BrowserStack session"), }, + { + title: "Fetch Automation Screenshots", + readOnlyHint: true, + openWorldHint: false, + destructiveHint: false, + idempotentHint: true, + }, async (args) => { try { trackMCP( diff --git a/src/tools/bstack-sdk.ts b/src/tools/bstack-sdk.ts index a7de7819..9e2a3a5c 100644 --- a/src/tools/bstack-sdk.ts +++ b/src/tools/bstack-sdk.ts @@ -16,6 +16,13 @@ export function registerRunBrowserStackTestsTool( "setupBrowserStackAutomateTests", RUN_ON_BROWSERSTACK_DESCRIPTION, RunTestsOnBrowserStackParamsShape, + { + title: "Set Up Automate Tests", + readOnlyHint: true, + openWorldHint: false, + destructiveHint: false, + idempotentHint: true, + }, async (args) => { try { trackMCP( diff --git a/src/tools/build-insights.ts b/src/tools/build-insights.ts index ed6e3d74..e9b510ae 100644 --- a/src/tools/build-insights.ts +++ b/src/tools/build-insights.ts @@ -77,6 +77,13 @@ export default function addBuildInsightsTools( { buildId: z.string().describe("The build UUID of the BrowserStack build"), }, + { + title: "Fetch Build Insights", + readOnlyHint: true, + openWorldHint: false, + destructiveHint: false, + idempotentHint: true, + }, async (args) => { try { trackMCP( diff --git a/src/tools/get-failure-logs.ts b/src/tools/get-failure-logs.ts index c3d82ab1..f360e953 100644 --- a/src/tools/get-failure-logs.ts +++ b/src/tools/get-failure-logs.ts @@ -202,6 +202,13 @@ export default function registerGetFailureLogs( ) .describe("The types of logs to fetch."), }, + { + title: "Get Failure Logs", + readOnlyHint: true, + openWorldHint: false, + destructiveHint: false, + idempotentHint: true, + }, async (args) => { try { trackMCP( diff --git a/src/tools/live.ts b/src/tools/live.ts index 19f50378..fa1ac4bc 100644 --- a/src/tools/live.ts +++ b/src/tools/live.ts @@ -128,6 +128,13 @@ export default function addBrowserLiveTools( "runBrowserLiveSession", "Launch a BrowserStack Live session (desktop or mobile).", LiveArgsShape, + { + title: "Run Browser Live Session", + readOnlyHint: false, + openWorldHint: true, + destructiveHint: false, + idempotentHint: false, + }, async (args) => { try { trackMCP( diff --git a/src/tools/observability.ts b/src/tools/observability.ts index ff1f51f4..d4ec371d 100644 --- a/src/tools/observability.ts +++ b/src/tools/observability.ts @@ -71,6 +71,13 @@ export default function addObservabilityTools( "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.", ), }, + { + title: "Get Failures in Last Run", + readOnlyHint: true, + openWorldHint: false, + destructiveHint: false, + idempotentHint: true, + }, async (args) => { try { trackMCP( diff --git a/src/tools/percy-sdk.ts b/src/tools/percy-sdk.ts index 94f62f2f..012ccd20 100644 --- a/src/tools/percy-sdk.ts +++ b/src/tools/percy-sdk.ts @@ -59,6 +59,13 @@ export function registerPercyTools( "percyVisualTestIntegrationAgent", SIMULATE_PERCY_CHANGE_DESCRIPTION, SetUpPercyParamsShape, + { + title: "Percy Visual Test Integration Agent", + readOnlyHint: true, + openWorldHint: false, + destructiveHint: false, + idempotentHint: true, + }, async (args) => { try { trackMCP( @@ -82,6 +89,13 @@ export function registerPercyTools( "expandPercyVisualTesting", SETUP_PERCY_DESCRIPTION, SetUpPercyParamsShape, + { + title: "Expand Percy Visual Testing", + readOnlyHint: true, + openWorldHint: false, + destructiveHint: false, + idempotentHint: true, + }, async (args) => { try { trackMCP( @@ -100,6 +114,13 @@ export function registerPercyTools( "addPercySnapshotCommands", PERCY_SNAPSHOT_COMMANDS_DESCRIPTION, UpdateTestFileWithInstructionsParams, + { + title: "Add Percy Snapshot Commands", + readOnlyHint: true, + openWorldHint: false, + destructiveHint: false, + idempotentHint: true, + }, async (args) => { try { trackMCP( @@ -123,6 +144,13 @@ export function registerPercyTools( "listTestFiles", LIST_TEST_FILES_DESCRIPTION, {}, + { + title: "List Test Files", + readOnlyHint: true, + openWorldHint: false, + destructiveHint: false, + idempotentHint: true, + }, async () => { try { trackMCP("listTestFiles", server.server.getClientVersion()!, config); @@ -137,6 +165,13 @@ export function registerPercyTools( "runPercyScan", "Run a Percy visual test scan. Example prompts : Run this Percy build/scan. Never run percy scan/build without this tool", RunPercyScanParamsShape, + { + title: "Run Percy Scan", + readOnlyHint: true, + openWorldHint: false, + destructiveHint: false, + idempotentHint: true, + }, async (args) => { try { trackMCP("runPercyScan", server.server.getClientVersion()!, config); @@ -151,6 +186,13 @@ export function registerPercyTools( "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, + { + title: "Fetch Percy Changes", + readOnlyHint: true, + openWorldHint: false, + destructiveHint: false, + idempotentHint: true, + }, async (args) => { try { trackMCP( @@ -169,6 +211,13 @@ export function registerPercyTools( "managePercyBuildApproval", "Approve or reject a Percy build", ManagePercyBuildApprovalParamsShape, + { + title: "Manage Percy Build Approval", + readOnlyHint: false, + openWorldHint: false, + destructiveHint: true, + idempotentHint: true, + }, async (args) => { try { trackMCP( diff --git a/src/tools/rca-agent.ts b/src/tools/rca-agent.ts index 1102d697..fc9f39fd 100644 --- a/src/tools/rca-agent.ts +++ b/src/tools/rca-agent.ts @@ -189,6 +189,13 @@ export default function addRCATools( "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, + { + title: "Fetch Root Cause Analysis", + readOnlyHint: true, + openWorldHint: false, + destructiveHint: false, + idempotentHint: true, + }, async (args) => { try { trackMCP( @@ -208,6 +215,13 @@ export default function addRCATools( "getBuildId", "Get the BrowserStack build ID for a given project and build name, scoped to the current user's builds.", GET_BUILD_ID_PARAMS, + { + title: "Get Build ID", + readOnlyHint: true, + openWorldHint: false, + destructiveHint: false, + idempotentHint: true, + }, async (args) => { try { trackMCP( @@ -227,6 +241,13 @@ export default function addRCATools( "listBuildId", "Get the latest build ID for a project and build name, across all users (no user filter).", GET_BUILD_ID_PARAMS, + { + title: "List Build IDs", + readOnlyHint: true, + openWorldHint: false, + destructiveHint: false, + idempotentHint: true, + }, async (args) => { try { trackMCP( @@ -246,6 +267,13 @@ export default function addRCATools( "listTestIds", "List test IDs from a BrowserStack Automate build, optionally filtered by status", LIST_TEST_IDS_PARAMS, + { + title: "List Test IDs", + readOnlyHint: true, + openWorldHint: false, + destructiveHint: false, + idempotentHint: true, + }, async (args) => { try { trackMCP( diff --git a/src/tools/selfheal.ts b/src/tools/selfheal.ts index 06665f79..94169612 100644 --- a/src/tools/selfheal.ts +++ b/src/tools/selfheal.ts @@ -596,6 +596,13 @@ export default function addSelfHealTools( .describe("Build UUID. Fetches the build's self-healing report.") .optional(), }, + { + title: "Fetch Self-Healed Selectors", + readOnlyHint: true, + openWorldHint: false, + destructiveHint: false, + idempotentHint: true, + }, async (args) => { try { trackMCP( @@ -670,6 +677,13 @@ export default function addSelfHealTools( "Sessions to plan edits for. See tool description for accepted shapes.", ), }, + { + title: "Prepare Self-Healing Plan", + readOnlyHint: true, + openWorldHint: false, + destructiveHint: false, + idempotentHint: true, + }, async (args) => { try { trackMCP( diff --git a/src/tools/testmanagement.ts b/src/tools/testmanagement.ts index 87b84d70..b4600afe 100644 --- a/src/tools/testmanagement.ts +++ b/src/tools/testmanagement.ts @@ -730,6 +730,13 @@ export default function addTestManagementTools( "createProjectOrFolder", "Create a project and/or folder in BrowserStack Test Management.", CreateProjFoldSchema.shape, + { + title: "Create Project or Folder", + readOnlyHint: false, + openWorldHint: false, + destructiveHint: false, + idempotentHint: false, + }, (args) => createProjectOrFolderTool(args, config, server), ); @@ -737,6 +744,13 @@ export default function addTestManagementTools( "createTestCase", "Use this tool to create a test case in BrowserStack Test Management.", CreateTestCaseSchema.shape, + { + title: "Create Test Case", + readOnlyHint: false, + openWorldHint: false, + destructiveHint: false, + idempotentHint: false, + }, (args) => createTestCaseTool(args, config, server), ); @@ -744,6 +758,13 @@ export default function addTestManagementTools( "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, + { + title: "Update Test Case", + readOnlyHint: false, + openWorldHint: false, + destructiveHint: true, + idempotentHint: true, + }, (args) => updateTestCaseTool(args, config, server), ); @@ -751,6 +772,13 @@ export default function addTestManagementTools( "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, + { + title: "List Test Cases", + readOnlyHint: true, + openWorldHint: false, + destructiveHint: false, + idempotentHint: true, + }, (args) => listTestCasesTool(args, config, server), ); @@ -758,6 +786,13 @@ export default function addTestManagementTools( "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, + { + title: "List Folders", + readOnlyHint: true, + openWorldHint: false, + destructiveHint: false, + idempotentHint: true, + }, (args) => listFoldersTool(args, config, server), ); @@ -765,6 +800,13 @@ export default function addTestManagementTools( "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, + { + title: "List Test Case Templates", + readOnlyHint: true, + openWorldHint: false, + destructiveHint: false, + idempotentHint: true, + }, (args) => listTemplatesTool(args, config, server), ); @@ -772,6 +814,13 @@ export default function addTestManagementTools( "createTestRun", "Create a test run in BrowserStack Test Management.", CreateTestRunSchema.shape, + { + title: "Create Test Run", + readOnlyHint: false, + openWorldHint: false, + destructiveHint: false, + idempotentHint: false, + }, (args) => createTestRunTool(args, config, server), ); @@ -779,6 +828,13 @@ export default function addTestManagementTools( "listTestRuns", "List test runs in a project with optional filters (date ranges, assignee, state, etc.)", ListTestRunsSchema.shape, + { + title: "List Test Runs", + readOnlyHint: true, + openWorldHint: false, + destructiveHint: false, + idempotentHint: true, + }, (args) => listTestRunsTool(args, config, server), ); @@ -786,6 +842,13 @@ export default function addTestManagementTools( "updateTestRun", "Update a test run's metadata and/or add test cases to it.", UpdateTestRunSchema.shape, + { + title: "Update Test Run", + readOnlyHint: false, + openWorldHint: false, + destructiveHint: true, + idempotentHint: true, + }, (args) => updateTestRunTool(args, config, server), ); @@ -793,6 +856,13 @@ export default function addTestManagementTools( "addTestResult", "Add a test result to a specific test run via BrowserStack Test Management API.", AddTestResultSchema.shape, + { + title: "Add Test Result", + readOnlyHint: false, + openWorldHint: false, + destructiveHint: false, + idempotentHint: false, + }, (args) => addTestResultTool(args, config, server), ); @@ -800,6 +870,13 @@ export default function addTestManagementTools( "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, + { + title: "Upload Product Requirement File", + readOnlyHint: false, + openWorldHint: false, + destructiveHint: false, + idempotentHint: false, + }, (args) => uploadProductRequirementFileTool(args, config, server), ); @@ -807,6 +884,13 @@ export default function addTestManagementTools( "createTestCasesFromFile", "Generate test cases from a file in BrowserStack Test Management using the Test Case Generator AI Agent.", CreateTestCasesFromFileSchema.shape, + { + title: "Create Test Cases from File", + readOnlyHint: false, + openWorldHint: false, + destructiveHint: false, + idempotentHint: false, + }, (args, context) => createTestCasesFromFileTool(args, context, config, server), ); @@ -815,6 +899,13 @@ export default function addTestManagementTools( "createLCASteps", "Generate Low Code Automation (LCA) steps for a test case in BrowserStack Test Management using the Low Code Automation Agent.", CreateLCAStepsSchema.shape, + { + title: "Create LCA Steps", + readOnlyHint: false, + openWorldHint: false, + destructiveHint: false, + idempotentHint: false, + }, (args, context) => createLCAStepsTool(args, context, config, server), ); @@ -822,6 +913,13 @@ export default function addTestManagementTools( "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, + { + title: "List Test Plans", + readOnlyHint: true, + openWorldHint: false, + destructiveHint: false, + idempotentHint: true, + }, (args) => listTestPlansTool(args, config, server), ); @@ -829,6 +927,13 @@ export default function addTestManagementTools( "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, + { + title: "Get Test Plan", + readOnlyHint: true, + openWorldHint: false, + destructiveHint: false, + idempotentHint: true, + }, (args) => getTestPlanTool(args, config, server), ); @@ -836,6 +941,13 @@ export default function addTestManagementTools( "listSubTestPlans", "List sub-test-plans under a parent test plan (TP-*) in a Test Management project. Supports pagination.", ListSubTestPlansSchema.shape, + { + title: "List Sub Test Plans", + readOnlyHint: true, + openWorldHint: false, + destructiveHint: false, + idempotentHint: true, + }, (args) => listSubTestPlansTool(args, config, server), ); @@ -843,6 +955,13 @@ export default function addTestManagementTools( "getSubTestPlan", "Fetch a sub-test-plan (STP-*) under a parent plan (TP-*). Returns metadata and linked test runs.", GetSubTestPlanSchema.shape, + { + title: "Get Sub Test Plan", + readOnlyHint: true, + openWorldHint: false, + destructiveHint: false, + idempotentHint: true, + }, (args) => getSubTestPlanTool(args, config, server), ); diff --git a/tests/tools/accessibility.test.ts b/tests/tools/accessibility.test.ts index 61cdb42c..c742df67 100644 --- a/tests/tools/accessibility.test.ts +++ b/tests/tools/accessibility.test.ts @@ -80,7 +80,9 @@ describe("Accessibility Tools", () => { vi.clearAllMocks(); handlers = {}; serverMock = { - tool: vi.fn((name: string, _desc: string, _schema: any, handler: (...args: any[]) => any) => { + tool: vi.fn((...toolArgs: any[]) => { + const name = toolArgs[0] as string; + const handler = toolArgs[toolArgs.length - 1] as (...args: any[]) => any; handlers[name] = handler; }), server: { diff --git a/tests/tools/bstack-sdk.test.ts b/tests/tools/bstack-sdk.test.ts index 712eda48..c626a3cc 100644 --- a/tests/tools/bstack-sdk.test.ts +++ b/tests/tools/bstack-sdk.test.ts @@ -27,7 +27,9 @@ describe("BStack SDK Tool", () => { beforeEach(() => { vi.clearAllMocks(); serverMock = { - tool: vi.fn((name, desc, schema, handler) => { + tool: vi.fn((...toolArgs: any[]) => { + const name = toolArgs[0]; + const handler = toolArgs[toolArgs.length - 1]; serverMock.handlers = serverMock.handlers || {}; serverMock.handlers[name] = handler; }), @@ -41,6 +43,7 @@ describe("BStack SDK Tool", () => { "setupBrowserStackAutomateTests", expect.any(String), expect.any(Object), + expect.any(Object), expect.any(Function), ); }); diff --git a/tests/tools/live.test.ts b/tests/tools/live.test.ts index 831aa9db..10a6261f 100644 --- a/tests/tools/live.test.ts +++ b/tests/tools/live.test.ts @@ -32,7 +32,8 @@ describe('startBrowserLiveSession', () => { beforeEach(() => { vi.clearAllMocks(); serverMock = { - tool: vi.fn((name, desc, schema, handler) => { + tool: vi.fn((...toolArgs: any[]) => { + const handler = toolArgs[toolArgs.length - 1]; serverMock.handler = handler; }), server: { diff --git a/tests/tools/percySdk.test.ts b/tests/tools/percySdk.test.ts index afeca3c0..32241480 100644 --- a/tests/tools/percySdk.test.ts +++ b/tests/tools/percySdk.test.ts @@ -49,7 +49,9 @@ describe("Percy SDK Tools", () => { vi.clearAllMocks(); handlers = {}; serverMock = { - tool: vi.fn((name: string, _desc: string, _schema: any, handler: (...args: any[]) => any) => { + tool: vi.fn((...toolArgs: any[]) => { + const name = toolArgs[0] as string; + const handler = toolArgs[toolArgs.length - 1] as (...args: any[]) => any; handlers[name] = handler; }), prompt: vi.fn(),