Skip to content

Dynamic tools #62

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions DYNAMIC_PRODUCTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# Dynamic Product Management System

The BrowserStack MCP Server now features a dynamic product management system that allows you to enable/disable specific BrowserStack capabilities on demand. This prevents tool overload and provides a cleaner, more focused experience.

## How It Works

### Initial State

When the server starts, only two core tools are available:

- `enable_products` - Enable specific BrowserStack products
- `get_product_status` - View current product status

### Product Queue System

- **Maximum Products**: 2 products can be enabled simultaneously
- **Queue Behavior**: When you enable a 3rd product, the oldest enabled product is automatically disabled
- **Always Available**: The `enable_products` tool is always accessible

## Enabling Dynamic Products

The dynamic product management system is controlled by an environment variable. To enable this feature:

### Environment Variable Configuration

Set the following environment variable when starting the MCP server in MCP configuration file:

```bash
DYNAMIC_SERVER=true
```

### Behavior

- **When `DYNAMIC_SERVER=true`**: The dynamic product management system is enabled, allowing you to selectively enable/disable products
- **When `DYNAMIC_SERVER=false` or not set**: All products and their tools are available by default (legacy behavior)

## Available Products

### 🚀 **SDK** (`sdk`)

**Category**: Test Automation
**Description**: Set up and run tests using BrowserStack SDK with automatic configuration
**Tools**: `runTestsOnBrowserStack`

### 📱 **App Live Testing** (`app-live`)

**Category**: Mobile Testing
**Description**: Test mobile apps on real devices with interactive debugging capabilities
**Tools**: `runAppLiveSession`

### 🌐 **Browser Live Testing** (`browser-live`)

**Category**: Web Testing
**Description**: Test web applications on real browsers and devices for cross-browser compatibility
**Tools**: `runBrowserLiveSession`

### ♿ **Accessibility Testing** (`accessibility`)

**Category**: Quality Assurance
**Description**: Automated accessibility scanning and reporting for WCAG compliance
**Tools**: `startAccessibilityScan`

### 📋 **Test Management** (`test-management`)

**Category**: Test Management
**Description**: Comprehensive test case and test run management with project organization
**Tools**: `createProjectOrFolder`, `createTestCase`, `listTestCases`, `createTestRun`, `listTestRuns`, `updateTestRun`, `addTestResult`, `uploadProductRequirementFile`, `createTestCasesFromFile`

### 🤖 **App Automation** (`app-automation`)

**Category**: Mobile Automation
**Description**: Automated mobile app testing with screenshot capture and visual validation
**Tools**: `takeAppScreenshot`

### 🔍 **Failure Analysis** (`failure-logs`)

**Category**: Debugging
**Description**: Debug test failures with comprehensive logs, network data, and crash reports
**Tools**: `getFailureLogs`

### 🖥️ **Web Automation** (`automate`)

**Category**: Web Automation
**Description**: Automated web testing with screenshot capture and session management
**Tools**: `fetchAutomationScreenshots`

### 🧠 **Self-Healing Tests** (`self-heal`)

**Category**: AI/ML
**Description**: AI-powered test maintenance with automatic selector healing for flaky tests
**Tools**: `fetchSelfHealedSelectors`

### Typical Workflow

1. **Start Server**: Only `enable_products` and `get_product_status` are available
2. **Check Available Products**: Use `get_product_status` to see all options
3. **Enable Needed Products**: Use `enable_products` with the products you need
4. **Use Product Tools**: The enabled product tools are now available
5. **Switch Products**: Enable different products as needed (oldest will be auto-disabled)

### Configuration

The system is configured in `src/lib/product-manager.ts`:

- `MAX_ENABLED_PRODUCTS`: Maximum concurrent products (default: 2)
- `PRODUCT_CONFIGS`: Product definitions and metadata
- `BrowserStackProduct`: Enum of available products
2 changes: 2 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ export class Config {
public readonly browserstackUsername: string,
public readonly browserstackAccessKey: string,
public readonly DEV_MODE: boolean,
public readonly DYNAMIC_SERVER: boolean,
) {}
}

const config = new Config(
process.env.BROWSERSTACK_USERNAME!,
process.env.BROWSERSTACK_ACCESS_KEY!,
process.env.DEV_MODE === "true",
process.env.DYNAMIC_SERVER === "true",
);

