Skip to main content
Glama

BrowserStack MCP server

Official
local.ts4.53 kB
import logger from "../logger.js"; import { execSync } from "child_process"; import { Local } from "browserstack-local"; import config from "../config.js"; async function isBrowserStackLocalRunning() { // Check if BrowserStackLocal binary is already running try { if (process.platform === "win32") { const result = execSync( 'tasklist /FI "IMAGENAME eq BrowserStackLocal.exe"', { encoding: "utf8", }, ); if (result.includes("BrowserStackLocal.exe")) { logger.info("BrowserStackLocal binary is already running"); return true; } } else { const result = execSync("pgrep -f BrowserStackLocal", { encoding: "utf8", stdio: "pipe", }).toString(); if (result) { logger.info("BrowserStackLocal binary is already running"); return true; } } logger.info("BrowserStackLocal binary is not running"); return false; } catch (error) { logger.info( "Error checking BrowserStackLocal status, assuming not running ... " + error, ); return false; } } export async function killExistingBrowserStackLocalProcesses() { const isRunning = await isBrowserStackLocalRunning(); if (!isRunning) { return; } // Check and kill any existing BrowserStackLocal processes before starting new one try { if (process.platform === "win32") { // Check if process exists on Windows const checkResult = execSync( 'tasklist /FI "IMAGENAME eq BrowserStackLocal.exe"', { encoding: "utf8" }, ); if (checkResult.includes("BrowserStackLocal.exe")) { execSync("taskkill /F /IM BrowserStackLocal.exe", { stdio: "ignore" }); logger.info("Successfully killed existing BrowserStackLocal processes"); } } else { // Check if process exists on Unix-like systems const checkResult = execSync("pgrep -f BrowserStackLocal", { encoding: "utf8", stdio: "pipe", }).toString(); if (checkResult) { execSync("pkill -f BrowserStackLocal", { stdio: "ignore" }); logger.info("Successfully killed existing BrowserStackLocal processes"); } } } catch (error) { logger.info(`Error checking/killing BrowserStackLocal processes: ${error}`); // Continue execution as there may not be any processes running } } export async function ensureLocalBinarySetup( username: string, password: string, localIdentifier?: string, ): Promise<void> { logger.info( "Ensuring local binary setup as it is required for private URLs...", ); if (config.USE_OWN_LOCAL_BINARY_PROCESS) { logger.info( "Using user's own BrowserStack Local binary process, checking if it's running...", ); const isRunning = await isBrowserStackLocalRunning(); if (!isRunning) { throw new Error( "USE_OWN_LOCAL_BINARY_PROCESS is enabled but BrowserStack Local process is not running. Please start your BrowserStack Local binary process first.", ); } logger.info( "BrowserStack Local process is running, proceeding with user's own process.", ); return; } const localBinary = new Local(); await killExistingBrowserStackLocalProcesses(); // Use a single options object from config and extend with required fields const bsLocalArgs: Record<string, any> = { ...(config.browserstackLocalOptions || {}), key: password, username, }; if (localIdentifier) { bsLocalArgs.localIdentifier = localIdentifier; } return await new Promise((resolve, reject) => { localBinary.start(bsLocalArgs, (error?: Error) => { if (error) { logger.error( `Unable to start BrowserStack Local... please check your credentials and try again. Error: ${error}`, ); reject( new Error( `Unable to configure local tunnel binary, please check your credentials and try again. Error: ${error}`, ), ); } else { logger.info("Successfully started BrowserStack Local"); resolve(); } }); }); } export function isLocalURL(url: string): boolean { try { const urlObj = new URL(url); const hostname = urlObj.hostname.toLowerCase(); return ( hostname === "localhost" || hostname === "127.0.0.1" || hostname.endsWith(".local") || hostname.endsWith(".localhost") ); } catch (error) { logger.error(`Error checking if URL is local: ${error}`); return false; } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/browserstack/mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server