export default config;
31 changes: 9 additions & 22 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,11 @@ import { createRequire } from "module";
const require = createRequire(import.meta.url);
const packageJson = require("../package.json");
import "dotenv/config";
import config from "./config.js";
import logger from "./logger.js";
import addSDKTools from "./tools/bstack-sdk.js";
import addAppLiveTools from "./tools/applive.js";
import addBrowserLiveTools from "./tools/live.js";
import addAccessibilityTools from "./tools/accessibility.js";
import addTestManagementTools from "./tools/testmanagement.js";
import addAppAutomationTools from "./tools/appautomate.js";
import addFailureLogsTools from "./tools/getFailureLogs.js";
import addAutomateTools from "./tools/automate.js";
import addSelfHealTools from "./tools/selfheal.js";
import { setupOnInitialized } from "./oninitialized.js";

function registerTools(server: McpServer) {
addSDKTools(server);
addAppLiveTools(server);
addBrowserLiveTools(server);
addAccessibilityTools(server);
addTestManagementTools(server);
addAppAutomationTools(server);
addFailureLogsTools(server);
addAutomateTools(server);
addSelfHealTools(server);
}
import { registerStaticTools } from "./lib/static-tools.js";
import { registerDynamicTools } from "./lib/dynamic-tools.js";

// Create an MCP server
const server: McpServer = new McpServer({
Expand All @@ -38,7 +20,12 @@ const server: McpServer = new McpServer({

setupOnInitialized(server);

registerTools(server);
// Choose registration mode based on config
if (config.DYNAMIC_SERVER) {
registerDynamicTools(server);
} else {
registerStaticTools(server);
}

async function main() {
logger.info(
Expand Down
80 changes: 80 additions & 0 deletions src/lib/dynamic-tools.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/**
* Dynamic Tools Registration
* Sets up the product manager and dynamic tool registration system
*/

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import logger from "../logger.js";
import { ProductManager, BrowserStackProduct } from "./product-manager.js";
import { addDynamicTools } from "../tools/dynamic.js";
import addSDKTools from "../tools/bstack-sdk.js";
import addAppLiveTools from "../tools/applive.js";
import addBrowserLiveTools from "../tools/live.js";
import addAccessibilityTools from "../tools/accessibility.js";
import addTestManagementTools from "../tools/testmanagement.js";
import addAppAutomationTools from "../tools/appautomate.js";
import addFailureLogsTools from "../tools/getFailureLogs.js";
import addAutomateTools from "../tools/automate.js";
import addSelfHealTools from "../tools/selfheal.js";

/**
* Set up the product manager with all available products
*/
function setupDynamicProductManager(server: McpServer): ProductManager {
const productManager = new ProductManager(server);

logger.info("Registering product tool registration functions...");

// Register all product tool registration functions
productManager.registerProduct(BrowserStackProduct.SDK, addSDKTools);
productManager.registerProduct(BrowserStackProduct.APP_LIVE, addAppLiveTools);
productManager.registerProduct(
BrowserStackProduct.BROWSER_LIVE,
addBrowserLiveTools,
);
productManager.registerProduct(
BrowserStackProduct.ACCESSIBILITY,
addAccessibilityTools,
);
productManager.registerProduct(
BrowserStackProduct.TEST_MANAGEMENT,
addTestManagementTools,
);
productManager.registerProduct(
BrowserStackProduct.APP_AUTOMATION,
addAppAutomationTools,
);
productManager.registerProduct(
BrowserStackProduct.FAILURE_LOGS,
addFailureLogsTools,
);
productManager.registerProduct(
BrowserStackProduct.AUTOMATE,
addAutomateTools,
);
productManager.registerProduct(
BrowserStackProduct.SELF_HEAL,
addSelfHealTools,
);

logger.info("Product registration functions setup completed.");
return productManager;
}

/**
* Register dynamic tools and product management system
* Only enable_products and get_product_status tools will be available initially
*/
export function registerDynamicTools(server: McpServer): void {
logger.info("Starting dynamic tools registration...");

// Set up the product manager
const productManager = setupDynamicProductManager(server);

// Add the dynamic tools (enable_products and get_product_status)
addDynamicTools(server, productManager);

logger.info(
"Dynamic product management initialized. Use 'enable_products' tool to activate specific BrowserStack capabilities.",
);
}
Loading