@wdio/mcp 3.2.0 → 3.2.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.
package/lib/server.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/session/state.ts","../package.json","../src/server.ts","../src/tools/navigate.tool.ts","../src/tools/click.tool.ts","../src/utils/zod-helpers.ts","../src/tools/set-value.tool.ts","../src/tools/scroll.tool.ts","../src/tools/cookies.tool.ts","../src/tools/gestures.tool.ts","../src/tools/context.tool.ts","../src/tools/device.tool.ts","../src/tools/execute-script.tool.ts","../src/tools/get-elements.tool.ts","../src/scripts/get-interactable-browser-elements.ts","../src/locators/constants.ts","../src/locators/xml-parsing.ts","../src/locators/element-filter.ts","../src/locators/locator-generation.ts","../src/locators/index.ts","../src/scripts/get-visible-mobile-elements.ts","../src/scripts/get-elements.ts","../src/tools/launch-chrome.tool.ts","../src/tools/emulate-device.tool.ts","../src/recording/step-recorder.ts","../src/resources/browserstack-local.resource.ts","../src/resources/sessions.resource.ts","../src/recording/code-generator.ts","../src/resources/capabilities.resource.ts","../src/resources/elements.resource.ts","../src/resources/accessibility.resource.ts","../src/scripts/get-browser-accessibility-tree.ts","../src/resources/screenshot.resource.ts","../src/resources/cookies.resource.ts","../src/resources/app-state.resource.ts","../src/resources/contexts.resource.ts","../src/resources/geolocation.resource.ts","../src/resources/tabs.resource.ts","../src/tools/session.tool.ts","../src/session/lifecycle.ts","../src/providers/local-browser.provider.ts","../src/config/appium.config.ts","../src/providers/local-appium.provider.ts","../src/providers/cloud/browserstack.provider.ts","../src/providers/registry.ts","../src/tools/tabs.tool.ts","../src/tools/browserstack.tool.ts"],"sourcesContent":["import type { SessionHistory } from '../types/recording';\n\nexport interface SessionMetadata {\n type: 'browser' | 'ios' | 'android';\n capabilities: Record<string, unknown>;\n isAttached: boolean;\n provider?: 'local' | 'browserstack';\n tunnelHandle?: unknown;\n}\n\nconst state = {\n browsers: new Map<string, WebdriverIO.Browser>(),\n currentSession: null as string | null,\n sessionMetadata: new Map<string, SessionMetadata>(),\n sessionHistory: new Map<string, SessionHistory>(),\n};\n\nexport function getBrowser(): WebdriverIO.Browser {\n const browser = state.browsers.get(state.currentSession);\n if (!browser) {\n throw new Error('No active browser session');\n }\n return browser;\n}\n\nexport function getState() {\n return state;\n}\n","{\n \"name\": \"@wdio/mcp\",\n \"mcpName\": \"io.github.webdriverio/mcp\",\n \"author\": \"Vince Graics\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git://github.com/webdriverio/mcp.git\"\n },\n \"version\": \"3.1.1\",\n \"description\": \"MCP server with WebdriverIO for browser and mobile app automation (iOS/Android via Appium)\",\n \"main\": \"./lib/server.js\",\n \"module\": \"./lib/server.js\",\n \"types\": \"./lib/server.d.ts\",\n \"exports\": {\n \".\": {\n \"import\": \"./lib/server.js\",\n \"types\": \"./lib/server.d.ts\"\n },\n \"./snapshot\": {\n \"import\": \"./lib/snapshot.js\",\n \"types\": \"./lib/snapshot.d.ts\"\n }\n },\n \"bin\": {\n \"wdio-mcp\": \"lib/server.js\"\n },\n \"license\": \"MIT\",\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"type\": \"module\",\n \"files\": [\n \"lib\",\n \"README.md\"\n ],\n \"scripts\": {\n \"prebundle\": \"rimraf lib --glob ./*.tgz\",\n \"bundle\": \"tsup && shx chmod +x lib/server.js\",\n \"postbundle\": \"npm pack\",\n \"lint\": \"eslint src/ tests/ --fix && tsc --noEmit\",\n \"start\": \"node lib/server.js\",\n \"dev\": \"tsx --watch src/server.ts\",\n \"prepare\": \"husky\",\n \"test\": \"vitest run\"\n },\n \"dependencies\": {\n \"@modelcontextprotocol/sdk\": \"^1.27.1\",\n \"@toon-format/toon\": \"^2.1.0\",\n \"@wdio/protocols\": \"^9.27.0\",\n \"@xmldom/xmldom\": \"^0.8.12\",\n \"browserstack-local\": \"^1.5.12\",\n \"puppeteer-core\": \"^24.40.0\",\n \"sharp\": \"^0.34.5\",\n \"webdriverio\": \"^9.27.0\",\n \"xpath\": \"^0.0.34\",\n \"zod\": \"^4.3.6\"\n },\n \"devDependencies\": {\n \"@release-it/conventional-changelog\": \"^10.0.6\",\n \"@types/node\": \"^20.19.37\",\n \"@wdio/eslint\": \"^0.1.3\",\n \"@wdio/types\": \"^9.27.0\",\n \"eslint\": \"^9.39.4\",\n \"happy-dom\": \"^20.8.9\",\n \"husky\": \"^9.1.7\",\n \"release-it\": \"^19.2.4\",\n \"rimraf\": \"^6.1.3\",\n \"shx\": \"^0.4.0\",\n \"tsup\": \"^8.5.1\",\n \"tsx\": \"^4.21.0\",\n \"typescript\": \"~5.9.3\",\n \"vitest\": \"^4.1.2\"\n },\n \"packageManager\": \"pnpm@10.32.1\"\n}\n","#!/usr/bin/env node\nimport pkg from '../package.json' with { type: 'json' };\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport type { ToolDefinition } from './types/tool';\nimport type { ResourceDefinition } from './types/resource';\nimport { navigateTool, navigateToolDefinition } from './tools/navigate.tool';\nimport { clickTool, clickToolDefinition } from './tools/click.tool';\nimport { setValueTool, setValueToolDefinition } from './tools/set-value.tool';\nimport { scrollTool, scrollToolDefinition } from './tools/scroll.tool';\nimport {\n deleteCookiesTool,\n deleteCookiesToolDefinition,\n setCookieTool,\n setCookieToolDefinition,\n} from './tools/cookies.tool';\nimport {\n dragAndDropTool,\n dragAndDropToolDefinition,\n swipeTool,\n swipeToolDefinition,\n tapElementTool,\n tapElementToolDefinition,\n} from './tools/gestures.tool';\nimport { switchContextTool, switchContextToolDefinition } from './tools/context.tool';\nimport {\n hideKeyboardTool,\n hideKeyboardToolDefinition,\n rotateDeviceTool,\n rotateDeviceToolDefinition,\n setGeolocationTool,\n setGeolocationToolDefinition,\n} from './tools/device.tool';\nimport { executeScriptTool, executeScriptToolDefinition } from './tools/execute-script.tool';\nimport { getElementsTool, getElementsToolDefinition } from './tools/get-elements.tool';\nimport { launchChromeTool, launchChromeToolDefinition } from './tools/launch-chrome.tool';\nimport { emulateDeviceTool, emulateDeviceToolDefinition } from './tools/emulate-device.tool';\nimport { withRecording } from './recording/step-recorder';\nimport {\n accessibilityResource,\n appStateResource,\n browserstackLocalBinaryResource,\n capabilitiesResource,\n contextResource,\n contextsResource,\n cookiesResource,\n elementsResource,\n geolocationResource,\n screenshotResource,\n sessionCodeResource,\n sessionCurrentCodeResource,\n sessionCurrentStepsResource,\n sessionsIndexResource,\n sessionStepsResource,\n tabsResource,\n} from './resources';\nimport {\n closeSessionTool,\n closeSessionToolDefinition,\n startSessionTool,\n startSessionToolDefinition\n} from './tools/session.tool';\nimport { switchTabTool, switchTabToolDefinition } from './tools/tabs.tool';\nimport {\n listAppsTool,\n listAppsToolDefinition,\n uploadAppTool,\n uploadAppToolDefinition,\n} from './tools/browserstack.tool';\n\nconsole.log = (...args) => console.error('[LOG]', ...args);\nconsole.info = (...args) => console.error('[INFO]', ...args);\nconsole.warn = (...args) => console.error('[WARN]', ...args);\nconsole.debug = (...args) => console.error('[DEBUG]', ...args);\n\nconst server = new McpServer({\n title: 'WebdriverIO MCP Server',\n name: pkg.name,\n version: pkg.version,\n description: pkg.description,\n websiteUrl: 'https://github.com/webdriverio/mcp',\n}, {\n instructions: 'MCP server for browser and mobile app automation using WebDriverIO. Supports Chrome, Firefox, Edge, and Safari browser control plus iOS/Android native app testing via Appium.',\n capabilities: {\n tools: {},\n resources: {},\n },\n});\n\nconst registerTool = (definition: ToolDefinition, callback: ToolCallback) =>\n server.registerTool(definition.name, {\n description: definition.description,\n inputSchema: definition.inputSchema,\n }, callback);\n\nconst registerResource = (definition: ResourceDefinition) => {\n if ('uri' in definition) {\n server.registerResource(\n definition.name,\n definition.uri,\n { description: definition.description },\n definition.handler,\n );\n } else {\n server.registerResource(\n definition.name,\n definition.template,\n { description: definition.description },\n definition.handler,\n );\n }\n};\n\nregisterTool(startSessionToolDefinition, withRecording('start_session', startSessionTool));\nregisterTool(closeSessionToolDefinition, closeSessionTool);\nregisterTool(launchChromeToolDefinition, withRecording('launch_chrome', launchChromeTool));\nregisterTool(emulateDeviceToolDefinition, emulateDeviceTool);\nregisterTool(navigateToolDefinition, withRecording('navigate', navigateTool));\n\nregisterTool(switchTabToolDefinition, switchTabTool);\n\nregisterTool(scrollToolDefinition, withRecording('scroll', scrollTool));\n\nregisterTool(clickToolDefinition, withRecording('click_element', clickTool));\nregisterTool(setValueToolDefinition, withRecording('set_value', setValueTool));\n\nregisterTool(setCookieToolDefinition, setCookieTool);\nregisterTool(deleteCookiesToolDefinition, deleteCookiesTool);\n\nregisterTool(tapElementToolDefinition, withRecording('tap_element', tapElementTool));\nregisterTool(swipeToolDefinition, withRecording('swipe', swipeTool));\nregisterTool(dragAndDropToolDefinition, withRecording('drag_and_drop', dragAndDropTool));\n\nregisterTool(switchContextToolDefinition, switchContextTool);\n\nregisterTool(rotateDeviceToolDefinition, rotateDeviceTool);\nregisterTool(hideKeyboardToolDefinition, hideKeyboardTool);\nregisterTool(setGeolocationToolDefinition, setGeolocationTool);\n\nregisterTool(executeScriptToolDefinition, withRecording('execute_script', executeScriptTool));\nregisterTool(getElementsToolDefinition, getElementsTool);\n\nregisterTool(listAppsToolDefinition, listAppsTool);\nregisterTool(uploadAppToolDefinition, uploadAppTool);\n\nregisterResource(sessionsIndexResource);\nregisterResource(sessionCurrentStepsResource);\nregisterResource(sessionCurrentCodeResource);\nregisterResource(sessionStepsResource);\nregisterResource(sessionCodeResource);\n\nregisterResource(browserstackLocalBinaryResource);\nregisterResource(capabilitiesResource);\nregisterResource(elementsResource);\nregisterResource(accessibilityResource);\nregisterResource(screenshotResource);\nregisterResource(cookiesResource);\nregisterResource(appStateResource);\nregisterResource(contextsResource);\nregisterResource(contextResource);\nregisterResource(geolocationResource);\nregisterResource(tabsResource);\n\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error('WebdriverIO MCP Server running on stdio');\n}\n\nmain().catch((error) => {\n console.error('Fatal error in main():', error);\n process.exit(1);\n});","import { getBrowser } from '../session/state';\nimport { z } from 'zod';\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ToolDefinition } from '../types/tool';\n\nexport const navigateToolDefinition: ToolDefinition = {\n name: 'navigate',\n description: 'navigates to a URL',\n inputSchema: {\n url: z.string().min(1).describe('The URL to navigate to'),\n },\n};\n\nexport const navigateAction = async (url: string): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n await browser.url(url);\n return {\n content: [{ type: 'text', text: `Navigated to ${url}` }],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error navigating: ${e}` }],\n };\n }\n};\n\nexport const navigateTool: ToolCallback = async ({ url }: { url: string }) => navigateAction(url);\n","import { getBrowser } from '../session/state';\nimport { z } from 'zod';\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ToolDefinition } from '../types/tool';\nimport { coerceBoolean } from '../utils/zod-helpers';\n\nconst defaultTimeout: number = 3000;\n\nexport const clickToolDefinition: ToolDefinition = {\n name: 'click_element',\n description: 'clicks an element',\n inputSchema: {\n selector: z.string().describe('Value for the selector, in the form of css selector or xpath (\"button.my-class\" or \"//button[@class=\\'my-class\\']\" or \"button=Exact text with spaces\" or \"a*=Link containing text\")'),\n scrollToView: coerceBoolean.optional().describe('Whether to scroll the element into view before clicking').default(true),\n timeout: z.number().optional().describe('Maximum time to wait for element in milliseconds'),\n },\n};\n\nexport const clickAction = async (selector: string, timeout: number, scrollToView = true): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n await browser.waitUntil(browser.$(selector).isExisting, { timeout });\n if (scrollToView) {\n await browser.$(selector).scrollIntoView({ block: 'center', inline: 'center' });\n }\n await browser.$(selector).click();\n return {\n content: [{ type: 'text', text: `Element clicked (selector: ${selector})` }],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error clicking element: ${e}` }],\n };\n }\n};\n\nexport const clickTool: ToolCallback = async ({ selector, scrollToView, timeout = defaultTimeout }: {\n selector: string;\n scrollToView?: boolean;\n timeout?: number\n}): Promise<CallToolResult> => clickAction(selector, timeout, scrollToView);\n","import { z } from 'zod';\n\nexport const coerceBoolean = z.preprocess((val) => {\n if (typeof val === 'boolean') return val;\n if (typeof val === 'string') {\n if (val === 'false' || val === '0') return false;\n if (val === 'true' || val === '1') return true;\n return Boolean(val);\n }\n return val;\n}, z.boolean());","import { getBrowser } from '../session/state';\nimport { z } from 'zod';\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ToolDefinition } from '../types/tool';\nimport { coerceBoolean } from '../utils/zod-helpers';\n\nconst defaultTimeout: number = 3000;\n\nexport const setValueToolDefinition: ToolDefinition = {\n name: 'set_value',\n description: 'set value to an element, aka typing',\n inputSchema: {\n selector: z.string().describe('Value for the selector, in the form of css selector or xpath (\"button.my-class\" or \"//button[@class=\\'my-class\\']\")'),\n value: z.string().describe('Text to enter into the element'),\n scrollToView: coerceBoolean.optional().describe('Whether to scroll the element into view before typing').default(true),\n timeout: z.number().optional().describe('Maximum time to wait for element in milliseconds'),\n },\n};\n\nexport const setValueAction = async (\n selector: string,\n value: string,\n scrollToView = true,\n timeout = defaultTimeout,\n): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n await browser.waitUntil(browser.$(selector).isExisting, { timeout });\n if (scrollToView) {\n await browser.$(selector).scrollIntoView({ block: 'center', inline: 'center' });\n }\n await browser.$(selector).clearValue();\n await browser.$(selector).setValue(value);\n return {\n content: [{ type: 'text', text: `Text \"${value}\" entered into element` }],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error entering text: ${e}` }],\n };\n }\n};\n\nexport const setValueTool: ToolCallback = async ({ selector, value, scrollToView = true, timeout = defaultTimeout }: {\n selector: string;\n value: string;\n scrollToView?: boolean;\n timeout?: number\n}) => setValueAction(selector, value, scrollToView, timeout);","import { getBrowser, getState } from '../session/state';\nimport { z } from 'zod';\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ToolDefinition } from '../types/tool';\n\nexport const scrollToolDefinition: ToolDefinition = {\n name: 'scroll',\n description: 'scrolls the page by specified pixels (browser only). For mobile, use the swipe tool.',\n inputSchema: {\n direction: z.enum(['up', 'down']).describe('Scroll direction'),\n pixels: z.number().optional().default(500).describe('Number of pixels to scroll'),\n },\n};\n\nexport const scrollAction = async (direction: 'up' | 'down', pixels = 500): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n const state = getState();\n const metadata = state.sessionMetadata.get(state.currentSession);\n const sessionType = metadata?.type;\n\n if (sessionType !== 'browser') {\n throw new Error('scroll only works in browser sessions. For mobile, use the swipe tool.');\n }\n\n const scrollAmount = direction === 'down' ? pixels : -pixels;\n await browser.execute((amount) => {\n window.scrollBy(0, amount);\n }, scrollAmount);\n\n return {\n content: [{ type: 'text', text: `Scrolled ${direction} ${pixels} pixels` }],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error scrolling: ${e}` }],\n };\n }\n};\n\nexport const scrollTool: ToolCallback = async ({ direction, pixels = 500 }: { direction: 'up' | 'down'; pixels?: number }) =>\n scrollAction(direction, pixels);","import type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ToolDefinition } from '../types/tool';\nimport { z } from 'zod';\nimport type { Cookie } from '@wdio/protocols';\nimport { coerceBoolean } from '../utils/zod-helpers';\n\nexport const setCookieToolDefinition: ToolDefinition = {\n name: 'set_cookie',\n description: 'sets a cookie with specified name, value, and optional attributes',\n inputSchema: {\n name: z.string().describe('Cookie name'),\n value: z.string().describe('Cookie value'),\n domain: z.string().optional().describe('Cookie domain (defaults to current domain)'),\n path: z.string().optional().describe('Cookie path (defaults to \"/\")'),\n expiry: z.number().optional().describe('Expiry date as Unix timestamp in seconds'),\n httpOnly: coerceBoolean.optional().describe('HttpOnly flag'),\n secure: coerceBoolean.optional().describe('Secure flag'),\n sameSite: z.enum(['strict', 'lax', 'none']).optional().describe('SameSite attribute'),\n },\n};\n\nexport const setCookieTool: ToolCallback = async ({\n name,\n value,\n domain,\n path = '/',\n expiry,\n httpOnly,\n secure,\n sameSite,\n}: Cookie): Promise<CallToolResult> => {\n try {\n const cookie: Cookie = { name, value, path, domain, expiry, httpOnly, secure, sameSite };\n const { getBrowser } = await import('../session/state');\n const browser = getBrowser();\n await browser.setCookies(cookie);\n\n return {\n content: [{ type: 'text', text: `Cookie \"${name}\" set successfully` }],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error setting cookie: ${e}` }],\n };\n }\n};\n\nexport const deleteCookiesToolDefinition: ToolDefinition = {\n name: 'delete_cookies',\n description: 'deletes all cookies or a specific cookie by name',\n inputSchema: {\n name: z.string().optional().describe('Optional cookie name to delete a specific cookie. If not provided, deletes all cookies'),\n },\n};\n\nexport const deleteCookiesTool: ToolCallback = async ({ name }: { name?: string }): Promise<CallToolResult> => {\n try {\n const { getBrowser } = await import('../session/state');\n const browser = getBrowser();\n\n if (name) {\n await browser.deleteCookies([name]);\n return {\n content: [{ type: 'text', text: `Cookie \"${name}\" deleted successfully` }],\n };\n }\n await browser.deleteCookies();\n return {\n content: [{ type: 'text', text: 'All cookies deleted successfully' }],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error deleting cookies: ${e}` }],\n };\n }\n};","import type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ToolDefinition } from '../types/tool';\nimport { z } from 'zod';\nimport { getBrowser } from '../session/state';\n\n// Tap Tool\nexport const tapElementToolDefinition: ToolDefinition = {\n name: 'tap_element',\n description: 'taps an element by selector or screen coordinates (mobile)',\n inputSchema: {\n selector: z\n .string()\n .optional()\n .describe('Element selector (CSS, XPath, accessibility ID, or UiAutomator)'),\n x: z.number().optional().describe('X coordinate for screen tap (if no selector provided)'),\n y: z.number().optional().describe('Y coordinate for screen tap (if no selector provided)'),\n },\n};\n\nexport const tapAction = async (args: {\n selector?: string;\n x?: number;\n y?: number;\n}): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n const { selector, x, y } = args;\n\n if (selector) {\n const element = await browser.$(selector);\n await element.tap();\n return {\n content: [{ type: 'text', text: `Tapped element: ${selector}` }],\n };\n } else if (x !== undefined && y !== undefined) {\n await browser.tap({ x, y });\n return {\n content: [{ type: 'text', text: `Tapped at coordinates: (${x}, ${y})` }],\n };\n }\n\n return {\n isError: true,\n content: [{ type: 'text', text: 'Error: Must provide either selector or x,y coordinates' }],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error tapping: ${e}` }],\n };\n }\n};\n\nexport const tapElementTool: ToolCallback = async (args: {\n selector?: string;\n x?: number;\n y?: number;\n}): Promise<CallToolResult> => tapAction(args);\n\n// Swipe Tool\nexport const swipeToolDefinition: ToolDefinition = {\n name: 'swipe',\n description: 'performs a swipe gesture in specified direction (mobile)',\n inputSchema: {\n direction: z.enum(['up', 'down', 'left', 'right']).describe('Swipe direction'),\n duration: z\n .number()\n .min(100)\n .max(5000)\n .optional()\n .describe('Swipe duration in milliseconds (default: 500)'),\n percent: z\n .number()\n .min(0)\n .max(1)\n .optional()\n .describe('Percentage of screen to swipe (0-1, default: 0.5 for up/down, 0.95 for left/right)'),\n },\n};\n\n// Map content direction to finger direction (inverted)\n// \"swipe left\" = content moves left = finger moves right\nconst contentToFingerDirection: Record<string, 'up' | 'down' | 'left' | 'right'> = {\n up: 'down',\n down: 'up',\n left: 'right',\n right: 'left',\n};\n\nexport const swipeAction = async (args: {\n direction: 'up' | 'down' | 'left' | 'right';\n duration?: number;\n percent?: number;\n}): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n const { direction, duration, percent } = args;\n\n // Direction-specific defaults: vertical (up/down) = 0.5, horizontal (left/right) = 0.95\n const isVertical = direction === 'up' || direction === 'down';\n const defaultPercent = isVertical ? 0.5 : 0.95;\n const effectivePercent = percent ?? defaultPercent;\n const effectiveDuration = duration ?? 500;\n\n // Convert content direction to finger direction\n const fingerDirection = contentToFingerDirection[direction];\n await browser.swipe({ direction: fingerDirection, duration: effectiveDuration, percent: effectivePercent });\n\n return {\n content: [{ type: 'text', text: `Swiped ${direction}` }],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error swiping: ${e}` }],\n };\n }\n};\n\nexport const swipeTool: ToolCallback = async (args: {\n direction: 'up' | 'down' | 'left' | 'right';\n duration?: number;\n percent?: number;\n}): Promise<CallToolResult> => swipeAction(args);\n\n// Drag and Drop Tool\nexport const dragAndDropToolDefinition: ToolDefinition = {\n name: 'drag_and_drop',\n description: 'drags an element to another element or coordinates (mobile)',\n inputSchema: {\n sourceSelector: z.string().describe('Source element selector to drag'),\n targetSelector: z.string().optional().describe('Target element selector to drop onto'),\n x: z.number().optional().describe('Target X offset (if no targetSelector)'),\n y: z.number().optional().describe('Target Y offset (if no targetSelector)'),\n duration: z.number().min(100).max(5000).optional().describe('Drag duration in milliseconds'),\n },\n};\n\nexport const dragAndDropAction = async (args: {\n sourceSelector: string;\n targetSelector?: string;\n x?: number;\n y?: number;\n duration?: number;\n}): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n const { sourceSelector, targetSelector, x, y, duration } = args;\n\n const sourceElement = await browser.$(sourceSelector);\n\n if (targetSelector) {\n const targetElement = await browser.$(targetSelector);\n await sourceElement.dragAndDrop(targetElement, { duration });\n return {\n content: [{ type: 'text', text: `Dragged ${sourceSelector} to ${targetSelector}` }],\n };\n } else if (x !== undefined && y !== undefined) {\n await sourceElement.dragAndDrop({ x, y }, { duration });\n return {\n content: [{ type: 'text', text: `Dragged ${sourceSelector} by (${x}, ${y})` }],\n };\n }\n\n return {\n isError: true,\n content: [{ type: 'text', text: 'Error: Must provide either targetSelector or x,y coordinates' }],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error dragging: ${e}` }],\n };\n }\n};\n\nexport const dragAndDropTool: ToolCallback = async (args: {\n sourceSelector: string;\n targetSelector?: string;\n x?: number;\n y?: number;\n duration?: number;\n}): Promise<CallToolResult> => dragAndDropAction(args);","import type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ToolDefinition } from '../types/tool';\nimport { z } from 'zod';\nimport { getBrowser } from '../session/state';\n\nexport const switchContextToolDefinition: ToolDefinition = {\n name: 'switch_context',\n description: 'switches between native and webview contexts',\n inputSchema: {\n context: z\n .string()\n .describe(\n 'Context name to switch to (e.g., \"NATIVE_APP\", \"WEBVIEW_com.example.app\", or use index from wdio://session/current/contexts resource)',\n ),\n },\n};\n\nexport const switchContextTool: ToolCallback = async (args: {\n context: string;\n}): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n const { context } = args;\n\n if (/^\\d+$/.test(context)) {\n const contexts = await browser.getContexts();\n const index = Number.parseInt(context, 10) - 1;\n if (index >= 0 && index < contexts.length) {\n const targetContext = contexts[index] as string;\n await browser.switchContext(targetContext);\n return { content: [{ type: 'text', text: `Switched to context: ${targetContext}` }] };\n }\n throw new Error(`Error: Invalid context index ${context}. Available contexts: ${contexts.length}`);\n\n }\n\n await browser.switchContext(context);\n\n return {\n content: [{ type: 'text', text: `Switched to context: ${context}` }],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error switching context: ${e}` }],\n };\n }\n};","import type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ToolDefinition } from '../types/tool';\nimport { z } from 'zod';\nimport { getBrowser } from '../session/state';\n\nexport const hideKeyboardToolDefinition: ToolDefinition = {\n name: 'hide_keyboard',\n description: 'hides the on-screen keyboard',\n inputSchema: {},\n};\n\nexport const rotateDeviceToolDefinition: ToolDefinition = {\n name: 'rotate_device',\n description: 'rotates device to portrait or landscape orientation',\n inputSchema: {\n orientation: z.enum(['PORTRAIT', 'LANDSCAPE']).describe('Device orientation'),\n },\n};\n\nexport const setGeolocationToolDefinition: ToolDefinition = {\n name: 'set_geolocation',\n description: 'sets device geolocation (latitude, longitude, altitude)',\n inputSchema: {\n latitude: z.number().min(-90).max(90).describe('Latitude coordinate'),\n longitude: z.number().min(-180).max(180).describe('Longitude coordinate'),\n altitude: z.number().optional().describe('Altitude in meters (optional)'),\n },\n};\n\nexport const rotateDeviceTool: ToolCallback = async (args: {\n orientation: 'PORTRAIT' | 'LANDSCAPE';\n}): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n const { orientation } = args;\n\n await browser.setOrientation(orientation);\n\n return {\n content: [{ type: 'text', text: `Device rotated to: ${orientation}` }],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error rotating device: ${e}` }],\n };\n }\n};\n\nexport const hideKeyboardTool: ToolCallback = async (): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n\n await browser.hideKeyboard();\n\n return {\n content: [{ type: 'text', text: 'Keyboard hidden' }],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error hiding keyboard: ${e}` }],\n };\n }\n};\n\nexport const setGeolocationTool: ToolCallback = async (args: {\n latitude: number;\n longitude: number;\n altitude?: number;\n}): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n const { latitude, longitude, altitude } = args;\n\n await browser.setGeoLocation({ latitude, longitude, altitude });\n\n return {\n content: [\n {\n type: 'text',\n text: `Geolocation set to:\\n Latitude: ${latitude}\\n Longitude: ${longitude}${altitude ? `\\n Altitude: ${altitude}m` : ''}`,\n },\n ],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error setting geolocation: ${e}` }],\n };\n }\n};","import type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ToolDefinition } from '../types/tool';\nimport { z } from 'zod';\nimport { getBrowser } from '../session/state';\n\nexport const executeScriptToolDefinition: ToolDefinition = {\n name: 'execute_script',\n description: `Executes JavaScript in browser or mobile commands via Appium.\n\n**Option B for browser interaction** — prefer get_visible_elements or click_element/set_value with a selector instead. Use execute_script only when no dedicated tool covers the action (e.g. reading computed values, triggering custom events, scrolling to a position).\n\n**Browser:** Runs JavaScript in page context. Use 'return' to get values back.\n - Example: execute_script({ script: \"return document.title\" })\n - Example: execute_script({ script: \"return window.scrollY\" })\n - Example: execute_script({ script: \"arguments[0].click()\", args: [\"#myButton\"] })\n\n**Mobile (Appium):** Executes mobile-specific commands using 'mobile: <command>' syntax.\n - Press key (Android): execute_script({ script: \"mobile: pressKey\", args: [{ keycode: 4 }] }) // BACK=4, HOME=3\n - Activate app: execute_script({ script: \"mobile: activateApp\", args: [{ appId: \"com.example\" }] })\n - Terminate app: execute_script({ script: \"mobile: terminateApp\", args: [{ appId: \"com.example\" }] })\n - Deep link: execute_script({ script: \"mobile: deepLink\", args: [{ url: \"myapp://screen\", package: \"com.example\" }] })\n - Shell command (Android): execute_script({ script: \"mobile: shell\", args: [{ command: \"dumpsys\", args: [\"battery\"] }] })`,\n inputSchema: {\n script: z.string().describe('JavaScript code (browser) or mobile command string like \"mobile: pressKey\" (Appium)'),\n args: z.array(z.any()).optional().describe('Arguments to pass to the script. For browser: element selectors or values. For mobile commands: command-specific parameters as objects.'),\n },\n};\n\nexport const executeScriptTool: ToolCallback = async (args: {\n script: string;\n args?: unknown[];\n}): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n const { script, args: scriptArgs = [] } = args;\n\n // For browser scripts with selector arguments, resolve them to elements\n const resolvedArgs = await Promise.all(\n scriptArgs.map(async (arg) => {\n // If it's a string that looks like a selector and we're in browser context, try to resolve it\n if (typeof arg === 'string' && !script.startsWith('mobile:')) {\n try {\n const element = await browser.$(arg);\n if (await element.isExisting()) {\n return element;\n }\n } catch {\n // Not a valid selector, pass as-is\n }\n }\n return arg;\n })\n );\n\n const result = await browser.execute(script, ...resolvedArgs);\n\n // Format result for display\n let resultText: string;\n if (result === undefined || result === null) {\n resultText = 'Script executed successfully (no return value)';\n } else if (typeof result === 'object') {\n try {\n resultText = `Result: ${JSON.stringify(result, null, 2)}`;\n } catch {\n resultText = `Result: ${String(result)}`;\n }\n } else {\n resultText = `Result: ${result}`;\n }\n\n return {\n content: [{ type: 'text', text: resultText }],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error executing script: ${e}` }],\n };\n }\n};\n","import { z } from 'zod';\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ToolDefinition } from '../types/tool';\nimport { getBrowser } from '../session/state';\nimport { getElements } from '../scripts/get-elements';\nimport { encode } from '@toon-format/toon';\nimport { coerceBoolean } from '../utils/zod-helpers';\n\nexport const getElementsToolDefinition: ToolDefinition = {\n name: 'get_elements',\n description: 'Get interactable elements on the current page. Use when wdio://session/current/elements does not return the desired elements.',\n inputSchema: {\n inViewportOnly: coerceBoolean.optional().default(false).describe('Only return elements visible in the current viewport (default: false).'),\n includeContainers: coerceBoolean.optional().default(false).describe('Include container elements like divs and sections (default: false)'),\n includeBounds: coerceBoolean.optional().default(false).describe('Include element bounding box coordinates (default: false)'),\n limit: z.number().optional().default(0).describe('Maximum number of elements to return (0 = no limit)'),\n offset: z.number().optional().default(0).describe('Number of elements to skip (for pagination)'),\n },\n};\n\nexport const getElementsTool: ToolCallback = async ({\n inViewportOnly = false,\n includeContainers = false,\n includeBounds = false,\n limit = 0,\n offset = 0,\n}: {\n inViewportOnly?: boolean;\n includeContainers?: boolean;\n includeBounds?: boolean;\n limit?: number;\n offset?: number;\n}) => {\n try {\n const browser = getBrowser();\n const result = await getElements(browser, { inViewportOnly, includeContainers, includeBounds, limit, offset });\n const text = encode(result).replace(/,\"\"/g, ',').replace(/\"\",/g, ',');\n return { content: [{ type: 'text' as const, text }] };\n } catch (e) {\n return { isError: true as const, content: [{ type: 'text' as const, text: `Error getting elements: ${e}` }] };\n }\n};\n","/**\n * Browser element detection\n * Single browser.execute() call: querySelectorAll → flat interactable element list\n *\n * NOTE: This script runs in browser context via browser.execute()\n * It must be self-contained with no external dependencies\n */\n\nexport interface BrowserElementInfo {\n tagName: string;\n name: string; // computed accessible name (ARIA spec)\n type: string;\n value: string;\n href: string;\n selector: string;\n isInViewport: boolean;\n boundingBox?: { x: number; y: number; width: number; height: number };\n}\n\nexport interface GetBrowserElementsOptions {\n includeBounds?: boolean;\n}\n\nconst elementsScript = (includeBounds: boolean) => (function () {\n const interactableSelectors = [\n 'a[href]',\n 'button',\n 'input:not([type=\"hidden\"])',\n 'select',\n 'textarea',\n '[role=\"button\"]',\n '[role=\"link\"]',\n '[role=\"checkbox\"]',\n '[role=\"radio\"]',\n '[role=\"tab\"]',\n '[role=\"menuitem\"]',\n '[role=\"combobox\"]',\n '[role=\"option\"]',\n '[role=\"switch\"]',\n '[role=\"slider\"]',\n '[role=\"textbox\"]',\n '[role=\"searchbox\"]',\n '[role=\"spinbutton\"]',\n '[contenteditable=\"true\"]',\n '[tabindex]:not([tabindex=\"-1\"])',\n ].join(',');\n\n function isVisible(element: HTMLElement): boolean {\n if (typeof element.checkVisibility === 'function') {\n return element.checkVisibility({ opacityProperty: true, visibilityProperty: true, contentVisibilityAuto: true });\n }\n const style = window.getComputedStyle(element);\n return style.display !== 'none' &&\n style.visibility !== 'hidden' &&\n style.opacity !== '0' &&\n element.offsetWidth > 0 &&\n element.offsetHeight > 0;\n }\n\n function getAccessibleName(el: HTMLElement): string {\n // 1. aria-label\n const ariaLabel = el.getAttribute('aria-label');\n if (ariaLabel) return ariaLabel.trim();\n\n // 2. aria-labelledby — resolve referenced elements\n const labelledBy = el.getAttribute('aria-labelledby');\n if (labelledBy) {\n const texts = labelledBy.split(/\\s+/)\n .map(id => document.getElementById(id)?.textContent?.trim() || '')\n .filter(Boolean);\n if (texts.length > 0) return texts.join(' ').slice(0, 100);\n }\n\n const tag = el.tagName.toLowerCase();\n\n // 3. alt for images and input[type=image]\n if (tag === 'img' || (tag === 'input' && el.getAttribute('type') === 'image')) {\n const alt = el.getAttribute('alt');\n if (alt !== null) return alt.trim();\n }\n\n // 4. label[for=id] for form elements\n if (['input', 'select', 'textarea'].includes(tag)) {\n const id = el.getAttribute('id');\n if (id) {\n const label = document.querySelector(`label[for=\"${CSS.escape(id)}\"]`);\n if (label) return label.textContent?.trim() || '';\n }\n // 5. Wrapping label — clone, strip inputs, read text\n const parentLabel = el.closest('label');\n if (parentLabel) {\n const clone = parentLabel.cloneNode(true) as HTMLElement;\n clone.querySelectorAll('input,select,textarea').forEach(n => n.remove());\n const lt = clone.textContent?.trim();\n if (lt) return lt;\n }\n }\n\n // 6. placeholder\n const ph = el.getAttribute('placeholder');\n if (ph) return ph.trim();\n\n // 7. title\n const title = el.getAttribute('title');\n if (title) return title.trim();\n\n // 8. text content (truncated, whitespace normalized)\n return (el.textContent?.trim().replace(/\\s+/g, ' ') || '').slice(0, 100);\n }\n\n function getSelector(element: HTMLElement): string {\n const tag = element.tagName.toLowerCase();\n\n // 1. tag*=Text — best per WebdriverIO docs\n const text = element.textContent?.trim().replace(/\\s+/g, ' ');\n if (text && text.length > 0 && text.length <= 50) {\n const sameTagElements = document.querySelectorAll(tag);\n let matchCount = 0;\n sameTagElements.forEach(el => {\n if (el.textContent?.includes(text)) matchCount++;\n });\n if (matchCount === 1) return `${tag}*=${text}`;\n }\n\n // 2. aria/label\n const ariaLabel = element.getAttribute('aria-label');\n if (ariaLabel && ariaLabel.length <= 80) return `aria/${ariaLabel}`;\n\n // 3. data-testid\n const testId = element.getAttribute('data-testid');\n if (testId) {\n const sel = `[data-testid=\"${CSS.escape(testId)}\"]`;\n if (document.querySelectorAll(sel).length === 1) return sel;\n }\n\n // 4. #id\n if (element.id) return `#${CSS.escape(element.id)}`;\n\n // 5. [name] — form elements\n const nameAttr = element.getAttribute('name');\n if (nameAttr) {\n const sel = `${tag}[name=\"${CSS.escape(nameAttr)}\"]`;\n if (document.querySelectorAll(sel).length === 1) return sel;\n }\n\n // 6. tag.class — try each class individually, then first-two combination\n if (element.className && typeof element.className === 'string') {\n const classes = element.className.trim().split(/\\s+/).filter(Boolean);\n for (const cls of classes) {\n const sel = `${tag}.${CSS.escape(cls)}`;\n if (document.querySelectorAll(sel).length === 1) return sel;\n }\n if (classes.length >= 2) {\n const sel = `${tag}${classes.slice(0, 2).map(c => `.${CSS.escape(c)}`).join('')}`;\n if (document.querySelectorAll(sel).length === 1) return sel;\n }\n }\n\n // 7. CSS path fallback\n let current: HTMLElement | null = element;\n const path: string[] = [];\n while (current && current !== document.documentElement) {\n let seg = current.tagName.toLowerCase();\n if (current.id) {\n path.unshift(`#${CSS.escape(current.id)}`);\n break;\n }\n const parent = current.parentElement;\n if (parent) {\n const siblings = Array.from(parent.children).filter(c => c.tagName === current!.tagName);\n if (siblings.length > 1) seg += `:nth-of-type(${siblings.indexOf(current) + 1})`;\n }\n path.unshift(seg);\n current = current.parentElement;\n if (path.length >= 4) break;\n }\n return path.join(' > ');\n }\n\n const elements: Record<string, unknown>[] = [];\n const seen = new Set<Element>();\n\n document.querySelectorAll(interactableSelectors).forEach((el) => {\n if (seen.has(el)) return;\n seen.add(el);\n\n const htmlEl = el as HTMLElement;\n if (!isVisible(htmlEl)) return;\n\n const inputEl = htmlEl as HTMLInputElement;\n const rect = htmlEl.getBoundingClientRect();\n const isInViewport = (\n rect.top >= 0 &&\n rect.left >= 0 &&\n rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&\n rect.right <= (window.innerWidth || document.documentElement.clientWidth)\n );\n\n const entry: Record<string, unknown> = {\n tagName: htmlEl.tagName.toLowerCase(),\n name: getAccessibleName(htmlEl),\n type: htmlEl.getAttribute('type') || '',\n value: inputEl.value || '',\n href: htmlEl.getAttribute('href') || '',\n selector: getSelector(htmlEl),\n isInViewport,\n };\n\n if (includeBounds) {\n entry.boundingBox = {\n x: rect.x + window.scrollX,\n y: rect.y + window.scrollY,\n width: rect.width,\n height: rect.height,\n };\n }\n\n elements.push(entry);\n });\n\n return elements;\n})();\n\n/**\n * Get interactable browser elements via querySelectorAll.\n */\nexport async function getInteractableBrowserElements(\n browser: WebdriverIO.Browser,\n options: GetBrowserElementsOptions = {},\n): Promise<BrowserElementInfo[]> {\n const { includeBounds = false } = options;\n return (browser as any).execute(elementsScript, includeBounds) as unknown as Promise<BrowserElementInfo[]>;\n}\n\nexport default elementsScript;\n","/**\n * Platform-specific element tag constants for mobile automation\n */\n\nexport const ANDROID_INTERACTABLE_TAGS = [\n // Input elements\n 'android.widget.EditText',\n 'android.widget.AutoCompleteTextView',\n 'android.widget.MultiAutoCompleteTextView',\n 'android.widget.SearchView',\n\n // Button-like elements\n 'android.widget.Button',\n 'android.widget.ImageButton',\n 'android.widget.ToggleButton',\n 'android.widget.CompoundButton',\n 'android.widget.RadioButton',\n 'android.widget.CheckBox',\n 'android.widget.Switch',\n 'android.widget.FloatingActionButton',\n 'com.google.android.material.button.MaterialButton',\n 'com.google.android.material.floatingactionbutton.FloatingActionButton',\n\n // Text elements (often tappable)\n 'android.widget.TextView',\n 'android.widget.CheckedTextView',\n\n // Image elements (often tappable)\n 'android.widget.ImageView',\n 'android.widget.QuickContactBadge',\n\n // Selection elements\n 'android.widget.Spinner',\n 'android.widget.SeekBar',\n 'android.widget.RatingBar',\n 'android.widget.ProgressBar',\n 'android.widget.DatePicker',\n 'android.widget.TimePicker',\n 'android.widget.NumberPicker',\n\n // List/grid items\n 'android.widget.AdapterView',\n];\n\nexport const ANDROID_LAYOUT_CONTAINERS = [\n // Core ViewGroup classes\n 'android.view.ViewGroup',\n 'android.view.View',\n 'android.widget.FrameLayout',\n 'android.widget.LinearLayout',\n 'android.widget.RelativeLayout',\n 'android.widget.GridLayout',\n 'android.widget.TableLayout',\n 'android.widget.TableRow',\n 'android.widget.AbsoluteLayout',\n\n // AndroidX layout classes\n 'androidx.constraintlayout.widget.ConstraintLayout',\n 'androidx.coordinatorlayout.widget.CoordinatorLayout',\n 'androidx.appcompat.widget.LinearLayoutCompat',\n 'androidx.cardview.widget.CardView',\n 'androidx.appcompat.widget.ContentFrameLayout',\n 'androidx.appcompat.widget.FitWindowsFrameLayout',\n\n // Scrolling containers\n 'android.widget.ScrollView',\n 'android.widget.HorizontalScrollView',\n 'android.widget.NestedScrollView',\n 'androidx.core.widget.NestedScrollView',\n 'androidx.recyclerview.widget.RecyclerView',\n 'android.widget.ListView',\n 'android.widget.GridView',\n 'android.widget.AbsListView',\n\n // App chrome / system elements\n 'android.widget.ActionBarContainer',\n 'android.widget.ActionBarOverlayLayout',\n 'android.view.ViewStub',\n 'androidx.appcompat.widget.ActionBarContainer',\n 'androidx.appcompat.widget.ActionBarContextView',\n 'androidx.appcompat.widget.ActionBarOverlayLayout',\n\n // Decor views\n 'com.android.internal.policy.DecorView',\n 'android.widget.DecorView',\n];\n\nexport const IOS_INTERACTABLE_TAGS = [\n // Input elements\n 'XCUIElementTypeTextField',\n 'XCUIElementTypeSecureTextField',\n 'XCUIElementTypeTextView',\n 'XCUIElementTypeSearchField',\n\n // Button-like elements\n 'XCUIElementTypeButton',\n 'XCUIElementTypeLink',\n\n // Text elements (often tappable)\n 'XCUIElementTypeStaticText',\n\n // Image elements\n 'XCUIElementTypeImage',\n 'XCUIElementTypeIcon',\n\n // Selection elements\n 'XCUIElementTypeSwitch',\n 'XCUIElementTypeSlider',\n 'XCUIElementTypeStepper',\n 'XCUIElementTypeSegmentedControl',\n 'XCUIElementTypePicker',\n 'XCUIElementTypePickerWheel',\n 'XCUIElementTypeDatePicker',\n 'XCUIElementTypePageIndicator',\n\n // Table/list items\n 'XCUIElementTypeCell',\n 'XCUIElementTypeMenuItem',\n 'XCUIElementTypeMenuBarItem',\n\n // Toggle elements\n 'XCUIElementTypeCheckBox',\n 'XCUIElementTypeRadioButton',\n 'XCUIElementTypeToggle',\n\n // Other interactive\n 'XCUIElementTypeKey',\n 'XCUIElementTypeKeyboard',\n 'XCUIElementTypeAlert',\n 'XCUIElementTypeSheet',\n];\n\nexport const IOS_LAYOUT_CONTAINERS = [\n // Generic containers\n 'XCUIElementTypeOther',\n 'XCUIElementTypeGroup',\n 'XCUIElementTypeLayoutItem',\n\n // Scroll containers\n 'XCUIElementTypeScrollView',\n 'XCUIElementTypeTable',\n 'XCUIElementTypeCollectionView',\n 'XCUIElementTypeScrollBar',\n\n // Navigation chrome\n 'XCUIElementTypeNavigationBar',\n 'XCUIElementTypeTabBar',\n 'XCUIElementTypeToolbar',\n 'XCUIElementTypeStatusBar',\n 'XCUIElementTypeMenuBar',\n\n // Windows and views\n 'XCUIElementTypeWindow',\n 'XCUIElementTypeSheet',\n 'XCUIElementTypeDrawer',\n 'XCUIElementTypeDialog',\n 'XCUIElementTypePopover',\n 'XCUIElementTypePopUpButton',\n\n // Outline elements\n 'XCUIElementTypeOutline',\n 'XCUIElementTypeOutlineRow',\n 'XCUIElementTypeBrowser',\n 'XCUIElementTypeSplitGroup',\n 'XCUIElementTypeSplitter',\n\n // Application root\n 'XCUIElementTypeApplication',\n];\n","/**\n * XML parsing utilities for mobile element source\n */\n\nimport { DOMParser } from '@xmldom/xmldom';\nimport xpath from 'xpath';\nimport type { ElementAttributes, JSONElement, Bounds, UniquenessResult } from './types';\n\n/**\n * Get child nodes that are elements (not text nodes, comments, etc.)\n */\nfunction childNodesOf(node: Node): Node[] {\n const children: Node[] = [];\n if (node.childNodes) {\n for (let i = 0; i < node.childNodes.length; i++) {\n const child = node.childNodes.item(i);\n if (child?.nodeType === 1) {\n children.push(child);\n }\n }\n }\n return children;\n}\n\n/**\n * Recursively translate DOM node to JSONElement\n */\nfunction translateRecursively(\n domNode: Node,\n parentPath: string = '',\n index: number | null = null,\n): JSONElement {\n const attributes: ElementAttributes = {};\n\n const element = domNode as Element;\n if (element.attributes) {\n for (let attrIdx = 0; attrIdx < element.attributes.length; attrIdx++) {\n const attr = element.attributes.item(attrIdx);\n if (attr) {\n attributes[attr.name] = attr.value.replace(/(\\n)/gm, '\\\\n');\n }\n }\n }\n\n const path = index === null ? '' : `${parentPath ? parentPath + '.' : ''}${index}`;\n\n return {\n children: childNodesOf(domNode).map((childNode, childIndex) =>\n translateRecursively(childNode, path, childIndex),\n ),\n tagName: domNode.nodeName,\n attributes,\n path,\n };\n}\n\n/**\n * Compare two nodes for equality by platform-specific attributes\n * (reference equality via === may fail when nodes come from different traversals)\n */\nfunction isSameElement(node1: Node, node2: Node): boolean {\n if (node1.nodeType !== 1 || node2.nodeType !== 1) return false;\n const el1 = node1 as Element;\n const el2 = node2 as Element;\n\n if (el1.nodeName !== el2.nodeName) return false;\n\n // For Android, compare by bounds (unique per element)\n const bounds1 = el1.getAttribute('bounds');\n const bounds2 = el2.getAttribute('bounds');\n if (bounds1 && bounds2) {\n return bounds1 === bounds2;\n }\n\n // For iOS, compare by x, y, width, height\n const x1 = el1.getAttribute('x');\n const y1 = el1.getAttribute('y');\n const x2 = el2.getAttribute('x');\n const y2 = el2.getAttribute('y');\n if (x1 && y1 && x2 && y2) {\n return (\n x1 === x2 &&\n y1 === y2 &&\n el1.getAttribute('width') === el2.getAttribute('width') &&\n el1.getAttribute('height') === el2.getAttribute('height')\n );\n }\n\n return false;\n}\n\n/**\n * Convert XML page source to JSON tree structure\n */\nexport function xmlToJSON(sourceXML: string): JSONElement | null {\n try {\n const parser = new DOMParser();\n const sourceDoc = parser.parseFromString(sourceXML, 'text/xml');\n\n const parseErrors = sourceDoc.getElementsByTagName('parsererror');\n if (parseErrors.length > 0) {\n console.error('[xmlToJSON] XML parsing error:', parseErrors[0].textContent);\n return null;\n }\n\n const children = childNodesOf(sourceDoc);\n const firstChild =\n children[0] ||\n (sourceDoc.documentElement ? childNodesOf(sourceDoc.documentElement)[0] : null);\n\n return firstChild\n ? translateRecursively(firstChild)\n : { children: [], tagName: '', attributes: {}, path: '' };\n } catch (e) {\n console.error('[xmlToJSON] Failed to parse XML:', e);\n return null;\n }\n}\n\n/**\n * Parse XML source to DOM Document for XPath evaluation\n */\nexport function xmlToDOM(sourceXML: string): Document | null {\n try {\n const parser = new DOMParser();\n const doc = parser.parseFromString(sourceXML, 'text/xml');\n\n const parseErrors = doc.getElementsByTagName('parsererror');\n if (parseErrors.length > 0) {\n console.error('[xmlToDOM] XML parsing error:', parseErrors[0].textContent);\n return null;\n }\n\n return doc;\n } catch (e) {\n console.error('[xmlToDOM] Failed to parse XML:', e);\n return null;\n }\n}\n\n/**\n * Execute XPath query on DOM document\n */\nexport function evaluateXPath(doc: Document, xpathExpr: string): Node[] {\n try {\n const nodes = xpath.select(xpathExpr, doc);\n if (Array.isArray(nodes)) {\n return nodes as Node[];\n }\n return [];\n } catch (e) {\n console.error(`[evaluateXPath] Failed to evaluate \"${xpathExpr}\":`, e);\n return [];\n }\n}\n\n/**\n * Check if an XPath selector is unique and get index if not\n */\nexport function checkXPathUniqueness(\n doc: Document,\n xpathExpr: string,\n targetNode?: Node,\n): UniquenessResult {\n try {\n const nodes = evaluateXPath(doc, xpathExpr);\n const totalMatches = nodes.length;\n\n if (totalMatches === 0) {\n return { isUnique: false };\n }\n\n if (totalMatches === 1) {\n return { isUnique: true };\n }\n\n // Not unique - find index of target node if provided\n if (targetNode) {\n for (let i = 0; i < nodes.length; i++) {\n if (nodes[i] === targetNode || isSameElement(nodes[i], targetNode)) {\n return {\n isUnique: false,\n index: i + 1, // 1-based index for XPath\n totalMatches,\n };\n }\n }\n }\n\n return { isUnique: false, totalMatches };\n } catch (e) {\n console.error(`[checkXPathUniqueness] Error checking \"${xpathExpr}\":`, e);\n return { isUnique: false };\n }\n}\n\n/**\n * Find DOM node by JSONElement path (e.g., \"0.2.1\")\n */\nexport function findDOMNodeByPath(doc: Document, path: string): Node | null {\n if (!path) return doc.documentElement;\n\n const indices = path.split('.').map(Number);\n let current: Node | null = doc.documentElement;\n\n for (const index of indices) {\n if (!current) return null;\n\n const children: Node[] = [];\n if (current.childNodes) {\n for (let i = 0; i < current.childNodes.length; i++) {\n const child = current.childNodes.item(i);\n if (child?.nodeType === 1) {\n children.push(child);\n }\n }\n }\n\n current = children[index] || null;\n }\n\n return current;\n}\n\n/**\n * Parse Android bounds string \"[x1,y1][x2,y2]\" to coordinates\n */\nexport function parseAndroidBounds(bounds: string): Bounds {\n const match = bounds.match(/\\[(\\d+),(\\d+)\\]\\[(\\d+),(\\d+)\\]/);\n if (!match) {\n return { x: 0, y: 0, width: 0, height: 0 };\n }\n\n const x1 = parseInt(match[1], 10);\n const y1 = parseInt(match[2], 10);\n const x2 = parseInt(match[3], 10);\n const y2 = parseInt(match[4], 10);\n\n return {\n x: x1,\n y: y1,\n width: x2 - x1,\n height: y2 - y1,\n };\n}\n\n/**\n * Parse iOS element bounds from individual x, y, width, height attributes\n */\nexport function parseIOSBounds(attributes: ElementAttributes): Bounds {\n return {\n x: parseInt(attributes.x || '0', 10),\n y: parseInt(attributes.y || '0', 10),\n width: parseInt(attributes.width || '0', 10),\n height: parseInt(attributes.height || '0', 10),\n };\n}\n\n/**\n * Flatten JSON element tree to array (depth-first)\n */\nexport function flattenElementTree(root: JSONElement): JSONElement[] {\n const result: JSONElement[] = [];\n\n function traverse(element: JSONElement) {\n result.push(element);\n for (const child of element.children) {\n traverse(child);\n }\n }\n\n traverse(root);\n return result;\n}\n\n/**\n * Count occurrences of an attribute value in the source XML\n */\nexport function countAttributeOccurrences(\n sourceXML: string,\n attribute: string,\n value: string,\n): number {\n const escapedValue = value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const pattern = new RegExp(`${attribute}=[\"']${escapedValue}[\"']`, 'g');\n const matches = sourceXML.match(pattern);\n return matches ? matches.length : 0;\n}\n\n/**\n * Check if an attribute value is unique in the source (fast regex-based check)\n */\nexport function isAttributeUnique(\n sourceXML: string,\n attribute: string,\n value: string,\n): boolean {\n return countAttributeOccurrences(sourceXML, attribute, value) === 1;\n}\n","/**\n * Element filtering logic for mobile automation\n */\n\nimport type { JSONElement, FilterOptions } from './types';\nimport {\n ANDROID_INTERACTABLE_TAGS,\n IOS_INTERACTABLE_TAGS,\n ANDROID_LAYOUT_CONTAINERS,\n IOS_LAYOUT_CONTAINERS,\n} from './constants';\n\n/**\n * Check if element tag matches any in the list (handles partial matches)\n */\nfunction matchesTagList(tagName: string, tagList: string[]): boolean {\n if (tagList.includes(tagName)) {\n return true;\n }\n\n for (const tag of tagList) {\n if (tagName.endsWith(tag) || tagName.includes(tag)) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Check if element matches tag name filters\n */\nfunction matchesTagFilters(\n element: JSONElement,\n includeTagNames: string[],\n excludeTagNames: string[],\n): boolean {\n if (includeTagNames.length > 0 && !matchesTagList(element.tagName, includeTagNames)) {\n return false;\n }\n\n if (matchesTagList(element.tagName, excludeTagNames)) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Check if element matches attribute-based filters\n */\nfunction matchesAttributeFilters(\n element: JSONElement,\n requireAttributes: string[],\n minAttributeCount: number,\n): boolean {\n if (requireAttributes.length > 0) {\n const hasRequiredAttr = requireAttributes.some((attr) => element.attributes?.[attr]);\n if (!hasRequiredAttr) return false;\n }\n\n if (element.attributes && minAttributeCount > 0) {\n const attrCount = Object.values(element.attributes).filter(\n (v) => v !== undefined && v !== null && v !== '',\n ).length;\n if (attrCount < minAttributeCount) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Check if element is interactable based on platform\n */\nexport function isInteractableElement(\n element: JSONElement,\n isNative: boolean,\n automationName: string,\n): boolean {\n const isAndroid = automationName.toLowerCase().includes('uiautomator');\n const interactableTags = isAndroid ? ANDROID_INTERACTABLE_TAGS : IOS_INTERACTABLE_TAGS;\n\n if (matchesTagList(element.tagName, interactableTags)) {\n return true;\n }\n\n if (isAndroid) {\n if (\n element.attributes?.clickable === 'true' ||\n element.attributes?.focusable === 'true' ||\n element.attributes?.checkable === 'true' ||\n element.attributes?.['long-clickable'] === 'true'\n ) {\n return true;\n }\n }\n\n if (!isAndroid) {\n if (element.attributes?.accessible === 'true') {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Check if element is a layout container\n */\nexport function isLayoutContainer(element: JSONElement, platform: 'android' | 'ios'): boolean {\n const containerList = platform === 'android' ? ANDROID_LAYOUT_CONTAINERS : IOS_LAYOUT_CONTAINERS;\n return matchesTagList(element.tagName, containerList);\n}\n\n/**\n * Check if element has meaningful content (text, accessibility info)\n */\nexport function hasMeaningfulContent(\n element: JSONElement,\n platform: 'android' | 'ios',\n): boolean {\n const attrs = element.attributes;\n\n if (attrs.text && attrs.text.trim() !== '' && attrs.text !== 'null') {\n return true;\n }\n\n if (platform === 'android') {\n if (attrs['content-desc'] && attrs['content-desc'].trim() !== '' && attrs['content-desc'] !== 'null') {\n return true;\n }\n } else {\n if (attrs.label && attrs.label.trim() !== '' && attrs.label !== 'null') {\n return true;\n }\n if (attrs.name && attrs.name.trim() !== '' && attrs.name !== 'null') {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Determine if an element should be included based on all filter criteria\n */\nexport function shouldIncludeElement(\n element: JSONElement,\n filters: FilterOptions,\n isNative: boolean,\n automationName: string,\n): boolean {\n const {\n includeTagNames = [],\n excludeTagNames = ['hierarchy'],\n requireAttributes = [],\n minAttributeCount = 0,\n fetchableOnly = false,\n clickableOnly = false,\n visibleOnly = true,\n } = filters;\n\n if (!matchesTagFilters(element, includeTagNames, excludeTagNames)) {\n return false;\n }\n\n if (!matchesAttributeFilters(element, requireAttributes, minAttributeCount)) {\n return false;\n }\n\n if (clickableOnly && element.attributes?.clickable !== 'true') {\n return false;\n }\n\n if (visibleOnly) {\n const isAndroid = automationName.toLowerCase().includes('uiautomator');\n if (isAndroid && element.attributes?.displayed === 'false') {\n return false;\n }\n if (!isAndroid && element.attributes?.visible === 'false') {\n return false;\n }\n }\n\n if (fetchableOnly && !isInteractableElement(element, isNative, automationName)) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Get default filter options for a platform\n */\nexport function getDefaultFilters(\n platform: 'android' | 'ios',\n includeContainers: boolean = false,\n): FilterOptions {\n const layoutContainers = platform === 'android' ? ANDROID_LAYOUT_CONTAINERS : IOS_LAYOUT_CONTAINERS;\n\n return {\n excludeTagNames: includeContainers ? ['hierarchy'] : ['hierarchy', ...layoutContainers],\n fetchableOnly: !includeContainers,\n visibleOnly: true,\n clickableOnly: false,\n };\n}\n","/**\n * Locator strategy generation for mobile elements\n */\n\nimport type { JSONElement, LocatorStrategy, LocatorContext, UniquenessResult } from './types';\nimport { checkXPathUniqueness, evaluateXPath, isAttributeUnique } from './xml-parsing';\n\n/**\n * Check if a string value is valid for use in a locator\n */\nfunction isValidValue(value: string | undefined): value is string {\n return value !== undefined && value !== null && value !== 'null' && value.trim() !== '';\n}\n\n/**\n * Escape special characters in text for use in selectors\n */\nfunction escapeText(text: string): string {\n return text.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"').replace(/\\n/g, '\\\\n');\n}\n\n/**\n * Escape value for use in XPath expressions\n */\nfunction escapeXPathValue(value: string): string {\n if (!value.includes(\"'\")) {\n return `'${value}'`;\n }\n if (!value.includes('\"')) {\n return `\"${value}\"`;\n }\n const parts: string[] = [];\n let current = '';\n for (const char of value) {\n if (char === \"'\") {\n if (current) parts.push(`'${current}'`);\n parts.push('\"\\'\"');\n current = '';\n } else {\n current += char;\n }\n }\n if (current) parts.push(`'${current}'`);\n return `concat(${parts.join(',')})`;\n}\n\n/**\n * Wrap non-unique XPath with index\n */\nfunction generateIndexedXPath(baseXPath: string, index: number): string {\n return `(${baseXPath})[${index}]`;\n}\n\n/**\n * Add .instance(n) for UiAutomator (0-based)\n */\nfunction generateIndexedUiAutomator(baseSelector: string, index: number): string {\n return `${baseSelector}.instance(${index - 1})`;\n}\n\n/**\n * Check uniqueness, falling back to regex if no DOM available\n */\nfunction checkUniqueness(\n ctx: LocatorContext,\n xpath: string,\n targetNode?: Node,\n): UniquenessResult {\n if (ctx.parsedDOM) {\n return checkXPathUniqueness(ctx.parsedDOM, xpath, targetNode);\n }\n\n const match = xpath.match(/\\/\\/\\*\\[@([^=]+)=\"([^\"]+)\"\\]/);\n if (match) {\n const [, attr, value] = match;\n return { isUnique: isAttributeUnique(ctx.sourceXML, attr, value) };\n }\n return { isUnique: false };\n}\n\n/**\n * Get sibling index (1-based) among same-tag siblings\n */\nfunction getSiblingIndex(element: Element): number {\n const parent = element.parentNode;\n if (!parent) return 1;\n\n const tagName = element.nodeName;\n let index = 0;\n\n for (let i = 0; i < parent.childNodes.length; i++) {\n const child = parent.childNodes.item(i);\n if (child?.nodeType === 1 && child.nodeName === tagName) {\n index++;\n if (child === element) return index;\n }\n }\n\n return 1;\n}\n\n/**\n * Count siblings with same tag name\n */\nfunction countSiblings(element: Element): number {\n const parent = element.parentNode;\n if (!parent) return 1;\n\n const tagName = element.nodeName;\n let count = 0;\n\n for (let i = 0; i < parent.childNodes.length; i++) {\n const child = parent.childNodes.item(i);\n if (child?.nodeType === 1 && child.nodeName === tagName) {\n count++;\n }\n }\n\n return count;\n}\n\n/**\n * Find unique attribute for element in XPath format\n */\nfunction findUniqueAttribute(element: Element, ctx: LocatorContext): string | null {\n const attrs = ctx.isAndroid\n ? ['resource-id', 'content-desc', 'text']\n : ['name', 'label', 'value'];\n\n for (const attr of attrs) {\n const value = element.getAttribute(attr);\n if (value && value.trim()) {\n const xpath = `//*[@${attr}=${escapeXPathValue(value)}]`;\n const result = ctx.parsedDOM\n ? checkXPathUniqueness(ctx.parsedDOM, xpath)\n : { isUnique: isAttributeUnique(ctx.sourceXML, attr, value) };\n\n if (result.isUnique) {\n return `@${attr}=${escapeXPathValue(value)}`;\n }\n }\n }\n\n return null;\n}\n\n/**\n * Build hierarchical XPath by traversing up the DOM tree\n */\nfunction buildHierarchicalXPath(\n ctx: LocatorContext,\n element: Element,\n maxDepth: number = 3,\n): string | null {\n if (!ctx.parsedDOM) return null;\n\n const pathParts: string[] = [];\n let current: Element | null = element;\n let depth = 0;\n\n while (current && depth < maxDepth) {\n const tagName = current.nodeName;\n const uniqueAttr = findUniqueAttribute(current, ctx);\n\n if (uniqueAttr) {\n pathParts.unshift(`//${tagName}[${uniqueAttr}]`);\n break;\n } else {\n const siblingIndex = getSiblingIndex(current);\n const siblingCount = countSiblings(current);\n\n if (siblingCount > 1) {\n pathParts.unshift(`${tagName}[${siblingIndex}]`);\n } else {\n pathParts.unshift(tagName);\n }\n }\n\n const parent = current.parentNode as Element | null;\n current = parent && parent.nodeType === 1 ? parent : null;\n depth++;\n }\n\n if (pathParts.length === 0) return null;\n\n let result = pathParts[0];\n for (let i = 1; i < pathParts.length; i++) {\n result += '/' + pathParts[i];\n }\n\n if (!result.startsWith('//')) {\n result = '//' + result;\n }\n\n return result;\n}\n\n/**\n * Add XPath locator with uniqueness checking and fallbacks\n */\nfunction addXPathLocator(\n results: [LocatorStrategy, string][],\n xpath: string,\n ctx: LocatorContext,\n targetNode?: Node,\n): void {\n const uniqueness = checkUniqueness(ctx, xpath, targetNode);\n if (uniqueness.isUnique) {\n results.push(['xpath', xpath]);\n } else if (uniqueness.index) {\n results.push(['xpath', generateIndexedXPath(xpath, uniqueness.index)]);\n } else {\n if (targetNode && ctx.parsedDOM) {\n const hierarchical = buildHierarchicalXPath(ctx, targetNode as Element);\n if (hierarchical) {\n results.push(['xpath', hierarchical]);\n }\n }\n results.push(['xpath', xpath]);\n }\n}\n\n/**\n * Check if element is within UiAutomator scope\n */\nfunction isInUiAutomatorScope(element: JSONElement, doc: Document | null): boolean {\n if (!doc) return true;\n\n const hierarchyNodes = evaluateXPath(doc, '/hierarchy/*');\n if (hierarchyNodes.length === 0) return true;\n\n const lastIndex = hierarchyNodes.length;\n const pathParts = element.path.split('.');\n if (pathParts.length === 0 || pathParts[0] === '') return true;\n\n const firstIndex = parseInt(pathParts[0], 10);\n return firstIndex === lastIndex - 1;\n}\n\n/**\n * Build Android UiAutomator selector with multiple attributes\n */\nfunction buildUiAutomatorSelector(element: JSONElement): string | null {\n const attrs = element.attributes;\n const parts: string[] = [];\n\n if (isValidValue(attrs['resource-id'])) {\n parts.push(`resourceId(\"${attrs['resource-id']}\")`);\n }\n if (isValidValue(attrs.text) && attrs.text!.length < 100) {\n parts.push(`text(\"${escapeText(attrs.text!)}\")`);\n }\n if (isValidValue(attrs['content-desc'])) {\n parts.push(`description(\"${attrs['content-desc']}\")`);\n }\n if (isValidValue(attrs.class)) {\n parts.push(`className(\"${attrs.class}\")`);\n }\n\n if (parts.length === 0) return null;\n\n return `android=new UiSelector().${parts.join('.')}`;\n}\n\n/**\n * Build iOS predicate string with multiple conditions\n */\nfunction buildPredicateString(element: JSONElement): string | null {\n const attrs = element.attributes;\n const conditions: string[] = [];\n\n if (isValidValue(attrs.name)) {\n conditions.push(`name == \"${escapeText(attrs.name!)}\"`);\n }\n if (isValidValue(attrs.label)) {\n conditions.push(`label == \"${escapeText(attrs.label!)}\"`);\n }\n if (isValidValue(attrs.value)) {\n conditions.push(`value == \"${escapeText(attrs.value!)}\"`);\n }\n if (attrs.visible === 'true') {\n conditions.push('visible == 1');\n }\n if (attrs.enabled === 'true') {\n conditions.push('enabled == 1');\n }\n\n if (conditions.length === 0) return null;\n\n return `-ios predicate string:${conditions.join(' AND ')}`;\n}\n\n/**\n * Build iOS class chain selector\n */\nfunction buildClassChain(element: JSONElement): string | null {\n const attrs = element.attributes;\n const tagName = element.tagName;\n\n if (!tagName.startsWith('XCUI')) return null;\n\n let selector = `**/${tagName}`;\n\n if (isValidValue(attrs.label)) {\n selector += `[\\`label == \"${escapeText(attrs.label!)}\"\\`]`;\n } else if (isValidValue(attrs.name)) {\n selector += `[\\`name == \"${escapeText(attrs.name!)}\"\\`]`;\n }\n\n return `-ios class chain:${selector}`;\n}\n\n/**\n * Build XPath for element with unique identification\n */\nfunction buildXPath(element: JSONElement, sourceXML: string, isAndroid: boolean): string | null {\n const attrs = element.attributes;\n const tagName = element.tagName;\n const conditions: string[] = [];\n\n if (isAndroid) {\n if (isValidValue(attrs['resource-id'])) {\n conditions.push(`@resource-id=\"${attrs['resource-id']}\"`);\n }\n if (isValidValue(attrs['content-desc'])) {\n conditions.push(`@content-desc=\"${attrs['content-desc']}\"`);\n }\n if (isValidValue(attrs.text) && attrs.text!.length < 100) {\n conditions.push(`@text=\"${escapeText(attrs.text!)}\"`);\n }\n } else {\n if (isValidValue(attrs.name)) {\n conditions.push(`@name=\"${attrs.name}\"`);\n }\n if (isValidValue(attrs.label)) {\n conditions.push(`@label=\"${attrs.label}\"`);\n }\n if (isValidValue(attrs.value)) {\n conditions.push(`@value=\"${attrs.value}\"`);\n }\n }\n\n if (conditions.length === 0) {\n return `//${tagName}`;\n }\n\n return `//${tagName}[${conditions.join(' and ')}]`;\n}\n\n/**\n * Get simple locators based on single attributes\n */\nfunction getSimpleSuggestedLocators(\n element: JSONElement,\n ctx: LocatorContext,\n automationName: string,\n targetNode?: Node,\n): [LocatorStrategy, string][] {\n const results: [LocatorStrategy, string][] = [];\n const isAndroid = automationName.toLowerCase().includes('uiautomator');\n const attrs = element.attributes;\n const inUiAutomatorScope = isAndroid ? isInUiAutomatorScope(element, ctx.parsedDOM) : true;\n\n if (isAndroid) {\n // Resource ID\n const resourceId = attrs['resource-id'];\n if (isValidValue(resourceId)) {\n const xpath = `//*[@resource-id=\"${resourceId}\"]`;\n const uniqueness = checkUniqueness(ctx, xpath, targetNode);\n\n if (uniqueness.isUnique && inUiAutomatorScope) {\n results.push(['id', `android=new UiSelector().resourceId(\"${resourceId}\")`]);\n } else if (uniqueness.index && inUiAutomatorScope) {\n const base = `android=new UiSelector().resourceId(\"${resourceId}\")`;\n results.push(['id', generateIndexedUiAutomator(base, uniqueness.index)]);\n }\n }\n\n // Content Description\n const contentDesc = attrs['content-desc'];\n if (isValidValue(contentDesc)) {\n const xpath = `//*[@content-desc=\"${contentDesc}\"]`;\n const uniqueness = checkUniqueness(ctx, xpath, targetNode);\n\n if (uniqueness.isUnique) {\n results.push(['accessibility-id', `~${contentDesc}`]);\n }\n }\n\n // Text\n const text = attrs.text;\n if (isValidValue(text) && text.length < 100) {\n const xpath = `//*[@text=\"${escapeText(text)}\"]`;\n const uniqueness = checkUniqueness(ctx, xpath, targetNode);\n\n if (uniqueness.isUnique && inUiAutomatorScope) {\n results.push(['text', `android=new UiSelector().text(\"${escapeText(text)}\")`]);\n } else if (uniqueness.index && inUiAutomatorScope) {\n const base = `android=new UiSelector().text(\"${escapeText(text)}\")`;\n results.push(['text', generateIndexedUiAutomator(base, uniqueness.index)]);\n }\n }\n } else {\n // iOS: Accessibility ID (name)\n const name = attrs.name;\n if (isValidValue(name)) {\n const xpath = `//*[@name=\"${name}\"]`;\n const uniqueness = checkUniqueness(ctx, xpath, targetNode);\n\n if (uniqueness.isUnique) {\n results.push(['accessibility-id', `~${name}`]);\n }\n }\n\n // iOS: Label\n const label = attrs.label;\n if (isValidValue(label) && label !== attrs.name) {\n const xpath = `//*[@label=\"${escapeText(label)}\"]`;\n const uniqueness = checkUniqueness(ctx, xpath, targetNode);\n\n if (uniqueness.isUnique) {\n results.push(['predicate-string', `-ios predicate string:label == \"${escapeText(label)}\"`]);\n }\n }\n\n // iOS: Value\n const value = attrs.value;\n if (isValidValue(value)) {\n const xpath = `//*[@value=\"${escapeText(value)}\"]`;\n const uniqueness = checkUniqueness(ctx, xpath, targetNode);\n\n if (uniqueness.isUnique) {\n results.push(['predicate-string', `-ios predicate string:value == \"${escapeText(value)}\"`]);\n }\n }\n }\n\n return results;\n}\n\n/**\n * Get complex locators (combinations, XPath, etc.)\n */\nfunction getComplexSuggestedLocators(\n element: JSONElement,\n ctx: LocatorContext,\n automationName: string,\n targetNode?: Node,\n): [LocatorStrategy, string][] {\n const results: [LocatorStrategy, string][] = [];\n const isAndroid = automationName.toLowerCase().includes('uiautomator');\n const inUiAutomatorScope = isAndroid ? isInUiAutomatorScope(element, ctx.parsedDOM) : true;\n\n if (isAndroid) {\n if (inUiAutomatorScope) {\n const uiAutomator = buildUiAutomatorSelector(element);\n if (uiAutomator) {\n results.push(['uiautomator', uiAutomator]);\n }\n }\n\n const xpath = buildXPath(element, ctx.sourceXML, true);\n if (xpath) {\n addXPathLocator(results, xpath, ctx, targetNode);\n }\n\n if (inUiAutomatorScope && isValidValue(element.attributes.class)) {\n results.push([\n 'class-name',\n `android=new UiSelector().className(\"${element.attributes.class}\")`,\n ]);\n }\n } else {\n const predicate = buildPredicateString(element);\n if (predicate) {\n results.push(['predicate-string', predicate]);\n }\n\n const classChain = buildClassChain(element);\n if (classChain) {\n results.push(['class-chain', classChain]);\n }\n\n const xpath = buildXPath(element, ctx.sourceXML, false);\n if (xpath) {\n addXPathLocator(results, xpath, ctx, targetNode);\n }\n\n const type = element.tagName;\n if (type.startsWith('XCUIElementType')) {\n results.push(['class-name', `-ios class chain:**/${type}`]);\n }\n }\n\n return results;\n}\n\n/**\n * Get all suggested locators for an element\n */\nexport function getSuggestedLocators(\n element: JSONElement,\n sourceXML: string,\n automationName: string,\n ctx?: LocatorContext,\n targetNode?: Node,\n): [LocatorStrategy, string][] {\n const locatorCtx = ctx ?? {\n sourceXML,\n parsedDOM: null,\n isAndroid: automationName.toLowerCase().includes('uiautomator'),\n };\n\n const simpleLocators = getSimpleSuggestedLocators(element, locatorCtx, automationName, targetNode);\n const complexLocators = getComplexSuggestedLocators(element, locatorCtx, automationName, targetNode);\n\n const seen = new Set<string>();\n const results: [LocatorStrategy, string][] = [];\n\n for (const locator of [...simpleLocators, ...complexLocators]) {\n if (!seen.has(locator[1])) {\n seen.add(locator[1]);\n results.push(locator);\n }\n }\n\n return results;\n}\n\n/**\n * Get the best (first priority) locator for an element\n */\nexport function getBestLocator(\n element: JSONElement,\n sourceXML: string,\n automationName: string,\n): string | null {\n const locators = getSuggestedLocators(element, sourceXML, automationName);\n return locators.length > 0 ? locators[0][1] : null;\n}\n\n/**\n * Convert locator array to object format\n */\nexport function locatorsToObject(locators: [LocatorStrategy, string][]): Record<string, string> {\n const result: Record<string, string> = {};\n for (const [strategy, value] of locators) {\n if (!result[strategy]) {\n result[strategy] = value;\n }\n }\n return result;\n}\n","/**\n * Mobile element locator generation\n *\n * Main orchestrator module that coordinates XML parsing, element filtering,\n * and locator generation for mobile automation.\n *\n * Based on: https://github.com/appium/appium-mcp\n */\n\n// Types\nexport type {\n ElementAttributes,\n JSONElement,\n Bounds,\n FilterOptions,\n UniquenessResult,\n LocatorStrategy,\n LocatorContext,\n ElementWithLocators,\n GenerateLocatorsOptions,\n} from './types';\n\n// Constants\nexport {\n ANDROID_INTERACTABLE_TAGS,\n IOS_INTERACTABLE_TAGS,\n ANDROID_LAYOUT_CONTAINERS,\n IOS_LAYOUT_CONTAINERS,\n} from './constants';\n\n// XML Parsing\nexport {\n xmlToJSON,\n xmlToDOM,\n evaluateXPath,\n checkXPathUniqueness,\n findDOMNodeByPath,\n parseAndroidBounds,\n parseIOSBounds,\n flattenElementTree,\n countAttributeOccurrences,\n isAttributeUnique,\n} from './xml-parsing';\n\n// Element Filtering\nexport {\n isInteractableElement,\n isLayoutContainer,\n hasMeaningfulContent,\n shouldIncludeElement,\n getDefaultFilters,\n} from './element-filter';\n\n// Locator Generation\nexport {\n getSuggestedLocators,\n getBestLocator,\n locatorsToObject,\n} from './locator-generation';\n\nimport type {\n JSONElement,\n FilterOptions,\n LocatorStrategy,\n ElementWithLocators,\n GenerateLocatorsOptions,\n} from './types';\n\nimport { xmlToJSON, xmlToDOM, parseAndroidBounds, parseIOSBounds, findDOMNodeByPath } from './xml-parsing';\nimport { shouldIncludeElement, isLayoutContainer, hasMeaningfulContent } from './element-filter';\nimport { getSuggestedLocators, locatorsToObject } from './locator-generation';\n\ninterface ProcessingContext {\n sourceXML: string;\n platform: 'android' | 'ios';\n automationName: string;\n isNative: boolean;\n viewportSize: { width: number; height: number };\n filters: FilterOptions;\n results: ElementWithLocators[];\n parsedDOM: Document | null;\n}\n\n/**\n * Parse element bounds based on platform\n */\nfunction parseBounds(\n element: JSONElement,\n platform: 'android' | 'ios',\n): { x: number; y: number; width: number; height: number } {\n return platform === 'android'\n ? parseAndroidBounds(element.attributes.bounds || '')\n : parseIOSBounds(element.attributes);\n}\n\n/**\n * Check if bounds are within viewport\n */\nfunction isWithinViewport(\n bounds: { x: number; y: number; width: number; height: number },\n viewport: { width: number; height: number },\n): boolean {\n return (\n bounds.x >= 0 &&\n bounds.y >= 0 &&\n bounds.width > 0 &&\n bounds.height > 0 &&\n bounds.x + bounds.width <= viewport.width &&\n bounds.y + bounds.height <= viewport.height\n );\n}\n\n/**\n * Transform JSONElement to ElementWithLocators\n */\nfunction transformElement(\n element: JSONElement,\n locators: [LocatorStrategy, string][],\n ctx: ProcessingContext,\n): ElementWithLocators {\n const attrs = element.attributes;\n const bounds = parseBounds(element, ctx.platform);\n\n return {\n tagName: element.tagName,\n locators: locatorsToObject(locators),\n text: attrs.text || attrs.label || '',\n contentDesc: attrs['content-desc'] || '',\n resourceId: attrs['resource-id'] || '',\n accessibilityId: attrs.name || attrs['content-desc'] || '',\n label: attrs.label || '',\n value: attrs.value || '',\n className: attrs.class || element.tagName,\n clickable: attrs.clickable === 'true' || attrs.accessible === 'true' || attrs['long-clickable'] === 'true',\n enabled: attrs.enabled !== 'false',\n displayed: ctx.platform === 'android' ? attrs.displayed !== 'false' : attrs.visible !== 'false',\n bounds,\n isInViewport: isWithinViewport(bounds, ctx.viewportSize),\n };\n}\n\n/**\n * Check if element should be processed\n */\nfunction shouldProcess(element: JSONElement, ctx: ProcessingContext): boolean {\n if (shouldIncludeElement(element, ctx.filters, ctx.isNative, ctx.automationName)) {\n return true;\n }\n return isLayoutContainer(element, ctx.platform) && hasMeaningfulContent(element, ctx.platform);\n}\n\n/**\n * Process a single element and add to results if valid\n */\nfunction processElement(element: JSONElement, ctx: ProcessingContext): void {\n if (!shouldProcess(element, ctx)) return;\n\n try {\n const targetNode = ctx.parsedDOM ? findDOMNodeByPath(ctx.parsedDOM, element.path) : undefined;\n\n const locators = getSuggestedLocators(\n element,\n ctx.sourceXML,\n ctx.automationName,\n { sourceXML: ctx.sourceXML, parsedDOM: ctx.parsedDOM, isAndroid: ctx.platform === 'android' },\n targetNode || undefined,\n );\n if (locators.length === 0) return;\n\n const transformed = transformElement(element, locators, ctx);\n if (Object.keys(transformed.locators).length === 0) return;\n\n ctx.results.push(transformed);\n } catch (error) {\n console.error(`[processElement] Error at path ${element.path}:`, error);\n }\n}\n\n/**\n * Recursively traverse and process element tree\n */\nfunction traverseTree(element: JSONElement | null, ctx: ProcessingContext): void {\n if (!element) return;\n\n processElement(element, ctx);\n\n for (const child of element.children || []) {\n traverseTree(child, ctx);\n }\n}\n\n/**\n * Generate locators for all elements from page source XML\n */\nexport function generateAllElementLocators(\n sourceXML: string,\n options: GenerateLocatorsOptions,\n): ElementWithLocators[] {\n const sourceJSON = xmlToJSON(sourceXML);\n\n if (!sourceJSON) {\n console.error('[generateAllElementLocators] Failed to parse page source XML');\n return [];\n }\n\n const parsedDOM = xmlToDOM(sourceXML);\n\n const ctx: ProcessingContext = {\n sourceXML,\n platform: options.platform,\n automationName: options.platform === 'android' ? 'uiautomator2' : 'xcuitest',\n isNative: options.isNative ?? true,\n viewportSize: options.viewportSize ?? { width: 9999, height: 9999 },\n filters: options.filters ?? {},\n results: [],\n parsedDOM,\n };\n\n traverseTree(sourceJSON, ctx);\n\n return ctx.results;\n}\n","/**\n * Mobile element detection utilities for iOS and Android\n *\n * Uses page source parsing for optimal performance (2 HTTP calls vs 600+ for 50 elements)\n */\n\nimport type { ElementWithLocators, FilterOptions, LocatorStrategy } from '../locators';\nimport { generateAllElementLocators, getDefaultFilters } from '../locators';\n\n/**\n * Element info returned by getMobileVisibleElements\n * Uses uniform fields (all elements have same keys) to enable TOON tabular format\n */\nexport interface MobileElementInfo {\n selector: string;\n tagName: string;\n isInViewport: boolean;\n text: string;\n resourceId: string;\n accessibilityId: string;\n isEnabled: boolean;\n altSelector: string; // Single alternative selector (flattened for tabular format)\n // Only present when includeBounds=true\n bounds?: { x: number; y: number; width: number; height: number };\n}\n\n/**\n * Options for getMobileVisibleElements\n */\nexport interface GetMobileElementsOptions {\n includeContainers?: boolean;\n includeBounds?: boolean;\n filterOptions?: FilterOptions;\n}\n\n/**\n * Locator strategy priority order for selecting best selector\n * Earlier = higher priority\n */\nconst LOCATOR_PRIORITY: LocatorStrategy[] = [\n 'accessibility-id', // Most stable, cross-platform\n 'id', // Android resource-id\n 'text', // Text-based (can be fragile but readable)\n 'predicate-string', // iOS predicate\n 'class-chain', // iOS class chain\n 'uiautomator', // Android UiAutomator compound\n 'xpath', // XPath (last resort, brittle)\n // 'class-name' intentionally excluded - too generic\n];\n\n/**\n * Select best locators from available strategies\n * Returns [primarySelector, ...alternativeSelectors]\n */\nfunction selectBestLocators(locators: Record<string, string>): string[] {\n const selected: string[] = [];\n\n // Find primary selector based on priority\n for (const strategy of LOCATOR_PRIORITY) {\n if (locators[strategy]) {\n selected.push(locators[strategy]);\n break;\n }\n }\n\n // Add one alternative if available (different strategy)\n for (const strategy of LOCATOR_PRIORITY) {\n if (locators[strategy] && !selected.includes(locators[strategy])) {\n selected.push(locators[strategy]);\n break;\n }\n }\n\n return selected;\n}\n\n/**\n * Convert ElementWithLocators to MobileElementInfo\n * Uses uniform fields (all elements have same keys) to enable CSV tabular format\n */\nfunction toMobileElementInfo(element: ElementWithLocators, includeBounds: boolean): MobileElementInfo {\n const selectedLocators = selectBestLocators(element.locators);\n\n // Use contentDesc for accessibilityId on Android, or name on iOS\n const accessId = element.accessibilityId || element.contentDesc;\n\n // Build object with ALL fields for uniform schema (enables CSV tabular format)\n // Empty string '' used for missing values to keep schema consistent\n const info: MobileElementInfo = {\n selector: selectedLocators[0] || '',\n tagName: element.tagName,\n isInViewport: element.isInViewport,\n text: element.text || '',\n resourceId: element.resourceId || '',\n accessibilityId: accessId || '',\n isEnabled: element.enabled !== false,\n altSelector: selectedLocators[1] || '', // Single alternative (flattened for tabular)\n };\n\n // Only include bounds if explicitly requested (adds 4 extra columns)\n if (includeBounds) {\n info.bounds = element.bounds;\n }\n\n return info;\n}\n\n/**\n * Get viewport size from browser\n */\nasync function getViewportSize(browser: WebdriverIO.Browser): Promise<{ width: number; height: number }> {\n try {\n const size = await browser.getWindowSize();\n return { width: size.width, height: size.height };\n } catch {\n return { width: 9999, height: 9999 };\n }\n}\n\n/**\n * Get all visible elements from a mobile app\n *\n * Performance: 2 HTTP calls (getWindowSize + getPageSource) vs 12+ per element with legacy approach\n */\nexport async function getMobileVisibleElements(\n browser: WebdriverIO.Browser,\n platform: 'ios' | 'android',\n options: GetMobileElementsOptions = {},\n): Promise<MobileElementInfo[]> {\n const { includeContainers = false, includeBounds = false, filterOptions } = options;\n\n const viewportSize = await getViewportSize(browser);\n const pageSource = await browser.getPageSource();\n\n const filters: FilterOptions = {\n ...getDefaultFilters(platform, includeContainers),\n ...filterOptions,\n };\n\n const elements = generateAllElementLocators(pageSource, {\n platform,\n viewportSize,\n filters,\n });\n\n return elements.map((el) => toMobileElementInfo(el, includeBounds));\n}\n","import { getInteractableBrowserElements } from './get-interactable-browser-elements';\nimport { getMobileVisibleElements } from './get-visible-mobile-elements';\n\nexport type VisibleElementsResult = {\n total: number;\n showing: number;\n hasMore: boolean;\n elements: unknown[];\n};\n\nexport async function getElements(\n browser: WebdriverIO.Browser,\n params: {\n inViewportOnly?: boolean;\n includeContainers?: boolean;\n includeBounds?: boolean;\n limit?: number;\n offset?: number;\n },\n): Promise<VisibleElementsResult> {\n const {\n inViewportOnly = true,\n includeContainers = false,\n includeBounds = false,\n limit = 0,\n offset = 0,\n } = params;\n\n let elements: { isInViewport?: boolean }[];\n\n if (browser.isAndroid || browser.isIOS) {\n const platform = browser.isAndroid ? 'android' : 'ios';\n elements = await getMobileVisibleElements(browser, platform, { includeContainers, includeBounds });\n } else {\n elements = await getInteractableBrowserElements(browser, { includeBounds });\n }\n\n if (inViewportOnly) {\n elements = elements.filter((el) => el.isInViewport !== false);\n }\n\n const total = elements.length;\n\n if (offset > 0) {\n elements = elements.slice(offset);\n }\n if (limit > 0) {\n elements = elements.slice(0, limit);\n }\n\n return {\n total,\n showing: elements.length,\n hasMore: offset + elements.length < total,\n elements,\n };\n}\n","import { spawn } from 'node:child_process';\nimport { copyFileSync, cpSync, existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';\nimport { homedir, platform, tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ToolDefinition } from '../types/tool';\nimport { z } from 'zod';\nimport { coerceBoolean } from '../utils/zod-helpers';\n\nconst USER_DATA_DIR = join(tmpdir(), 'chrome-debug');\n\nexport const launchChromeToolDefinition: ToolDefinition = {\n name: 'launch_chrome',\n description: `Prepares and launches Chrome with remote debugging enabled so attach_browser() can connect.\n\nTwo modes:\n\n newInstance (default): Opens a Chrome window alongside your existing one using a separate\n profile dir. Your current Chrome session is untouched.\n\n freshSession: Launches Chrome with an empty profile (no cookies, no logins).\n\nUse copyProfileFiles: true to carry over your cookies and logins into the debug session.\nNote: changes made during the session won't sync back to your main profile.\n\nAfter this tool succeeds, call attach_browser() to connect.`,\n inputSchema: {\n port: z.number().default(9222).describe('Remote debugging port (default: 9222)'),\n mode: z.enum(['newInstance', 'freshSession']).default('newInstance').describe(\n 'newInstance: open alongside existing Chrome | freshSession: clean profile'\n ),\n copyProfileFiles: coerceBoolean.default(false).describe(\n 'Copy your Default Chrome profile (cookies, logins) into the debug session.'\n ),\n },\n};\n\nfunction isMac(): boolean {\n return platform() === 'darwin';\n}\n\nfunction chromeExec(): string {\n if (isMac()) return '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome';\n if (platform() === 'win32') {\n const candidates = [\n join('C:', 'Program Files', 'Google', 'Chrome', 'Application', 'chrome.exe'),\n join('C:', 'Program Files (x86)', 'Google', 'Chrome', 'Application', 'chrome.exe'),\n ];\n return candidates.find((p) => existsSync(p)) ?? candidates[0];\n }\n return 'google-chrome';\n}\n\nfunction defaultProfileDir(): string {\n const home = homedir();\n if (isMac()) return join(home, 'Library', 'Application Support', 'Google', 'Chrome');\n if (platform() === 'win32') return join(home, 'AppData', 'Local', 'Google', 'Chrome', 'User Data');\n return join(home, '.config', 'google-chrome');\n}\n\nfunction copyProfile(): void {\n const srcDir = defaultProfileDir();\n rmSync(USER_DATA_DIR, { recursive: true, force: true });\n mkdirSync(USER_DATA_DIR, { recursive: true });\n copyFileSync(join(srcDir, 'Local State'), join(USER_DATA_DIR, 'Local State'));\n cpSync(join(srcDir, 'Default'), join(USER_DATA_DIR, 'Default'), { recursive: true });\n\n // Remove singleton/lock files from the source Chrome instance.\n for (const f of ['SingletonLock', 'SingletonCookie', 'SingletonSocket']) {\n rmSync(join(USER_DATA_DIR, f), { force: true });\n }\n\n // Remove session files — they reference the original profile's state and trigger\n // \"Something went wrong when opening your profile\" when Chrome opens the copy.\n for (const f of ['Current Session', 'Current Tabs', 'Last Session', 'Last Tabs']) {\n rmSync(join(USER_DATA_DIR, 'Default', f), { force: true });\n }\n\n // First Run sentinel tells Chrome this is a fresh start — suppresses first-run dialogs.\n writeFileSync(join(USER_DATA_DIR, 'First Run'), '');\n}\n\nfunction launchChrome(port: number): void {\n spawn(chromeExec(), [\n `--remote-debugging-port=${port}`,\n `--user-data-dir=${USER_DATA_DIR}`,\n '--profile-directory=Default',\n '--no-first-run',\n '--disable-session-crashed-bubble',\n ], { detached: true, stdio: 'ignore' }).unref();\n}\n\nasync function waitForCDP(port: number, timeoutMs = 15000): Promise<void> {\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n try {\n const res = await fetch(`http://localhost:${port}/json/version`);\n if (res.ok) return;\n } catch {\n // not ready yet\n }\n await new Promise((r) => setTimeout(r, 300));\n }\n throw new Error(`Chrome did not expose CDP on port ${port} within ${timeoutMs}ms`);\n}\n\nexport const launchChromeTool: ToolCallback = async ({\n port = 9222,\n mode = 'newInstance',\n copyProfileFiles = false,\n}: {\n port?: number;\n mode?: 'newInstance' | 'freshSession';\n copyProfileFiles?: boolean;\n}): Promise<CallToolResult> => {\n const warnings: string[] = [];\n const notes: string[] = [];\n\n try {\n if (copyProfileFiles) {\n warnings.push('⚠️ Cookies and logins were copied at this moment. Changes during this session won\\'t sync back to your main profile.');\n copyProfile();\n } else {\n notes.push(mode === 'newInstance'\n ? 'No profile copied — this instance starts with no cookies or logins.'\n : 'Fresh profile — no existing cookies or logins.');\n rmSync(USER_DATA_DIR, { recursive: true, force: true });\n mkdirSync(USER_DATA_DIR, { recursive: true });\n }\n\n launchChrome(port);\n await waitForCDP(port);\n\n const lines = [\n `Chrome launched on port ${port} (mode: ${mode}).`,\n ...warnings,\n ...notes,\n ];\n\n return { content: [{ type: 'text', text: lines.join('\\n') }] };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error launching Chrome: ${e}` }],\n };\n }\n};","import type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ToolDefinition } from '../types/tool';\n// DeviceName is not in webdriverio's public exports but is required to satisfy browser.emulate('device', ...) overloads.\n// This is a type-only import — it is stripped at build time by tsup and has no runtime impact.\nimport type { DeviceName } from 'webdriverio/build/deviceDescriptorsSource.js';\nimport { z } from 'zod';\nimport { getBrowser, getState } from '../session/state';\n\n// Stores restore functions returned by browser.emulate(), keyed by sessionId\nconst restoreFunctions = new Map<string, () => Promise<void>>();\n\nexport const emulateDeviceToolDefinition: ToolDefinition = {\n name: 'emulate_device',\n description: `Emulate a mobile or tablet device in the current browser session (sets viewport, DPR, user-agent, touch events).\n\nRequires a BiDi-enabled session: start_browser({ capabilities: { webSocketUrl: true } })\n\nUsage:\n emulate_device() — list available device presets\n emulate_device({ device: \"iPhone 15\" }) — activate emulation\n emulate_device({ device: \"reset\" }) — restore desktop defaults`,\n inputSchema: {\n device: z.string().optional().describe(\n 'Device preset name (e.g. \"iPhone 15\", \"Pixel 7\"). Omit to list available presets. Pass \"reset\" to restore desktop defaults.'\n ),\n },\n};\n\nexport const emulateDeviceTool: ToolCallback = async ({\n device,\n}: {\n device?: string;\n}): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n const state = getState();\n const sessionId = state.currentSession;\n const metadata = state.sessionMetadata.get(sessionId);\n\n // Guard: mobile sessions\n if (metadata?.type === 'ios' || metadata?.type === 'android') {\n return {\n isError: true,\n content: [{\n type: 'text',\n text: 'Error: emulate_device is only supported for web browser sessions, not iOS/Android.'\n }],\n };\n }\n\n // Guard: BiDi required\n if (!browser.isBidi) {\n return {\n isError: true,\n content: [{\n type: 'text',\n text: 'Error: emulate_device requires a BiDi-enabled session.\\nRestart the browser with: start_browser({ capabilities: { webSocketUrl: true } })',\n }],\n };\n }\n\n // List presets by triggering a known-bad device name and parsing the error\n if (!device) {\n try {\n await browser.emulate('device', '\\u0000' as DeviceName);\n } catch (e) {\n const msg = String(e);\n const match = msg.match(/please use one of the following: (.+)$/);\n if (match) {\n const names = match[1].split(', ').sort();\n return {\n content: [{ type: 'text', text: `Available devices (${names.length}):\\n${names.join('\\n')}` }],\n };\n }\n return { isError: true, content: [{ type: 'text', text: `Error listing devices: ${e}` }] };\n }\n return { content: [{ type: 'text', text: 'Could not retrieve device list.' }] };\n }\n\n // Reset\n if (device === 'reset') {\n const restoreFn = restoreFunctions.get(sessionId);\n if (!restoreFn) {\n return { content: [{ type: 'text', text: 'No active device emulation to reset.' }] };\n }\n await restoreFn();\n restoreFunctions.delete(sessionId);\n return { content: [{ type: 'text', text: 'Device emulation reset to desktop defaults.' }] };\n }\n\n // Emulate device\n try {\n const restoreFn = await browser.emulate('device', device as DeviceName);\n restoreFunctions.set(sessionId, restoreFn as () => Promise<void>);\n return {\n content: [{ type: 'text', text: `Emulating \"${device}\".` }],\n };\n } catch (e) {\n const msg = String(e);\n if (msg.includes('Unknown device name')) {\n return {\n content: [{\n type: 'text',\n text: `Error: Unknown device \"${device}\". Call emulate_device() with no arguments to list valid names.`,\n }],\n };\n }\n return { isError: true, content: [{ type: 'text', text: `Error: ${e}` }] };\n }\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error: ${e}` }],\n };\n }\n};\n","// src/recording/step-recorder.ts\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { RecordedStep, SessionHistory } from '../types/recording';\nimport { getState } from '../session/state';\n\nexport function appendStep(\n toolName: string,\n params: Record<string, unknown>,\n status: 'ok' | 'error',\n durationMs: number,\n error?: string,\n): void {\n const state = getState();\n const sessionId = state.currentSession;\n if (!sessionId) return;\n\n const history = state.sessionHistory.get(sessionId);\n if (!history) return;\n\n const step: RecordedStep = {\n index: history.steps.length + 1,\n tool: toolName,\n params,\n status,\n durationMs,\n timestamp: new Date().toISOString(),\n ...(error !== undefined && { error }),\n };\n history.steps.push(step);\n}\n\nexport function getSessionHistory(): Map<string, SessionHistory> {\n return getState().sessionHistory;\n}\n\nfunction extractErrorText(result: Awaited<ReturnType<ToolCallback>>): string {\n const textContent = result.content.find((c: any) => c.type === 'text');\n return textContent ? (textContent as any).text : 'Unknown error';\n}\n\nexport function withRecording(toolName: string, callback: ToolCallback): ToolCallback {\n return async (params, extra) => {\n const start = Date.now();\n const result = await callback(params, extra);\n const isError = (result as any).isError === true;\n appendStep(\n toolName,\n params as Record<string, unknown>,\n isError ? 'error' : 'ok',\n Date.now() - start,\n isError ? extractErrorText(result) : undefined,\n );\n return result;\n };\n}\n","import type { ResourceDefinition } from '../types/resource';\n\nfunction getLocalBinaryInfo(): {\n downloadUrl: string;\n platform: string;\n arch: string;\n binaryName: string;\n note?: string;\n} {\n const platform = process.platform;\n const arch = process.arch;\n\n if (platform === 'darwin') {\n return {\n downloadUrl: 'https://local-downloads.browserstack.com/BrowserStackLocal-darwin-x64.zip',\n platform: 'macOS',\n arch: arch === 'arm64' ? 'Apple Silicon (via Rosetta 2)' : 'Intel x64',\n binaryName: 'BrowserStackLocal',\n note: arch === 'arm64' ? 'macOS binary is Intel-only. Rosetta 2 must be installed (it is on most Apple Silicon Macs by default).' : undefined,\n };\n }\n\n if (platform === 'win32') {\n return {\n downloadUrl: 'https://local-downloads.browserstack.com/BrowserStackLocal-win32.zip',\n platform: 'Windows',\n arch: 'x86/x64',\n binaryName: 'BrowserStackLocal.exe',\n };\n }\n\n // Linux\n if (arch === 'arm64') {\n return {\n downloadUrl: 'https://local-downloads.browserstack.com/BrowserStackLocal-linux-arm64.zip',\n platform: 'Linux',\n arch: 'ARM64',\n binaryName: 'BrowserStackLocal',\n };\n }\n\n if (arch === 'ia32') {\n return {\n downloadUrl: 'https://local-downloads.browserstack.com/BrowserStackLocal-linux-ia32.zip',\n platform: 'Linux',\n arch: 'x86 32-bit',\n binaryName: 'BrowserStackLocal',\n };\n }\n\n return {\n downloadUrl: 'https://local-downloads.browserstack.com/BrowserStackLocal-linux-x64.zip',\n platform: 'Linux',\n arch: 'x64',\n binaryName: 'BrowserStackLocal',\n };\n}\n\nexport const browserstackLocalBinaryResource: ResourceDefinition = {\n name: 'browserstack-local-binary',\n uri: 'wdio://browserstack/local-binary',\n description: 'BrowserStack Local binary download URL and daemon setup instructions for the current platform. MUST be read and followed before using browserstackLocal: true in start_session.',\n handler: async () => {\n const info = getLocalBinaryInfo();\n const accessKey = process.env.BROWSERSTACK_ACCESS_KEY ?? '<BROWSERSTACK_ACCESS_KEY>';\n\n const content = {\n requirement: 'MUST start the BrowserStack Local daemon BEFORE calling start_session with browserstackLocal: true. Without it, all navigation to local/internal URLs will fail with ERR_TUNNEL_CONNECTION_FAILED.',\n platform: info.platform,\n arch: info.arch,\n downloadUrl: info.downloadUrl,\n ...(info.note ? { note: info.note } : {}),\n setup: [\n `1. Download: curl -O ${info.downloadUrl}`,\n `2. Unzip: unzip ${info.downloadUrl.split('/').pop()}`,\n `3. Make executable (macOS/Linux): chmod +x ${info.binaryName}`,\n `4. Start daemon: ./${info.binaryName} --key ${accessKey} --force-local --daemon start`,\n ],\n commands: {\n start: `./${info.binaryName} --key ${accessKey} --force-local --daemon start`,\n stop: `./${info.binaryName} --key ${accessKey} --daemon stop`,\n status: `./${info.binaryName} --daemon list`,\n },\n afterDaemonIsRunning: 'Call start_session with browserstackLocal: true to route BrowserStack traffic through the tunnel.',\n };\n\n return {\n contents: [{\n uri: 'wdio://browserstack/local-binary',\n mimeType: 'application/json',\n text: JSON.stringify(content, null, 2),\n }],\n };\n },\n};","import type { ResourceDefinition } from '../types/resource';\nimport { ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { SessionHistory } from '../types/recording';\nimport { generateCode } from '../recording/code-generator';\nimport { getSessionHistory } from '../recording/step-recorder';\nimport { getState } from '../session/state';\n\nfunction getCurrentSessionId(): string | null {\n return getState().currentSession;\n}\n\nexport interface SessionStepsPayload {\n stepsJson: string;\n generatedJs: string;\n}\n\nexport function buildSessionsIndex(): string {\n const histories = getSessionHistory();\n const currentId = getCurrentSessionId();\n const sessions = Array.from(histories.values()).map((h) => ({\n sessionId: h.sessionId,\n type: h.type,\n startedAt: h.startedAt,\n ...(h.endedAt ? { endedAt: h.endedAt } : {}),\n stepCount: h.steps.length,\n isCurrent: h.sessionId === currentId,\n }));\n return JSON.stringify({ sessions });\n}\n\nexport function buildCurrentSessionSteps(): SessionStepsPayload | null {\n const currentId = getCurrentSessionId();\n if (!currentId) return null;\n\n return buildSessionStepsById(currentId);\n}\n\nexport function buildSessionStepsById(sessionId: string): SessionStepsPayload | null {\n const history = getSessionHistory().get(sessionId);\n if (!history) return null;\n\n return buildSessionPayload(history);\n}\n\nfunction buildSessionPayload(history: SessionHistory): SessionStepsPayload {\n const stepsJson = JSON.stringify({\n sessionId: history.sessionId,\n type: history.type,\n startedAt: history.startedAt,\n ...(history.endedAt ? { endedAt: history.endedAt } : {}),\n stepCount: history.steps.length,\n steps: history.steps,\n });\n\n return { stepsJson, generatedJs: generateCode(history) };\n}\n\nexport const sessionsIndexResource: ResourceDefinition = {\n name: 'sessions',\n uri: 'wdio://sessions',\n description: 'JSON index of all browser and app sessions with metadata and step counts',\n handler: async () => ({\n contents: [{ uri: 'wdio://sessions', mimeType: 'application/json', text: buildSessionsIndex() }],\n }),\n};\n\nexport const sessionCurrentStepsResource: ResourceDefinition = {\n name: 'session-current-steps',\n uri: 'wdio://session/current/steps',\n description: 'JSON step log for the currently active session',\n handler: async () => {\n const payload = buildCurrentSessionSteps();\n return {\n contents: [{\n uri: 'wdio://session/current/steps',\n mimeType: 'application/json',\n text: payload?.stepsJson ?? '{\"error\":\"No active session\"}',\n }],\n };\n },\n};\n\nexport const sessionCurrentCodeResource: ResourceDefinition = {\n name: 'session-current-code',\n uri: 'wdio://session/current/code',\n description: 'Generated WebdriverIO JS code for the currently active session',\n handler: async () => {\n const payload = buildCurrentSessionSteps();\n return {\n contents: [{\n uri: 'wdio://session/current/code',\n mimeType: 'text/plain',\n text: payload?.generatedJs ?? '// No active session',\n }],\n };\n },\n};\n\nexport const sessionStepsResource: ResourceDefinition = {\n name: 'session-steps',\n template: new ResourceTemplate('wdio://session/{sessionId}/steps', { list: undefined }),\n description: 'JSON step log for a specific session by ID',\n handler: async (uri, { sessionId }) => {\n const payload = buildSessionStepsById(sessionId as string);\n return {\n contents: [{\n uri: uri.href,\n mimeType: 'application/json',\n text: payload?.stepsJson ?? `{\"error\":\"Session not found: ${sessionId}\"}`,\n }],\n };\n },\n};\n\nexport const sessionCodeResource: ResourceDefinition = {\n name: 'session-code',\n template: new ResourceTemplate('wdio://session/{sessionId}/code', { list: undefined }),\n description: 'Generated WebdriverIO JS code for a specific session by ID',\n handler: async (uri, { sessionId }) => {\n const payload = buildSessionStepsById(sessionId as string);\n return {\n contents: [{\n uri: uri.href,\n mimeType: 'text/plain',\n text: payload?.generatedJs ?? `// Session not found: ${sessionId}`,\n }],\n };\n },\n};","// src/recording/code-generator.ts\nimport type { RecordedStep, SessionHistory } from '../types/recording';\n\n/** Escape single quotes so generated JS string literals are valid. */\nfunction escapeStr(value: unknown): string {\n return String(value).replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n}\n\nfunction formatParams(params: Record<string, unknown>): string {\n return Object.entries(params)\n .map(([k, v]) => `${k}=\"${v}\"`)\n .join(' ');\n}\n\nfunction indentJson(value: unknown): string {\n return JSON.stringify(value, null, 2)\n .split('\\n')\n .map((line, i) => (i > 0 ? ` ${line}` : line))\n .join('\\n');\n}\n\nfunction generateStep(step: RecordedStep, history: SessionHistory): string {\n if (step.tool === '__session_transition__') {\n const newId = (step.params.newSessionId as string) ?? 'unknown';\n return `// --- new session: ${newId} started at ${step.timestamp} ---`;\n }\n\n if (step.status === 'error') {\n return `// [error] ${step.tool}: ${formatParams(step.params)} — ${step.error ?? 'unknown error'}`;\n }\n\n const p = step.params;\n switch (step.tool) {\n case 'start_session': {\n const platform = p.platform as string;\n const isBrowserStack = 'bstack:options' in history.capabilities;\n const capJson = indentJson(history.capabilities)\n .split('\\n')\n .map((line, i) => (i > 0 ? ` ${line}` : line))\n .join('\\n');\n\n if (isBrowserStack) {\n const nav =\n platform === 'browser' && p.navigationUrl\n ? `\\nawait browser.url('${escapeStr(p.navigationUrl)}');`\n : '';\n return [\n 'const browser = await remote({',\n \" protocol: 'https',\",\n \" hostname: 'hub.browserstack.com',\",\n ' port: 443,',\n \" path: '/wd/hub',\",\n ' user: process.env.BS_USER,',\n ' key: process.env.BS_KEY,',\n ` capabilities: ${capJson}`,\n `});${nav}`,\n ].join('\\n');\n }\n\n if (platform === 'browser') {\n const nav = p.navigationUrl ? `\\nawait browser.url('${escapeStr(p.navigationUrl)}');` : '';\n return `const browser = await remote({\\n capabilities: ${indentJson(history.capabilities)}\\n});${nav}`;\n }\n // Mobile (ios/android)\n const config: Record<string, unknown> = {\n protocol: 'http',\n hostname: history.appiumConfig?.hostname ?? 'localhost',\n port: history.appiumConfig?.port ?? 4723,\n path: history.appiumConfig?.path ?? '/',\n capabilities: history.capabilities,\n };\n return `const browser = await remote(${indentJson(config)});`;\n }\n case 'close_session':\n return '// Session closed';\n case 'navigate':\n return `await browser.url('${escapeStr(p.url)}');`;\n case 'click_element':\n return `await browser.$('${escapeStr(p.selector)}').click();`;\n case 'set_value':\n return `await browser.$('${escapeStr(p.selector)}').setValue('${escapeStr(p.value)}');`;\n case 'scroll': {\n const scrollAmount = (p.direction as string) === 'down' ? (p.pixels as number) : -(p.pixels as number);\n return `await browser.execute(() => window.scrollBy(0, ${scrollAmount}));`;\n }\n case 'tap_element':\n if (p.selector !== undefined) {\n return `await browser.$('${escapeStr(p.selector)}').click();`;\n }\n return `await browser.tap({ x: ${p.x}, y: ${p.y} });`;\n case 'swipe':\n return `await browser.execute('mobile: swipe', { direction: '${escapeStr(p.direction)}' });`;\n case 'drag_and_drop':\n if (p.targetSelector !== undefined) {\n return `await browser.$('${escapeStr(p.sourceSelector)}').dragAndDrop(browser.$('${escapeStr(p.targetSelector)}'));`;\n }\n return `await browser.$('${escapeStr(p.sourceSelector)}').dragAndDrop({ x: ${p.x}, y: ${p.y} });`;\n case 'execute_script': {\n const scriptCode = `'${escapeStr(p.script)}'`;\n const scriptArgs = (p.args as unknown[])?.length ? `, ${indentJson(p.args)}` : '';\n return `await browser.execute(${scriptCode}${scriptArgs});`;\n }\n default:\n return `// [unknown tool] ${step.tool}`;\n }\n}\n\nfunction bsStatusUpdateLines(sessionType: 'browser' | 'ios' | 'android'): string[] {\n const apiUrl = sessionType === 'browser'\n ? 'https://api.browserstack.com/automate/sessions/'\n : 'https://api-cloud.browserstack.com/app-automate/sessions/';\n return [\n \" const bsAuth = Buffer.from(`${process.env.BS_USER}:${process.env.BS_KEY}`).toString('base64');\",\n ` await fetch('${apiUrl}' + browser.sessionId + '.json', {`,\n \" method: 'PUT',\",\n \" headers: { Authorization: 'Basic ' + bsAuth, 'Content-Type': 'application/json' },\",\n ' body: JSON.stringify({ status: bsStatus, ...(bsReason ? { reason: bsReason } : {}) })',\n ' });',\n ];\n}\n\nexport function generateCode(history: SessionHistory): string {\n const bstackOptions = history.capabilities['bstack:options'] as Record<string, unknown> | undefined;\n const isBrowserStack = bstackOptions !== undefined;\n const usesBrowserstackLocal = bstackOptions?.local === true;\n\n const steps = history.steps\n .map(step => generateStep(step, history))\n .join('\\n')\n .split('\\n')\n .map(line => ` ${line}`)\n .join('\\n');\n\n if (isBrowserStack) {\n const bsSteps = steps.replace(/const browser = await remote\\(/g, 'browser = await remote(');\n const statusUpdate = bsStatusUpdateLines(history.type).join('\\n');\n const preamble = 'let browser;\\nlet bsStatus = \\'passed\\';\\nlet bsReason;';\n const catchBlock = '} catch (e) {\\n bsStatus = \\'failed\\';\\n bsReason = String(e);\\n throw e;';\n const finallyBody = ` if (browser) {\\n${statusUpdate}\\n await browser.deleteSession();\\n }`;\n\n if (usesBrowserstackLocal) {\n const tunnelSetup = [\n '',\n 'const tunnel = new BrowserstackTunnel();',\n 'const startTunnel = promisify(tunnel.start.bind(tunnel));',\n 'const stopTunnel = promisify(tunnel.stop.bind(tunnel));',\n 'await startTunnel({ key: process.env.BROWSERSTACK_ACCESS_KEY });',\n '',\n ].join('\\n');\n\n return [\n \"import { remote } from 'webdriverio';\",\n \"import { Local as BrowserstackTunnel } from 'browserstack-local';\",\n \"import { promisify } from 'node:util';\",\n tunnelSetup,\n preamble,\n 'try {',\n bsSteps,\n catchBlock,\n '} finally {',\n finallyBody,\n ' await stopTunnel();',\n '}',\n ].join('\\n');\n }\n\n return [\n \"import { remote } from 'webdriverio';\",\n '',\n preamble,\n 'try {',\n bsSteps,\n catchBlock,\n '} finally {',\n finallyBody,\n '}',\n ].join('\\n');\n }\n\n return `import { remote } from 'webdriverio';\\n\\ntry {\\n${steps}\\n} finally {\\n await browser.deleteSession();\\n}`;\n}\n","import type { ResourceDefinition } from '../types/resource';\nimport { getBrowser } from '../session/state';\n\nexport const capabilitiesResource: ResourceDefinition = {\n name: 'session-current-capabilities',\n uri: 'wdio://session/current/capabilities',\n description: 'Raw capabilities returned by the WebDriver/Appium server for the current session. Use for debugging — shows the actual values the driver accepted, including defaults applied by BrowserStack or Appium.',\n handler: async () => {\n try {\n const browser = getBrowser();\n return {\n contents: [{\n uri: 'wdio://session/current/capabilities',\n mimeType: 'application/json',\n text: JSON.stringify(browser.capabilities, null, 2),\n }],\n };\n } catch (e) {\n return {\n contents: [{\n uri: 'wdio://session/current/capabilities',\n mimeType: 'application/json',\n text: JSON.stringify({ error: String(e) }),\n }],\n };\n }\n },\n};\n","import type { ResourceDefinition } from '../types/resource';\nimport { getBrowser } from '../session/state';\nimport { getElements } from '../scripts/get-elements';\nimport { encode } from '@toon-format/toon';\n\nexport const elementsResource: ResourceDefinition = {\n name: 'session-current-elements',\n uri: 'wdio://session/current/elements',\n description: 'Interactable elements on the current page. Prefer this over screenshot — returns ready-to-use selectors, faster, and far fewer tokens. Only use screenshot for visual verification or debugging.',\n handler: async () => {\n try {\n const browser = getBrowser();\n const result = await getElements(browser, {});\n const text = encode(result).replace(/,\"\"/g, ',').replace(/\"\",/g, ',');\n return { contents: [{ uri: 'wdio://session/current/elements', mimeType: 'text/plain', text }] };\n } catch (e) {\n return {\n contents: [{\n uri: 'wdio://session/current/elements',\n mimeType: 'text/plain',\n text: `Error getting visible elements: ${e}`\n }]\n };\n }\n },\n};\n","import type { ResourceDefinition } from '../types/resource';\nimport { getBrowser } from '../session/state';\nimport { getBrowserAccessibilityTree } from '../scripts/get-browser-accessibility-tree';\nimport { encode } from '@toon-format/toon';\n\nexport async function readAccessibilityTree(params: {\n limit?: number;\n offset?: number;\n roles?: string[];\n}): Promise<{ mimeType: string; text: string }> {\n try {\n const browser = getBrowser();\n\n if (browser.isAndroid || browser.isIOS) {\n return {\n mimeType: 'text/plain',\n text: 'Error: accessibility is browser-only. For mobile apps, use elements resource instead.',\n };\n }\n\n const { limit = 0, offset = 0, roles } = params;\n\n let nodes = await getBrowserAccessibilityTree(browser);\n\n if (nodes.length === 0) {\n return { mimeType: 'text/plain', text: 'No accessibility tree available' };\n }\n\n nodes = nodes.filter((n) => n.name && n.name.trim() !== '');\n\n if (roles && roles.length > 0) {\n const roleSet = new Set(roles.map((r) => r.toLowerCase()));\n nodes = nodes.filter((n) => n.role && roleSet.has(n.role.toLowerCase()));\n }\n\n const total = nodes.length;\n\n if (offset > 0) {\n nodes = nodes.slice(offset);\n }\n if (limit > 0) {\n nodes = nodes.slice(0, limit);\n }\n\n const stateKeys = ['level', 'disabled', 'checked', 'expanded', 'selected', 'pressed', 'required', 'readonly'] as const;\n const usedKeys = stateKeys.filter((k) => nodes.some((n) => n[k] !== ''));\n const trimmed = nodes.map(({ role, name, selector, ...state }) => {\n const node: Record<string, unknown> = { role, name, selector };\n for (const k of usedKeys) node[k] = state[k];\n return node;\n });\n\n const result = {\n total,\n showing: trimmed.length,\n hasMore: offset + trimmed.length < total,\n nodes: trimmed,\n };\n\n const toon = encode(result).replace(/,\"\"/g, ',').replace(/\"\",/g, ',');\n\n return { mimeType: 'text/plain', text: toon };\n } catch (e) {\n return { mimeType: 'text/plain', text: `Error getting accessibility tree: ${e}` };\n }\n}\n\nexport const accessibilityResource: ResourceDefinition = {\n name: 'session-current-accessibility',\n uri: 'wdio://session/current/accessibility',\n description: 'Accessibility tree for the current page. Returns all elements by default.',\n handler: async () => {\n const result = await readAccessibilityTree({});\n return { contents: [{ uri: 'wdio://session/current/accessibility', mimeType: result.mimeType, text: result.text }] };\n },\n};","/**\n * Browser accessibility tree\n * Single browser.execute() call: DOM walk → flat accessibility node list\n *\n * NOTE: This script runs in browser context via browser.execute()\n * It must be self-contained with no external dependencies\n */\n\nexport interface AccessibilityNode {\n role: string;\n name: string;\n selector: string;\n level: number | string;\n disabled: string;\n checked: string;\n expanded: string;\n selected: string;\n pressed: string;\n required: string;\n readonly: string;\n}\n\nconst accessibilityTreeScript = () => (function () {\n\n const INPUT_TYPE_ROLES: Record<string, string> = {\n text: 'textbox', search: 'searchbox', email: 'textbox', url: 'textbox',\n tel: 'textbox', password: 'textbox', number: 'spinbutton',\n checkbox: 'checkbox', radio: 'radio', range: 'slider',\n submit: 'button', reset: 'button', image: 'button', file: 'button', color: 'button',\n };\n\n const LANDMARK_ROLES = new Set([\n 'navigation', 'main', 'banner', 'contentinfo', 'complementary', 'form', 'dialog', 'region',\n ]);\n\n // Container roles: named only via aria-label/aria-labelledby, not textContent\n const CONTAINER_ROLES = new Set([\n 'navigation', 'banner', 'contentinfo', 'complementary', 'main', 'form',\n 'region', 'group', 'list', 'listitem', 'table', 'row', 'rowgroup', 'generic',\n ]);\n\n function getRole(el: HTMLElement): string | null {\n const explicit = el.getAttribute('role');\n if (explicit) return explicit.split(' ')[0];\n\n const tag = el.tagName.toLowerCase();\n\n switch (tag) {\n case 'button': return 'button';\n case 'a': return el.hasAttribute('href') ? 'link' : null;\n case 'input': {\n const type = (el.getAttribute('type') || 'text').toLowerCase();\n if (type === 'hidden') return null;\n return INPUT_TYPE_ROLES[type] || 'textbox';\n }\n case 'select': return 'combobox';\n case 'textarea': return 'textbox';\n case 'h1': case 'h2': case 'h3': case 'h4': case 'h5': case 'h6': return 'heading';\n case 'img': return 'img';\n case 'nav': return 'navigation';\n case 'main': return 'main';\n case 'header': return !el.closest('article,aside,main,nav,section') ? 'banner' : null;\n case 'footer': return !el.closest('article,aside,main,nav,section') ? 'contentinfo' : null;\n case 'aside': return 'complementary';\n case 'dialog': return 'dialog';\n case 'form': return 'form';\n case 'section': return (el.hasAttribute('aria-label') || el.hasAttribute('aria-labelledby')) ? 'region' : null;\n case 'summary': return 'button';\n case 'details': return 'group';\n case 'progress': return 'progressbar';\n case 'meter': return 'meter';\n case 'ul': case 'ol': return 'list';\n case 'li': return 'listitem';\n case 'table': return 'table';\n }\n\n if ((el as HTMLElement & { contentEditable: string }).contentEditable === 'true') return 'textbox';\n if (el.hasAttribute('tabindex') && parseInt(el.getAttribute('tabindex') || '-1', 10) >= 0) return 'generic';\n\n return null;\n }\n\n function getAccessibleName(el: HTMLElement, role: string | null): string {\n const ariaLabel = el.getAttribute('aria-label');\n if (ariaLabel) return ariaLabel.trim();\n\n const labelledBy = el.getAttribute('aria-labelledby');\n if (labelledBy) {\n const texts = labelledBy.split(/\\s+/)\n .map(id => document.getElementById(id)?.textContent?.trim() || '')\n .filter(Boolean);\n if (texts.length > 0) return texts.join(' ').slice(0, 100);\n }\n\n const tag = el.tagName.toLowerCase();\n\n if (tag === 'img' || (tag === 'input' && el.getAttribute('type') === 'image')) {\n const alt = el.getAttribute('alt');\n if (alt !== null) return alt.trim();\n }\n\n if (['input', 'select', 'textarea'].includes(tag)) {\n const id = el.getAttribute('id');\n if (id) {\n const label = document.querySelector(`label[for=\"${CSS.escape(id)}\"]`);\n if (label) return label.textContent?.trim() || '';\n }\n const parentLabel = el.closest('label');\n if (parentLabel) {\n const clone = parentLabel.cloneNode(true) as HTMLElement;\n clone.querySelectorAll('input,select,textarea').forEach(n => n.remove());\n const lt = clone.textContent?.trim();\n if (lt) return lt;\n }\n }\n\n const ph = el.getAttribute('placeholder');\n if (ph) return ph.trim();\n\n const title = el.getAttribute('title');\n if (title) return title.trim();\n\n if (role && CONTAINER_ROLES.has(role)) return '';\n return (el.textContent?.trim().replace(/\\s+/g, ' ') || '').slice(0, 100);\n }\n\n function getSelector(element: HTMLElement): string {\n const tag = element.tagName.toLowerCase();\n\n const text = element.textContent?.trim().replace(/\\s+/g, ' ');\n if (text && text.length > 0 && text.length <= 50) {\n const sameTagElements = document.querySelectorAll(tag);\n let matchCount = 0;\n sameTagElements.forEach(el => { if (el.textContent?.includes(text)) matchCount++; });\n if (matchCount === 1) return `${tag}*=${text}`;\n }\n\n const ariaLabel = element.getAttribute('aria-label');\n if (ariaLabel && ariaLabel.length <= 80) return `aria/${ariaLabel}`;\n\n const testId = element.getAttribute('data-testid');\n if (testId) {\n const sel = `[data-testid=\"${CSS.escape(testId)}\"]`;\n if (document.querySelectorAll(sel).length === 1) return sel;\n }\n\n if (element.id) return `#${CSS.escape(element.id)}`;\n\n const nameAttr = element.getAttribute('name');\n if (nameAttr) {\n const sel = `${tag}[name=\"${CSS.escape(nameAttr)}\"]`;\n if (document.querySelectorAll(sel).length === 1) return sel;\n }\n\n if (element.className && typeof element.className === 'string') {\n const classes = element.className.trim().split(/\\s+/).filter(Boolean);\n for (const cls of classes) {\n const sel = `${tag}.${CSS.escape(cls)}`;\n if (document.querySelectorAll(sel).length === 1) return sel;\n }\n if (classes.length >= 2) {\n const sel = `${tag}${classes.slice(0, 2).map(c => `.${CSS.escape(c)}`).join('')}`;\n if (document.querySelectorAll(sel).length === 1) return sel;\n }\n }\n\n let current: HTMLElement | null = element;\n const path: string[] = [];\n while (current && current !== document.documentElement) {\n let seg = current.tagName.toLowerCase();\n if (current.id) { path.unshift(`#${CSS.escape(current.id)}`); break; }\n const parent = current.parentElement;\n if (parent) {\n const siblings = Array.from(parent.children).filter(c => c.tagName === current!.tagName);\n if (siblings.length > 1) seg += `:nth-of-type(${siblings.indexOf(current) + 1})`;\n }\n path.unshift(seg);\n current = current.parentElement;\n if (path.length >= 4) break;\n }\n return path.join(' > ');\n }\n\n function isVisible(el: HTMLElement): boolean {\n if (typeof el.checkVisibility === 'function') {\n return el.checkVisibility({ opacityProperty: true, visibilityProperty: true, contentVisibilityAuto: true });\n }\n const style = window.getComputedStyle(el);\n return style.display !== 'none' &&\n style.visibility !== 'hidden' &&\n style.opacity !== '0' &&\n el.offsetWidth > 0 &&\n el.offsetHeight > 0;\n }\n\n function getLevel(el: HTMLElement): number | undefined {\n const m = el.tagName.toLowerCase().match(/^h([1-6])$/);\n if (m) return parseInt(m[1], 10);\n const ariaLevel = el.getAttribute('aria-level');\n if (ariaLevel) return parseInt(ariaLevel, 10);\n return undefined;\n }\n\n function getState(el: HTMLElement): Record<string, string> {\n const inputEl = el as HTMLInputElement;\n const isCheckable = ['input', 'menuitemcheckbox', 'menuitemradio'].includes(el.tagName.toLowerCase()) ||\n ['checkbox', 'radio', 'switch'].includes(el.getAttribute('role') || '');\n return {\n disabled: (el.getAttribute('aria-disabled') === 'true' || inputEl.disabled) ? 'true' : '',\n checked: (isCheckable && inputEl.checked) ? 'true' : el.getAttribute('aria-checked') || '',\n expanded: el.getAttribute('aria-expanded') || '',\n selected: el.getAttribute('aria-selected') || '',\n pressed: el.getAttribute('aria-pressed') || '',\n required: (inputEl.required || el.getAttribute('aria-required') === 'true') ? 'true' : '',\n readonly: (inputEl.readOnly || el.getAttribute('aria-readonly') === 'true') ? 'true' : '',\n };\n }\n\n type RawNode = Record<string, unknown>;\n\n const result: RawNode[] = [];\n\n function walk(el: HTMLElement, depth = 0): void {\n if (depth > 200) return;\n if (!isVisible(el)) return;\n\n const role = getRole(el);\n\n if (!role) {\n for (const child of Array.from(el.children)) {\n walk(child as HTMLElement, depth + 1);\n }\n return;\n }\n\n const name = getAccessibleName(el, role);\n const isLandmark = LANDMARK_ROLES.has(role);\n const hasIdentity = !!(name || isLandmark);\n const selector = hasIdentity ? getSelector(el) : '';\n const node: RawNode = { role, name, selector, level: getLevel(el) ?? '', ...getState(el) };\n result.push(node);\n\n for (const child of Array.from(el.children)) {\n walk(child as HTMLElement, depth + 1);\n }\n }\n\n for (const child of Array.from(document.body.children)) {\n walk(child as HTMLElement, 0);\n }\n\n return result;\n})();\n\n/**\n * Get browser accessibility tree via a single DOM walk.\n */\nexport async function getBrowserAccessibilityTree(\n browser: WebdriverIO.Browser,\n): Promise<AccessibilityNode[]> {\n return (browser as any).execute(accessibilityTreeScript) as unknown as Promise<AccessibilityNode[]>;\n}\n","import type { ResourceDefinition } from '../types/resource';\nimport { getBrowser } from '../session/state';\nimport sharp from 'sharp';\n\nconst MAX_DIMENSION = 2000;\nconst MAX_FILE_SIZE_BYTES = 1024 * 1024;\n\nasync function processScreenshot(screenshotBase64: string): Promise<{ data: Buffer; mimeType: string }> {\n const inputBuffer = Buffer.from(screenshotBase64, 'base64');\n let image = sharp(inputBuffer);\n const metadata = await image.metadata();\n\n const width = metadata.width ?? 0;\n const height = metadata.height ?? 0;\n\n if (width > MAX_DIMENSION || height > MAX_DIMENSION) {\n const resizeOptions = width > height ? { width: MAX_DIMENSION } : { height: MAX_DIMENSION };\n image = image.resize(resizeOptions);\n }\n\n let outputBuffer = await image.png({ compressionLevel: 9 }).toBuffer();\n\n if (outputBuffer.length > MAX_FILE_SIZE_BYTES) {\n let quality = 90;\n while (quality >= 10 && outputBuffer.length > MAX_FILE_SIZE_BYTES) {\n outputBuffer = await image.jpeg({ quality, mozjpeg: true }).toBuffer();\n quality -= 10;\n }\n return { data: outputBuffer, mimeType: 'image/jpeg' };\n }\n\n return { data: outputBuffer, mimeType: 'image/png' };\n}\n\nasync function readScreenshot(): Promise<{ mimeType: string; blob: string }> {\n try {\n const browser = getBrowser();\n const screenshot = await browser.takeScreenshot();\n const { data, mimeType } = await processScreenshot(screenshot);\n return { mimeType, blob: data.toString('base64') };\n } catch (e) {\n return { mimeType: 'text/plain', blob: Buffer.from(`Error: ${e}`).toString('base64') };\n }\n}\n\nexport const screenshotResource: ResourceDefinition = {\n name: 'session-current-screenshot',\n uri: 'wdio://session/current/screenshot',\n description: 'Screenshot of the current page',\n handler: async () => {\n const result = await readScreenshot();\n return { contents: [{ uri: 'wdio://session/current/screenshot', mimeType: result.mimeType, blob: result.blob }] };\n },\n};","import type { ResourceDefinition } from '../types/resource';\nimport { getBrowser } from '../session/state';\n\nasync function readCookies(name?: string): Promise<{ mimeType: string; text: string }> {\n try {\n const browser = getBrowser();\n\n if (name) {\n const cookie = await browser.getCookies([name]);\n if (cookie.length === 0) {\n return { mimeType: 'application/json', text: JSON.stringify(null) };\n }\n return { mimeType: 'application/json', text: JSON.stringify(cookie[0]) };\n }\n const cookies = await browser.getCookies();\n return { mimeType: 'application/json', text: JSON.stringify(cookies) };\n } catch (e) {\n return { mimeType: 'application/json', text: JSON.stringify({ error: String(e) }) };\n }\n}\n\nexport const cookiesResource: ResourceDefinition = {\n name: 'session-current-cookies',\n uri: 'wdio://session/current/cookies',\n description: 'Cookies for the current session',\n handler: async () => {\n const result = await readCookies();\n return { contents: [{ uri: 'wdio://session/current/cookies', mimeType: result.mimeType, text: result.text }] };\n },\n};","import type { ResourceDefinition } from '../types/resource';\nimport { ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { getBrowser } from '../session/state';\n\nasync function readAppState(bundleId: string): Promise<{ mimeType: string; text: string }> {\n try {\n const browser = getBrowser();\n\n const appIdentifier = browser.isAndroid\n ? { appId: bundleId }\n : { bundleId: bundleId };\n\n const state: string = await browser.execute('mobile: queryAppState', appIdentifier);\n\n const stateMap: Record<string, string> = {\n 0: 'not installed',\n 1: 'not running',\n 2: 'running in background (suspended)',\n 3: 'running in background',\n 4: 'running in foreground',\n };\n\n return {\n mimeType: 'text/plain',\n text: `App state for ${bundleId}: ${stateMap[state] || 'unknown: ' + state}`,\n };\n } catch (e) {\n return { mimeType: 'text/plain', text: `Error getting app state: ${e}` };\n }\n}\n\nexport const appStateResource: ResourceDefinition = {\n name: 'session-current-app-state',\n template: new ResourceTemplate('wdio://session/current/app-state/{bundleId}', { list: undefined }),\n description: 'App state for a given bundle ID',\n handler: async (uri, variables) => {\n const result = await readAppState(variables.bundleId as string);\n return { contents: [{ uri: uri.href, mimeType: result.mimeType, text: result.text }] };\n },\n};","import type { ResourceDefinition } from '../types/resource';\nimport { getBrowser } from '../session/state';\n\nasync function readContexts(): Promise<{ mimeType: string; text: string }> {\n try {\n const browser = getBrowser();\n const contexts = await browser.getContexts();\n return { mimeType: 'application/json', text: JSON.stringify(contexts) };\n } catch (e) {\n return { mimeType: 'text/plain', text: `Error: ${e}` };\n }\n}\n\nasync function readCurrentContext(): Promise<{ mimeType: string; text: string }> {\n try {\n const browser = getBrowser();\n const currentContext = await browser.getContext();\n return { mimeType: 'application/json', text: JSON.stringify(currentContext) };\n } catch (e) {\n return { mimeType: 'text/plain', text: `Error: ${e}` };\n }\n}\n\nexport const contextsResource: ResourceDefinition = {\n name: 'session-current-contexts',\n uri: 'wdio://session/current/contexts',\n description: 'Available contexts (NATIVE_APP, WEBVIEW)',\n handler: async () => {\n const result = await readContexts();\n return { contents: [{ uri: 'wdio://session/current/contexts', mimeType: result.mimeType, text: result.text }] };\n },\n};\n\nexport const contextResource: ResourceDefinition = {\n name: 'session-current-context',\n uri: 'wdio://session/current/context',\n description: 'Currently active context',\n handler: async () => {\n const result = await readCurrentContext();\n return { contents: [{ uri: 'wdio://session/current/context', mimeType: result.mimeType, text: result.text }] };\n },\n};","import type { ResourceDefinition } from '../types/resource';\nimport { getBrowser } from '../session/state';\n\nasync function readGeolocation(): Promise<{ mimeType: string; text: string }> {\n try {\n const browser = getBrowser();\n const location = await browser.getGeoLocation();\n return { mimeType: 'application/json', text: JSON.stringify(location) };\n } catch (e) {\n return { mimeType: 'text/plain', text: `Error: ${e}` };\n }\n}\n\nexport const geolocationResource: ResourceDefinition = {\n name: 'session-current-geolocation',\n uri: 'wdio://session/current/geolocation',\n description: 'Current device geolocation',\n handler: async () => {\n const result = await readGeolocation();\n return { contents: [{ uri: 'wdio://session/current/geolocation', mimeType: result.mimeType, text: result.text }] };\n },\n};","import type { ResourceDefinition } from '../types/resource';\nimport { getBrowser } from '../session/state';\n\nasync function readTabs(): Promise<{ mimeType: string; text: string }> {\n try {\n const browser = getBrowser();\n const handles = await browser.getWindowHandles();\n const currentHandle = await browser.getWindowHandle();\n const tabs = [];\n for (const handle of handles) {\n await browser.switchToWindow(handle);\n tabs.push({\n handle,\n title: await browser.getTitle(),\n url: await browser.getUrl(),\n isActive: handle === currentHandle,\n });\n }\n await browser.switchToWindow(currentHandle);\n return { mimeType: 'application/json', text: JSON.stringify(tabs) };\n } catch (e) {\n return { mimeType: 'text/plain', text: `Error: ${e}` };\n }\n}\n\nexport const tabsResource: ResourceDefinition = {\n name: 'session-current-tabs',\n uri: 'wdio://session/current/tabs',\n description: 'Browser tabs in the current session',\n handler: async () => {\n const result = await readTabs();\n return { contents: [{ uri: 'wdio://session/current/tabs', mimeType: result.mimeType, text: result.text }] };\n },\n};","import { remote } from 'webdriverio';\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ToolDefinition } from '../types/tool';\nimport { z } from 'zod';\nimport type { SessionMetadata } from '../session/state';\nimport { getBrowser, getState } from '../session/state';\nimport { closeSession, registerSession } from '../session/lifecycle';\nimport { getProvider } from '../providers/registry';\nimport { coerceBoolean } from '../utils/zod-helpers';\n\nconst platformEnum = z.enum(['browser', 'ios', 'android']);\nconst browserEnum = z.enum(['chrome', 'firefox', 'edge', 'safari']);\nconst automationEnum = z.enum(['XCUITest', 'UiAutomator2']);\n\nexport const startSessionToolDefinition: ToolDefinition = {\n name: 'start_session',\n description: 'Starts a browser or mobile app session. For local browser, use browser platform. For mobile apps, use ios or android platform. Use attach mode to connect to an existing Chrome instance.',\n inputSchema: {\n provider: z.enum(['local', 'browserstack']).optional().default('local').describe('Session provider (default: local)'),\n platform: platformEnum.describe('Session platform type'),\n browser: browserEnum.optional().describe('Browser to launch (required for browser platform)'),\n browserVersion: z.string().optional().describe('Browser version (BrowserStack only, default: latest)'),\n os: z.string().optional().describe('Operating system (BrowserStack browser only, e.g. \"Windows\", \"OS X\")'),\n osVersion: z.string().optional().describe('OS version (BrowserStack browser only, e.g. \"11\", \"Sequoia\")'),\n app: z.string().optional().describe('BrowserStack app URL (bs://...) or custom_id for mobile sessions'),\n reporting: z.object({\n project: z.string().optional(),\n build: z.string().optional(),\n session: z.string().optional(),\n }).optional().describe('BrowserStack reporting labels (project, build, session)'),\n headless: coerceBoolean.optional().default(true).describe('Run browser in headless mode (default: true)'),\n windowWidth: z.number().min(400).max(3840).optional().default(1920).describe('Browser window width'),\n windowHeight: z.number().min(400).max(2160).optional().default(1080).describe('Browser window height'),\n deviceName: z.string().optional().describe('Mobile device/emulator/simulator name (required for ios/android)'),\n platformVersion: z.string().optional().describe('OS version (e.g., \"17.0\", \"14\")'),\n appPath: z.string().optional().describe('Path to app file (.app/.apk/.ipa)'),\n automationName: automationEnum.optional().describe('Automation driver'),\n autoGrantPermissions: coerceBoolean.optional().describe('Auto-grant app permissions (default: true)'),\n autoAcceptAlerts: coerceBoolean.optional().describe('Auto-accept alerts (default: true)'),\n autoDismissAlerts: coerceBoolean.optional().describe('Auto-dismiss alerts (default: false)'),\n appWaitActivity: z.string().optional().describe('Activity to wait for on Android launch'),\n udid: z.string().optional().describe('Unique Device Identifier for iOS real device'),\n noReset: coerceBoolean.optional().describe('Preserve app data between sessions'),\n fullReset: coerceBoolean.optional().describe('Uninstall app before/after session'),\n newCommandTimeout: z.number().min(0).optional().default(300).describe('Appium command timeout in seconds'),\n attach: coerceBoolean.optional().default(false).describe('Attach to existing Chrome instead of launching'),\n attachConfig: z.object({\n port: z.number().optional().default(9222),\n host: z.string().optional().default('localhost'),\n }).optional().describe('Chrome remote debugging connection (attach mode only, defaults: port 9222, host localhost)'),\n appiumConfig: z.object({\n host: z.string().optional(),\n port: z.number().optional(),\n path: z.string().optional(),\n }).optional().describe('Appium server connection (local provider only)'),\n browserstackLocal: coerceBoolean.optional().default(false).describe('Enable BrowserStack Local tunnel for testing against local/internal URLs (BrowserStack only, default: false). When true, the tunnel is started automatically before the session and stopped when the session is closed.'),\n navigationUrl: z.string().optional().describe('URL to navigate to after starting'),\n capabilities: z.record(z.string(), z.unknown()).optional().describe('Additional capabilities to merge'),\n },\n};\n\ntype StartSessionArgs = {\n provider?: 'local' | 'browserstack';\n platform: 'browser' | 'ios' | 'android';\n browser?: 'chrome' | 'firefox' | 'edge' | 'safari';\n browserVersion?: string;\n os?: string;\n osVersion?: string;\n app?: string;\n reporting?: { project?: string; build?: string; session?: string };\n headless?: boolean;\n windowWidth?: number;\n windowHeight?: number;\n deviceName?: string;\n platformVersion?: string;\n appPath?: string;\n automationName?: 'XCUITest' | 'UiAutomator2';\n autoGrantPermissions?: boolean;\n autoAcceptAlerts?: boolean;\n autoDismissAlerts?: boolean;\n appWaitActivity?: string;\n udid?: string;\n noReset?: boolean;\n fullReset?: boolean;\n newCommandTimeout?: number;\n attach?: boolean;\n attachConfig?: { port?: number; host?: string };\n appiumConfig?: { host?: string; port?: number; path?: string };\n browserstackLocal?: boolean;\n navigationUrl?: string;\n capabilities?: Record<string, unknown>;\n};\n\nexport const closeSessionToolDefinition: ToolDefinition = {\n name: 'close_session',\n description: 'Closes or detaches from the current browser or app session',\n inputSchema: {\n detach: coerceBoolean.optional().describe('If true, disconnect without terminating (preserves app state). Default: false'),\n },\n};\n\ntype TabSnapshot = { activeTabUrl: string | undefined; allTabUrls: string[] };\n\nasync function closeStaleMappers(host: string, port: number): Promise<TabSnapshot> {\n try {\n const res = await fetch(`http://${host}:${port}/json`);\n const targets = await res.json() as { id: string; title: string; type: string; url: string }[];\n const mappers = targets.filter((t) => t.title?.includes('BiDi'));\n await Promise.all(mappers.map((t) => fetch(`http://${host}:${port}/json/close/${t.id}`)));\n const pages = targets.filter((t) => t.type === 'page' && !t.title?.includes('BiDi'));\n return { activeTabUrl: pages[0]?.url, allTabUrls: pages.map((t) => t.url) };\n } catch {\n return { activeTabUrl: undefined, allTabUrls: [] };\n }\n}\n\nasync function restoreAndSwitchToActiveTab(browser: WebdriverIO.Browser, activeTabUrl: string, allTabUrls: string[]): Promise<void> {\n const handles = await browser.getWindowHandles();\n const currentUrls: string[] = [];\n for (const handle of handles) {\n await browser.switchToWindow(handle);\n currentUrls.push(await browser.getUrl());\n }\n\n const missingUrls = allTabUrls.filter((u) => !currentUrls.includes(u));\n let missingIdx = 0;\n for (let i = 0; i < handles.length; i++) {\n if (currentUrls[i] === 'about:blank' && missingIdx < missingUrls.length) {\n await browser.switchToWindow(handles[i]);\n await browser.url(missingUrls[missingIdx]);\n currentUrls[i] = missingUrls[missingIdx++];\n }\n }\n\n for (let i = 0; i < handles.length; i++) {\n if (currentUrls[i] === activeTabUrl) {\n await browser.switchToWindow(handles[i]);\n break;\n }\n }\n}\n\nasync function waitForCDP(host: string, port: number, timeoutMs = 10000): Promise<void> {\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n try {\n const res = await fetch(`http://${host}:${port}/json/version`);\n if (res.ok) return;\n } catch {\n // not ready yet\n }\n await new Promise((r) => setTimeout(r, 300));\n }\n throw new Error(`Chrome did not expose CDP on ${host}:${port} within ${timeoutMs}ms`);\n}\n\nasync function startBrowserSession(args: StartSessionArgs): Promise<CallToolResult> {\n const {\n browser = 'chrome',\n headless = true,\n windowWidth = 1920,\n windowHeight = 1080,\n navigationUrl,\n capabilities: userCapabilities = {},\n } = args;\n\n const browserDisplayNames: Record<string, string> = {\n chrome: 'Chrome',\n firefox: 'Firefox',\n edge: 'Edge',\n safari: 'Safari',\n };\n\n const headlessSupported = browser !== 'safari';\n const effectiveHeadless = headless && headlessSupported;\n\n const provider = getProvider(args.provider ?? 'local', 'browser');\n const connectionConfig = provider.getConnectionConfig(args as Record<string, unknown>);\n const mergedCapabilities = provider.buildCapabilities({\n ...args as Record<string, unknown>,\n browser,\n headless,\n windowWidth,\n windowHeight,\n capabilities: userCapabilities,\n });\n\n const tunnelHandle = args.browserstackLocal\n ? await provider.startTunnel?.(args as Record<string, unknown>)\n : undefined;\n\n const wdioBrowser = await remote({ ...connectionConfig, capabilities: mergedCapabilities });\n const { sessionId } = wdioBrowser;\n\n const sessionMetadata: SessionMetadata = {\n type: 'browser',\n capabilities: mergedCapabilities,\n isAttached: false,\n provider: args.provider ?? 'local',\n tunnelHandle,\n };\n\n registerSession(sessionId, wdioBrowser, sessionMetadata, {\n sessionId,\n type: 'browser',\n startedAt: new Date().toISOString(),\n capabilities: mergedCapabilities,\n steps: [],\n });\n\n let sizeNote = '';\n try {\n await wdioBrowser.setWindowSize(windowWidth, windowHeight);\n } catch (e) {\n sizeNote = `\\nNote: Unable to set window size (${windowWidth}x${windowHeight}). ${e}`;\n }\n\n if (navigationUrl) {\n await wdioBrowser.url(navigationUrl);\n }\n\n const modeText = effectiveHeadless ? 'headless' : 'headed';\n const urlText = navigationUrl ? ` and navigated to ${navigationUrl}` : '';\n const headlessNote = headless && !headlessSupported\n ? '\\nNote: Safari does not support headless mode. Started in headed mode.'\n : '';\n\n return {\n content: [{\n type: 'text',\n text: `${browserDisplayNames[browser]} browser started in ${modeText} mode with sessionId: ${sessionId} (${windowWidth}x${windowHeight})${urlText}${headlessNote}${sizeNote}`,\n }],\n };\n}\n\nasync function startMobileSession(args: StartSessionArgs): Promise<CallToolResult> {\n const { platform, appPath, app, deviceName, noReset } = args;\n\n if (!appPath && !app && noReset !== true) {\n return {\n content: [{\n type: 'text',\n text: 'Error: Either \"appPath\" must be provided to install an app, or \"noReset: true\" must be set to connect to an already-running app.',\n }],\n };\n }\n\n const provider = getProvider(args.provider ?? 'local', args.platform);\n const serverConfig = provider.getConnectionConfig(args as Record<string, unknown>);\n const mergedCapabilities = provider.buildCapabilities(args as Record<string, unknown>);\n\n const tunnelHandle = args.browserstackLocal\n ? await provider.startTunnel?.(args as Record<string, unknown>)\n : undefined;\n\n const browser = await remote({ ...serverConfig, capabilities: mergedCapabilities });\n\n const { sessionId } = browser;\n const shouldAutoDetach = provider.shouldAutoDetach(args as Record<string, unknown>);\n const sessionType = provider.getSessionType(args as Record<string, unknown>);\n\n const metadata: SessionMetadata = {\n type: sessionType,\n capabilities: mergedCapabilities,\n isAttached: shouldAutoDetach,\n provider: args.provider ?? 'local',\n tunnelHandle,\n };\n\n registerSession(sessionId, browser, metadata, {\n sessionId,\n type: sessionType,\n startedAt: new Date().toISOString(),\n capabilities: mergedCapabilities,\n appiumConfig: { hostname: serverConfig.hostname, port: serverConfig.port, path: serverConfig.path },\n steps: [],\n });\n\n const appInfo = appPath ? `\\nApp: ${appPath}` : '\\nApp: (connected to running app)';\n const detachNote = shouldAutoDetach\n ? '\\n\\n(Auto-detach enabled: session will be preserved on close. Use close_session({ detach: false }) to force terminate.)'\n : '';\n\n return {\n content: [\n {\n type: 'text',\n text: `${platform} app session started with sessionId: ${sessionId}\\nDevice: ${deviceName}${appInfo}\\nAppium Server: ${serverConfig.hostname}:${serverConfig.port}${serverConfig.path}${detachNote}`,\n },\n ],\n };\n}\n\nasync function attachBrowserSession(args: StartSessionArgs): Promise<CallToolResult> {\n const { port = 9222, host = 'localhost' } = args.attachConfig ?? {};\n const { navigationUrl } = args;\n\n await waitForCDP(host, port);\n const { activeTabUrl, allTabUrls } = await closeStaleMappers(host, port);\n\n const capabilities = {\n browserName: 'chrome',\n unhandledPromptBehavior: 'dismiss',\n webSocketUrl: false,\n 'goog:chromeOptions': {\n debuggerAddress: `${host}:${port}`,\n },\n };\n\n const browser = await remote({\n connectionRetryTimeout: 30000,\n connectionRetryCount: 3,\n capabilities,\n });\n\n const { sessionId } = browser;\n\n const sessionMetadata: SessionMetadata = {\n type: 'browser',\n capabilities,\n isAttached: true,\n provider: 'local',\n };\n\n registerSession(sessionId, browser, sessionMetadata, {\n sessionId,\n type: 'browser',\n startedAt: new Date().toISOString(),\n capabilities,\n steps: [],\n });\n\n if (navigationUrl) {\n await browser.url(navigationUrl);\n } else if (activeTabUrl) {\n await restoreAndSwitchToActiveTab(browser, activeTabUrl, allTabUrls);\n }\n\n const title = await browser.getTitle();\n const url = await browser.getUrl();\n\n return {\n content: [{\n type: 'text',\n text: `Attached to Chrome on ${host}:${port}\\nSession ID: ${sessionId}\\nCurrent page: \"${title}\" (${url})`,\n }],\n };\n}\n\nexport const startSessionTool: ToolCallback = async (args: StartSessionArgs): Promise<CallToolResult> => {\n try {\n if (args.platform === 'browser') {\n if (args.attach) {\n return await attachBrowserSession(args);\n }\n return await startBrowserSession(args);\n }\n return await startMobileSession(args);\n } catch (e) {\n return { isError: true, content: [{ type: 'text', text: `Error starting session: ${e}` }] };\n }\n};\n\nexport const closeSessionTool: ToolCallback = async (args: { detach?: boolean } = {}): Promise<CallToolResult> => {\n try {\n getBrowser();\n const state = getState();\n const sessionId = state.currentSession;\n const metadata = state.sessionMetadata.get(sessionId);\n\n const isAttached = !!metadata?.isAttached;\n const detach = args.detach ?? false;\n\n // Determine if this is a force-close (auto-detached session + explicit close)\n const force = !detach && isAttached;\n\n const effectiveDetach = detach || isAttached;\n await closeSession(sessionId, detach, isAttached, force);\n\n const action = effectiveDetach && !force ? 'detached from' : 'closed';\n const note = detach && !isAttached\n ? '\\nNote: Session will remain active on Appium server.'\n : '';\n\n return {\n content: [{ type: 'text', text: `Session ${sessionId} ${action}${note}` }],\n };\n } catch (e) {\n return { isError: true, content: [{ type: 'text', text: `Error closing session: ${e}` }] };\n }\n};\n","import type { SessionHistory } from '../types/recording';\nimport type { SessionResult } from '../providers/types';\nimport type { SessionMetadata } from './state';\nimport { getState } from './state';\nimport { getProvider } from '../providers/registry';\n\nfunction getSessionResult(history: SessionHistory | undefined): SessionResult {\n const errorStep = history?.steps.find(s => s.status === 'error');\n return errorStep\n ? { status: 'failed', reason: errorStep.error }\n : { status: 'passed' };\n}\n\nexport function handleSessionTransition(newSessionId: string): void {\n const state = getState();\n if (state.currentSession && state.currentSession !== newSessionId) {\n const outgoing = state.sessionHistory.get(state.currentSession);\n if (outgoing) {\n outgoing.steps.push({\n index: outgoing.steps.length + 1,\n tool: '__session_transition__',\n params: { newSessionId },\n status: 'ok',\n durationMs: 0,\n timestamp: new Date().toISOString(),\n });\n outgoing.endedAt = new Date().toISOString();\n }\n }\n}\n\nexport function registerSession(\n sessionId: string,\n browser: WebdriverIO.Browser,\n metadata: SessionMetadata,\n historyEntry: SessionHistory,\n): void {\n const state = getState();\n const oldSessionId = state.currentSession;\n if (oldSessionId && oldSessionId !== sessionId) {\n handleSessionTransition(sessionId);\n }\n state.browsers.set(sessionId, browser);\n state.sessionMetadata.set(sessionId, metadata);\n state.sessionHistory.set(sessionId, historyEntry);\n state.currentSession = sessionId;\n\n // If there was a previous session, terminate it to prevent orphaning\n if (oldSessionId && oldSessionId !== sessionId) {\n const oldBrowser = state.browsers.get(oldSessionId);\n const oldMetadata = state.sessionMetadata.get(oldSessionId);\n if (oldBrowser) {\n // Fire and forget — don't block registration on close\n void (async () => {\n if (oldMetadata?.provider) {\n const oldHistory = state.sessionHistory.get(oldSessionId);\n const provider = getProvider(oldMetadata.provider, oldMetadata.type);\n await provider.onSessionClose?.(oldSessionId, oldMetadata.type, getSessionResult(oldHistory), oldMetadata.tunnelHandle).catch(() => {});\n }\n await oldBrowser.deleteSession().catch(() => {\n // Ignore errors during force-close of orphaned session\n });\n })();\n state.browsers.delete(oldSessionId);\n state.sessionMetadata.delete(oldSessionId);\n }\n }\n}\n\nexport async function closeSession(sessionId: string, detach: boolean, isAttached: boolean, force?: boolean): Promise<void> {\n const state = getState();\n const browser = state.browsers.get(sessionId);\n if (!browser) return;\n\n const history = state.sessionHistory.get(sessionId);\n if (history) {\n history.endedAt = new Date().toISOString();\n }\n\n const metadata = state.sessionMetadata.get(sessionId);\n\n // Terminate the WebDriver session if:\n // - force is true (override), OR\n // - detach is false AND isAttached is false (normal close)\n if (force || (!detach && !isAttached)) {\n if (metadata?.provider) {\n try {\n const provider = getProvider(metadata.provider, metadata.type);\n await provider.onSessionClose?.(sessionId, metadata.type, getSessionResult(history), metadata.tunnelHandle);\n } catch (e) {\n console.error('[WARN] Failed to run provider onSessionClose:', e);\n }\n }\n await browser.deleteSession();\n }\n\n state.browsers.delete(sessionId);\n state.sessionMetadata.delete(sessionId);\n\n // Only clear currentSession if it matches the session being closed\n if (state.currentSession === sessionId) {\n state.currentSession = null;\n }\n}\n","import type { SessionProvider, ConnectionConfig } from './types';\n\nexport type LocalBrowserOptions = {\n browser?: 'chrome' | 'firefox' | 'edge' | 'safari';\n headless?: boolean;\n windowWidth?: number;\n windowHeight?: number;\n capabilities?: Record<string, unknown>;\n};\n\nexport class LocalBrowserProvider implements SessionProvider {\n name = 'local-browser';\n\n getConnectionConfig(_options: Record<string, unknown>): ConnectionConfig {\n return {}; // local — use WebdriverIO defaults\n }\n\n buildCapabilities(options: Record<string, unknown>): Record<string, unknown> {\n const selectedBrowser = (options.browser as string | undefined) ?? 'chrome';\n const headless = (options.headless as boolean | undefined) ?? true;\n const windowWidth = (options.windowWidth as number | undefined) ?? 1920;\n const windowHeight = (options.windowHeight as number | undefined) ?? 1080;\n const userCapabilities = (options.capabilities as Record<string, unknown> | undefined) ?? {};\n\n const headlessSupported = selectedBrowser !== 'safari';\n const effectiveHeadless = headless && headlessSupported;\n\n const chromiumArgs = [\n `--window-size=${windowWidth},${windowHeight}`,\n '--no-sandbox',\n '--disable-search-engine-choice-screen',\n '--disable-infobars',\n '--log-level=3',\n '--use-fake-device-for-media-stream',\n '--use-fake-ui-for-media-stream',\n '--disable-web-security',\n '--allow-running-insecure-content',\n ];\n\n if (effectiveHeadless) {\n chromiumArgs.push('--headless=new');\n chromiumArgs.push('--disable-gpu');\n chromiumArgs.push('--disable-dev-shm-usage');\n }\n\n const firefoxArgs: string[] = [];\n if (effectiveHeadless && selectedBrowser === 'firefox') {\n firefoxArgs.push('-headless');\n }\n\n const capabilities: Record<string, any> = {\n acceptInsecureCerts: true,\n };\n\n switch (selectedBrowser) {\n case 'chrome':\n capabilities.browserName = 'chrome';\n capabilities['goog:chromeOptions'] = { args: chromiumArgs };\n break;\n case 'edge':\n capabilities.browserName = 'msedge';\n capabilities['ms:edgeOptions'] = { args: chromiumArgs };\n break;\n case 'firefox':\n capabilities.browserName = 'firefox';\n if (firefoxArgs.length > 0) {\n capabilities['moz:firefoxOptions'] = { args: firefoxArgs };\n }\n break;\n case 'safari':\n capabilities.browserName = 'safari';\n break;\n }\n\n const mergedCapabilities: Record<string, unknown> = {\n ...capabilities,\n ...userCapabilities,\n 'goog:chromeOptions': this.mergeCapabilityOptions(capabilities['goog:chromeOptions'], userCapabilities['goog:chromeOptions']),\n 'ms:edgeOptions': this.mergeCapabilityOptions(capabilities['ms:edgeOptions'], userCapabilities['ms:edgeOptions']),\n 'moz:firefoxOptions': this.mergeCapabilityOptions(capabilities['moz:firefoxOptions'], userCapabilities['moz:firefoxOptions']),\n };\n\n for (const [key, value] of Object.entries(mergedCapabilities)) {\n if (value === undefined) {\n delete mergedCapabilities[key];\n }\n }\n\n return mergedCapabilities;\n }\n\n getSessionType(_options: Record<string, unknown>): 'browser' {\n return 'browser';\n }\n\n shouldAutoDetach(_options: Record<string, unknown>): boolean {\n return false;\n }\n\n private mergeCapabilityOptions(defaultOptions: unknown, customOptions: unknown): unknown {\n if (!defaultOptions || typeof defaultOptions !== 'object' || !customOptions || typeof customOptions !== 'object') {\n return customOptions ?? defaultOptions;\n }\n\n const defaultRecord = defaultOptions as Record<string, unknown>;\n const customRecord = customOptions as Record<string, unknown>;\n const merged = { ...defaultRecord, ...customRecord };\n if (Array.isArray(defaultRecord.args) || Array.isArray(customRecord.args)) {\n merged.args = [\n ...(Array.isArray(defaultRecord.args) ? defaultRecord.args : []),\n ...(Array.isArray(customRecord.args) ? customRecord.args : []),\n ];\n }\n return merged;\n }\n}\n\nexport const localBrowserProvider = new LocalBrowserProvider();\n","/**\n * Appium server configuration and capability builders\n */\n\nexport interface AppiumServerConfig {\n hostname: string;\n port: number;\n path: string;\n}\n\nexport interface IOSCapabilityOptions {\n deviceName: string;\n platformVersion?: string;\n automationName?: 'XCUITest';\n autoGrantPermissions?: boolean;\n autoAcceptAlerts?: boolean;\n autoDismissAlerts?: boolean;\n udid?: string;\n noReset?: boolean;\n fullReset?: boolean;\n newCommandTimeout?: number;\n\n [key: string]: any;\n}\n\nexport interface AndroidCapabilityOptions {\n deviceName: string;\n platformVersion?: string;\n automationName?: 'UiAutomator2' | 'Espresso';\n autoGrantPermissions?: boolean;\n autoAcceptAlerts?: boolean;\n autoDismissAlerts?: boolean;\n appWaitActivity?: string;\n noReset?: boolean;\n fullReset?: boolean;\n newCommandTimeout?: number;\n\n [key: string]: any;\n}\n\n/**\n * Get Appium server configuration from environment variables or defaults\n */\nexport function getAppiumServerConfig(overrides?: Partial<AppiumServerConfig>): AppiumServerConfig {\n return {\n hostname: overrides?.hostname || process.env.APPIUM_URL || '127.0.0.1',\n port: overrides?.port || Number(process.env.APPIUM_URL_PORT) || 4723,\n path: overrides?.path || process.env.APPIUM_PATH || '/',\n };\n}\n\n/**\n * Build iOS capabilities for Appium session\n */\nexport function buildIOSCapabilities(\n appPath: string | undefined,\n options: IOSCapabilityOptions,\n): Record<string, any> {\n const capabilities: Record<string, any> = {\n platformName: 'iOS',\n 'appium:platformVersion': options.platformVersion,\n 'appium:deviceName': options.deviceName,\n 'appium:automationName': options.automationName || 'XCUITest',\n };\n\n // Only set app path if provided (allows connecting to already-running app)\n if (appPath) {\n capabilities['appium:app'] = appPath;\n }\n\n // Set UDID for real device testing (required for physical iOS devices)\n if (options.udid) {\n capabilities['appium:udid'] = options.udid;\n }\n\n // Set reset behavior (for preserving app state)\n if (options.noReset !== undefined) {\n capabilities['appium:noReset'] = options.noReset;\n }\n if (options.fullReset !== undefined) {\n capabilities['appium:fullReset'] = options.fullReset;\n }\n\n // Set session timeout (how long Appium waits for new commands)\n if (options.newCommandTimeout !== undefined) {\n capabilities['appium:newCommandTimeout'] = options.newCommandTimeout;\n }\n\n capabilities['appium:autoGrantPermissions'] = options.autoGrantPermissions ?? true;\n capabilities['appium:autoAcceptAlerts'] = options.autoAcceptAlerts ?? true;\n\n if (options.autoDismissAlerts !== undefined) {\n capabilities['appium:autoDismissAlerts'] = options.autoDismissAlerts;\n capabilities['appium:autoAcceptAlerts'] = undefined;\n }\n\n // Add any additional custom options\n for (const [key, value] of Object.entries(options)) {\n if (\n !['deviceName', 'platformVersion', 'automationName', 'autoGrantPermissions', 'autoAcceptAlerts', 'autoDismissAlerts', 'udid', 'noReset', 'fullReset', 'newCommandTimeout'].includes(\n key,\n )\n ) {\n capabilities[`appium:${key}`] = value;\n }\n }\n\n return capabilities;\n}\n\n/**\n * Build Android capabilities for Appium session\n */\nexport function buildAndroidCapabilities(\n appPath: string | undefined,\n options: AndroidCapabilityOptions,\n): Record<string, any> {\n const capabilities: Record<string, any> = {\n platformName: 'Android',\n 'appium:platformVersion': options.platformVersion,\n 'appium:deviceName': options.deviceName,\n 'appium:automationName': options.automationName || 'UiAutomator2',\n };\n\n // Only set app path if provided (allows connecting to already-running app)\n if (appPath) {\n capabilities['appium:app'] = appPath;\n }\n\n // Set reset behavior (for preserving app state)\n if (options.noReset !== undefined) {\n capabilities['appium:noReset'] = options.noReset;\n }\n if (options.fullReset !== undefined) {\n capabilities['appium:fullReset'] = options.fullReset;\n }\n\n // Set session timeout (how long Appium waits for new commands)\n if (options.newCommandTimeout !== undefined) {\n capabilities['appium:newCommandTimeout'] = options.newCommandTimeout;\n }\n\n // Optional Android-specific settings\n capabilities['appium:autoGrantPermissions'] = options.autoGrantPermissions ?? true;\n capabilities['appium:autoAcceptAlerts'] = options.autoAcceptAlerts ?? true;\n\n if (options.autoDismissAlerts !== undefined) {\n capabilities['appium:autoDismissAlerts'] = options.autoDismissAlerts;\n capabilities['appium:autoAcceptAlerts'] = undefined;\n }\n\n if (options.appWaitActivity) {\n capabilities['appium:appWaitActivity'] = options.appWaitActivity;\n }\n\n // Add any additional custom options\n for (const [key, value] of Object.entries(options)) {\n if (\n !['deviceName', 'platformVersion', 'automationName', 'autoGrantPermissions', 'autoAcceptAlerts', 'autoDismissAlerts', 'appWaitActivity', 'noReset', 'fullReset', 'newCommandTimeout'].includes(\n key,\n )\n ) {\n capabilities[`appium:${key}`] = value;\n }\n }\n\n return capabilities;\n}\n","import type { SessionProvider, ConnectionConfig } from './types';\nimport { buildIOSCapabilities, buildAndroidCapabilities, getAppiumServerConfig } from '../config/appium.config';\n\nexport type LocalAppiumOptions = {\n platform: 'iOS' | 'Android';\n appPath?: string;\n deviceName: string;\n platformVersion?: string;\n automationName?: string;\n appiumConfig?: { host?: string; port?: number; path?: string };\n autoGrantPermissions?: boolean;\n autoAcceptAlerts?: boolean;\n autoDismissAlerts?: boolean;\n appWaitActivity?: string;\n udid?: string;\n noReset?: boolean;\n fullReset?: boolean;\n newCommandTimeout?: number;\n capabilities?: Record<string, unknown>;\n};\n\nexport class LocalAppiumProvider implements SessionProvider {\n name = 'local-appium';\n\n getConnectionConfig(options: Record<string, unknown>): ConnectionConfig {\n const appiumConfig = options.appiumConfig as { host?: string; port?: number; path?: string } | undefined;\n const config = getAppiumServerConfig({\n hostname: appiumConfig?.host,\n port: appiumConfig?.port,\n path: appiumConfig?.path,\n });\n return { protocol: 'http', ...config };\n }\n\n buildCapabilities(options: Record<string, unknown>): Record<string, unknown> {\n const platform = options.platform as string;\n const appPath = options.appPath as string | undefined;\n const deviceName = options.deviceName as string;\n const platformVersion = options.platformVersion as string | undefined;\n const autoGrantPermissions = options.autoGrantPermissions as boolean | undefined;\n const autoAcceptAlerts = options.autoAcceptAlerts as boolean | undefined;\n const autoDismissAlerts = options.autoDismissAlerts as boolean | undefined;\n const udid = options.udid as string | undefined;\n const noReset = options.noReset as boolean | undefined;\n const fullReset = options.fullReset as boolean | undefined;\n const newCommandTimeout = options.newCommandTimeout as number | undefined;\n const appWaitActivity = options.appWaitActivity as string | undefined;\n const userCapabilities = (options.capabilities as Record<string, unknown> | undefined) ?? {};\n\n const capabilities: Record<string, any> = platform === 'iOS'\n ? buildIOSCapabilities(appPath, {\n deviceName,\n platformVersion,\n automationName: (options.automationName as 'XCUITest') || 'XCUITest',\n autoGrantPermissions,\n autoAcceptAlerts,\n autoDismissAlerts,\n udid,\n noReset,\n fullReset,\n newCommandTimeout,\n })\n : buildAndroidCapabilities(appPath, {\n deviceName,\n platformVersion,\n automationName: (options.automationName as 'UiAutomator2' | 'Espresso') || 'UiAutomator2',\n autoGrantPermissions,\n autoAcceptAlerts,\n autoDismissAlerts,\n appWaitActivity,\n noReset,\n fullReset,\n newCommandTimeout,\n });\n\n const mergedCapabilities = {\n ...capabilities,\n ...userCapabilities,\n };\n\n for (const [key, value] of Object.entries(mergedCapabilities)) {\n if (value === undefined) {\n delete mergedCapabilities[key];\n }\n }\n\n return mergedCapabilities;\n }\n\n getSessionType(options: Record<string, unknown>): 'ios' | 'android' {\n const platform = options.platform as string;\n return platform.toLowerCase() as 'ios' | 'android';\n }\n\n shouldAutoDetach(options: Record<string, unknown>): boolean {\n return options.noReset === true || !options.appPath;\n }\n}\n\nexport const localAppiumProvider = new LocalAppiumProvider();\n","import { promisify } from 'node:util';\nimport { Local as BrowserstackTunnel } from 'browserstack-local';\nimport type { ConnectionConfig, SessionProvider, SessionResult } from '../types';\n\nexport class BrowserStackProvider implements SessionProvider {\n name = 'browserstack';\n\n getConnectionConfig(_options: Record<string, unknown>): ConnectionConfig {\n return {\n protocol: 'https',\n hostname: 'hub.browserstack.com',\n port: 443,\n path: '/wd/hub',\n user: process.env.BROWSERSTACK_USERNAME,\n key: process.env.BROWSERSTACK_ACCESS_KEY,\n };\n }\n\n buildCapabilities(options: Record<string, unknown>): Record<string, unknown> {\n const platform = options.platform as string;\n const userCapabilities = (options.capabilities as Record<string, unknown> | undefined) ?? {};\n\n const browserstackLocal = options.browserstackLocal as boolean | undefined;\n\n if (platform === 'browser') {\n const bstackOptions: Record<string, unknown> = {\n browserVersion: (options.browserVersion as string | undefined) ?? 'latest',\n };\n if (options.os) bstackOptions.os = options.os;\n if (options.osVersion) bstackOptions.osVersion = options.osVersion;\n if (browserstackLocal) bstackOptions.local = true;\n\n const reporting = options.reporting as { project?: string; build?: string; session?: string } | undefined;\n\n if (reporting?.project) bstackOptions.projectName = reporting.project;\n if (reporting?.build) bstackOptions.buildName = reporting.build;\n if (reporting?.session) bstackOptions.sessionName = reporting.session;\n\n return {\n browserName: (options.browser as string | undefined) ?? 'chrome',\n 'bstack:options': bstackOptions,\n ...userCapabilities,\n };\n }\n\n // Mobile (ios / android)\n const bstackOptions: Record<string, unknown> = {\n platformName: platform,\n deviceName: options.deviceName,\n platformVersion: options.platformVersion,\n deviceType: 'phone',\n appiumVersion: '3.1.0',\n };\n if (browserstackLocal) bstackOptions.local = true;\n const reporting = options.reporting as { project?: string; build?: string; session?: string } | undefined;\n if (reporting?.project) bstackOptions.projectName = reporting.project;\n if (reporting?.build) bstackOptions.buildName = reporting.build;\n if (reporting?.session) bstackOptions.sessionName = reporting.session;\n\n const autoAcceptAlerts = options.autoAcceptAlerts as boolean | undefined;\n const autoDismissAlerts = options.autoDismissAlerts as boolean | undefined;\n\n return {\n platformName: platform,\n 'appium:app': options.app,\n 'appium:autoGrantPermissions': (options.autoGrantPermissions as boolean | undefined) ?? true,\n 'appium:autoAcceptAlerts': autoDismissAlerts ? undefined : (autoAcceptAlerts ?? true),\n 'appium:autoDismissAlerts': autoDismissAlerts,\n 'appium:newCommandTimeout': (options.newCommandTimeout as number | undefined) ?? 300,\n 'bstack:options': bstackOptions,\n ...userCapabilities,\n };\n }\n\n getSessionType(options: Record<string, unknown>): 'browser' | 'ios' | 'android' {\n const platform = options.platform as string;\n if (platform === 'browser') return 'browser';\n return platform as 'ios' | 'android';\n }\n\n shouldAutoDetach(_options: Record<string, unknown>): boolean {\n return false;\n }\n\n async startTunnel(_options: Record<string, unknown>): Promise<unknown> {\n const key = process.env.BROWSERSTACK_ACCESS_KEY ?? '';\n const tunnel = new BrowserstackTunnel();\n const start = promisify(tunnel.start.bind(tunnel));\n try {\n await start({ key });\n } catch (e: unknown) {\n const msg = e instanceof Error ? e.message : String(e);\n if (msg.includes('another browserstack local client is running') || msg.includes('server is listening on port')) {\n console.error('[BrowserStack] Tunnel already running — reusing existing tunnel');\n return null;\n }\n throw e;\n }\n return tunnel;\n }\n\n async onSessionClose(\n sessionId: string,\n sessionType: 'browser' | 'ios' | 'android',\n result: SessionResult,\n tunnelHandle?: unknown,\n ): Promise<void> {\n if (tunnelHandle) {\n const tunnel = tunnelHandle as InstanceType<typeof BrowserstackTunnel>;\n const stop = promisify(tunnel.stop.bind(tunnel));\n await stop();\n }\n\n const user = process.env.BROWSERSTACK_USERNAME;\n const key = process.env.BROWSERSTACK_ACCESS_KEY;\n if (!user || !key) return;\n\n const baseUrl = sessionType === 'browser'\n ? 'https://api.browserstack.com/automate/sessions'\n : 'https://api-cloud.browserstack.com/app-automate/sessions';\n\n const auth = Buffer.from(`${user}:${key}`).toString('base64');\n const body: Record<string, string> = { status: result.status, ...(result.reason ? { reason: result.reason } : {}) };\n await fetch(`${baseUrl}/${sessionId}.json`, {\n method: 'PUT',\n headers: { Authorization: `Basic ${auth}`, 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n }\n}\n\nexport const browserStackProvider = new BrowserStackProvider();\n","import type { SessionProvider } from './types';\nimport { localBrowserProvider } from './local-browser.provider';\nimport { localAppiumProvider } from './local-appium.provider';\nimport { browserStackProvider } from './cloud/browserstack.provider';\n\nexport function getProvider(providerName: string, platform: string): SessionProvider {\n if (providerName === 'browserstack') return browserStackProvider;\n return platform === 'browser' ? localBrowserProvider : localAppiumProvider;\n}\n","import type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ToolDefinition } from '../types/tool';\nimport { z } from 'zod';\nimport { getBrowser } from '../session/state';\n\nexport const switchTabToolDefinition: ToolDefinition = {\n name: 'switch_tab',\n description: 'switches to a browser tab by handle or index',\n inputSchema: {\n handle: z.string().optional().describe('Window handle to switch to'),\n index: z.number().int().min(0).optional().describe('0-based tab index to switch to'),\n },\n};\n\nexport const switchTabTool: ToolCallback = async ({ handle, index }: { handle?: string; index?: number }): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n if (handle) {\n await browser.switchToWindow(handle);\n return { content: [{ type: 'text', text: `Switched to tab: ${handle}` }] };\n } else if (index !== undefined) {\n const handles = await browser.getWindowHandles();\n if (index >= handles.length) {\n return { isError: true, content: [{ type: 'text', text: `Error: index ${index} out of range (${handles.length} tabs)` }] };\n }\n await browser.switchToWindow(handles[index]);\n return { content: [{ type: 'text', text: `Switched to tab ${index}: ${handles[index]}` }] };\n }\n return { isError: true, content: [{ type: 'text', text: 'Error: Must provide either handle or index' }] };\n } catch (e) {\n return { isError: true, content: [{ type: 'text', text: `Error switching tab: ${e}` }] };\n }\n};","import { existsSync, createReadStream } from 'node:fs';\nimport { z } from 'zod';\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ToolDefinition } from '../types/tool';\nimport { coerceBoolean } from '../utils/zod-helpers';\n\nconst BS_API = 'https://api-cloud.browserstack.com';\n\nfunction getAuth(): string | null {\n const user = process.env.BROWSERSTACK_USERNAME;\n const key = process.env.BROWSERSTACK_ACCESS_KEY;\n if (!user || !key) return null;\n return Buffer.from(`${user}:${key}`).toString('base64');\n}\n\nexport interface BrowserStackApp {\n app_name: string;\n app_version: string;\n app_url: string;\n app_id: string;\n custom_id?: string;\n uploaded_at: string;\n}\n\nfunction formatAppList(apps: BrowserStackApp[]): string {\n if (apps.length === 0) return 'No apps found.';\n return apps.map((a) => {\n const id = a.custom_id ? ` [${a.custom_id}]` : '';\n return `${a.app_name} v${a.app_version}${id} — ${a.app_url} (${a.uploaded_at})`;\n }).join('\\n');\n}\n\n// ─── list_apps ───────────────────────────────────────────────────────────────\n\nexport const listAppsToolDefinition: ToolDefinition = {\n name: 'list_apps',\n description: 'List apps uploaded to BrowserStack App Automate. Reads BROWSERSTACK_USERNAME and BROWSERSTACK_ACCESS_KEY from environment.',\n inputSchema: {\n sortBy: z.enum(['app_name', 'uploaded_at']).optional().default('uploaded_at').describe('Sort order for results'),\n organizationWide: coerceBoolean.optional().default(false).describe('List apps uploaded by all users in the organization (uses recent_group_apps endpoint). Defaults to false (own uploads only).'),\n limit: z.number().int().min(1).optional().default(20).describe('Maximum number of apps to return (only applies when organizationWide is true, default 20)'),\n },\n};\n\nexport const listAppsTool: ToolCallback = async ({ sortBy = 'uploaded_at', organizationWide = false, limit = 20 }: { sortBy?: 'app_name' | 'uploaded_at'; organizationWide?: boolean; limit?: number }) => {\n const auth = getAuth();\n if (!auth) {\n return { isError: true as const, content: [{ type: 'text' as const, text: 'Missing credentials: set BROWSERSTACK_USERNAME and BROWSERSTACK_ACCESS_KEY environment variables.' }] };\n }\n\n try {\n let url = `${BS_API}/app-automate/${organizationWide ? 'recent_group_apps' : 'recent_apps'}`;\n if (organizationWide && limit) url += `?limit=${limit}`;\n\n const res = await fetch(url, {\n headers: { Authorization: `Basic ${auth}` },\n });\n\n if (!res.ok) {\n const body = await res.text();\n return { isError: true as const, content: [{ type: 'text' as const, text: `BrowserStack API error ${res.status}: ${body}` }] };\n }\n\n const raw = await res.json();\n let apps: BrowserStackApp[] = Array.isArray(raw) ? raw : [];\n\n apps = sortBy === 'app_name' ? apps.sort((a, b) => a.app_name.localeCompare(b.app_name)) : apps.sort((a, b) => new Date(b.uploaded_at).getTime() - new Date(a.uploaded_at).getTime());\n\n return { content: [{ type: 'text' as const, text: formatAppList(apps) }] };\n } catch (e) {\n return { isError: true as const, content: [{ type: 'text' as const, text: `Error listing apps: ${e}` }] };\n }\n};\n\n// ─── upload_app ──────────────────────────────────────────────────────────────\n\nexport const uploadAppToolDefinition: ToolDefinition = {\n name: 'upload_app',\n description: 'Upload a local .apk or .ipa to BrowserStack App Automate. Returns a bs:// URL for use in start_session.',\n inputSchema: {\n path: z.string().describe('Absolute path to the .apk or .ipa file'),\n customId: z.string().optional().describe('Optional custom ID for the app (used to reference it later)'),\n },\n};\n\nexport const uploadAppTool: ToolCallback = async ({ path, customId }: { path: string; customId?: string }) => {\n const auth = getAuth();\n if (!auth) {\n return { isError: true as const, content: [{ type: 'text' as const, text: 'Missing credentials: set BROWSERSTACK_USERNAME and BROWSERSTACK_ACCESS_KEY environment variables.' }] };\n }\n\n if (!existsSync(path)) {\n return { isError: true as const, content: [{ type: 'text' as const, text: `File not found: ${path}` }] };\n }\n\n try {\n const form = new FormData();\n const stream = createReadStream(path);\n const fileName = path.split('/').pop() ?? 'app';\n form.append('file', new Blob([stream as unknown as BlobPart]), fileName);\n if (customId) form.append('custom_id', customId);\n\n const res = await fetch(`${BS_API}/app-automate/upload`, {\n method: 'POST',\n headers: { Authorization: `Basic ${auth}` },\n body: form,\n });\n\n if (!res.ok) {\n const body = await res.text();\n return { isError: true as const, content: [{ type: 'text' as const, text: `Upload failed ${res.status}: ${body}` }] };\n }\n\n const data = await res.json() as { app_url: string; custom_id?: string };\n const customIdNote = data.custom_id ? `\\nCustom ID: ${data.custom_id}` : '';\n return { content: [{ type: 'text' as const, text: `Upload successful.\\nApp URL: ${data.app_url}${customIdNote}\\n\\nUse this URL as the \"app\" parameter in start_session with provider: \"browserstack\".` }] };\n } catch (e) {\n return { isError: true as const, content: [{ type: 'text' as const, text: `Error uploading app: ${e}` }] };\n }\n};\n"],"mappings":"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","names":["z","z","z","z","defaultTimeout","z","z","state","z","z","getBrowser","z","z","z","z","z","platform","xpath","platform","platform","platform","z","z","z","z","state","state","platform","platform","encode","getState","encode","state","ResourceTemplate","state","z","platform","platform","bstackOptions","reporting","platform","state","z","waitForCDP","platform","state","z","existsSync","z","z","existsSync"]}
1
+ {"version":3,"sources":["../src/session/state.ts","../package.json","../src/server.ts","../src/tools/navigate.tool.ts","../src/tools/click.tool.ts","../src/utils/zod-helpers.ts","../src/tools/set-value.tool.ts","../src/tools/scroll.tool.ts","../src/tools/cookies.tool.ts","../src/tools/gestures.tool.ts","../src/tools/context.tool.ts","../src/tools/device.tool.ts","../src/tools/execute-script.tool.ts","../src/tools/get-elements.tool.ts","../src/scripts/get-interactable-browser-elements.ts","../src/locators/constants.ts","../src/locators/xml-parsing.ts","../src/locators/element-filter.ts","../src/locators/locator-generation.ts","../src/locators/index.ts","../src/scripts/get-visible-mobile-elements.ts","../src/scripts/get-elements.ts","../src/tools/launch-chrome.tool.ts","../src/tools/emulate-device.tool.ts","../src/recording/step-recorder.ts","../src/resources/browserstack-local.resource.ts","../src/resources/sessions.resource.ts","../src/recording/code-generator.ts","../src/resources/capabilities.resource.ts","../src/resources/elements.resource.ts","../src/resources/accessibility.resource.ts","../src/scripts/get-browser-accessibility-tree.ts","../src/resources/screenshot.resource.ts","../src/resources/cookies.resource.ts","../src/resources/app-state.resource.ts","../src/resources/contexts.resource.ts","../src/resources/geolocation.resource.ts","../src/resources/tabs.resource.ts","../src/tools/session.tool.ts","../src/session/lifecycle.ts","../src/providers/local-browser.provider.ts","../src/config/appium.config.ts","../src/providers/local-appium.provider.ts","../src/providers/cloud/browserstack.provider.ts","../src/providers/registry.ts","../src/tools/tabs.tool.ts","../src/tools/browserstack.tool.ts"],"sourcesContent":["import type { SessionHistory } from '../types/recording';\n\nexport interface SessionMetadata {\n type: 'browser' | 'ios' | 'android';\n capabilities: Record<string, unknown>;\n isAttached: boolean;\n provider?: 'local' | 'browserstack';\n tunnelHandle?: unknown;\n}\n\nconst state = {\n browsers: new Map<string, WebdriverIO.Browser>(),\n currentSession: null as string | null,\n sessionMetadata: new Map<string, SessionMetadata>(),\n sessionHistory: new Map<string, SessionHistory>(),\n};\n\nexport function getBrowser(): WebdriverIO.Browser {\n const browser = state.browsers.get(state.currentSession);\n if (!browser) {\n throw new Error('No active browser session');\n }\n return browser;\n}\n\nexport function getState() {\n return state;\n}\n","{\n \"name\": \"@wdio/mcp\",\n \"mcpName\": \"io.github.webdriverio/mcp\",\n \"author\": \"Vince Graics\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git://github.com/webdriverio/mcp.git\"\n },\n \"version\": \"3.2.0\",\n \"description\": \"MCP server with WebdriverIO for browser and mobile app automation (iOS/Android via Appium)\",\n \"main\": \"./lib/server.js\",\n \"module\": \"./lib/server.js\",\n \"types\": \"./lib/server.d.ts\",\n \"exports\": {\n \".\": {\n \"import\": \"./lib/server.js\",\n \"types\": \"./lib/server.d.ts\"\n },\n \"./snapshot\": {\n \"import\": \"./lib/snapshot.js\",\n \"types\": \"./lib/snapshot.d.ts\"\n }\n },\n \"bin\": {\n \"wdio-mcp\": \"lib/server.js\"\n },\n \"license\": \"MIT\",\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"type\": \"module\",\n \"files\": [\n \"lib\",\n \"README.md\"\n ],\n \"scripts\": {\n \"prebundle\": \"rimraf lib --glob ./*.tgz\",\n \"bundle\": \"tsup && shx chmod +x lib/server.js\",\n \"postbundle\": \"npm pack\",\n \"lint\": \"eslint src/ tests/ --fix && tsc --noEmit\",\n \"start\": \"node lib/server.js\",\n \"dev\": \"tsx --watch src/server.ts\",\n \"prepare\": \"husky\",\n \"test\": \"vitest run\"\n },\n \"dependencies\": {\n \"@modelcontextprotocol/sdk\": \"^1.27.1\",\n \"@toon-format/toon\": \"^2.1.0\",\n \"@wdio/protocols\": \"^9.27.0\",\n \"@xmldom/xmldom\": \"^0.8.12\",\n \"browserstack-local\": \"^1.5.12\",\n \"puppeteer-core\": \"^24.40.0\",\n \"sharp\": \"^0.34.5\",\n \"webdriverio\": \"^9.27.0\",\n \"xpath\": \"^0.0.34\",\n \"zod\": \"^4.3.6\"\n },\n \"devDependencies\": {\n \"@release-it/conventional-changelog\": \"^10.0.6\",\n \"@types/node\": \"^20.19.37\",\n \"@wdio/eslint\": \"^0.1.3\",\n \"@wdio/types\": \"^9.27.0\",\n \"eslint\": \"^9.39.4\",\n \"happy-dom\": \"^20.8.9\",\n \"husky\": \"^9.1.7\",\n \"release-it\": \"^19.2.4\",\n \"rimraf\": \"^6.1.3\",\n \"shx\": \"^0.4.0\",\n \"tsup\": \"^8.5.1\",\n \"tsx\": \"^4.21.0\",\n \"typescript\": \"~5.9.3\",\n \"vitest\": \"^4.1.2\"\n },\n \"packageManager\": \"pnpm@10.32.1\"\n}\n","#!/usr/bin/env node\nimport pkg from '../package.json' with { type: 'json' };\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport type { ToolDefinition } from './types/tool';\nimport type { ResourceDefinition } from './types/resource';\nimport { navigateTool, navigateToolDefinition } from './tools/navigate.tool';\nimport { clickTool, clickToolDefinition } from './tools/click.tool';\nimport { setValueTool, setValueToolDefinition } from './tools/set-value.tool';\nimport { scrollTool, scrollToolDefinition } from './tools/scroll.tool';\nimport {\n deleteCookiesTool,\n deleteCookiesToolDefinition,\n setCookieTool,\n setCookieToolDefinition,\n} from './tools/cookies.tool';\nimport {\n dragAndDropTool,\n dragAndDropToolDefinition,\n swipeTool,\n swipeToolDefinition,\n tapElementTool,\n tapElementToolDefinition,\n} from './tools/gestures.tool';\nimport { switchContextTool, switchContextToolDefinition } from './tools/context.tool';\nimport {\n hideKeyboardTool,\n hideKeyboardToolDefinition,\n rotateDeviceTool,\n rotateDeviceToolDefinition,\n setGeolocationTool,\n setGeolocationToolDefinition,\n} from './tools/device.tool';\nimport { executeScriptTool, executeScriptToolDefinition } from './tools/execute-script.tool';\nimport { getElementsTool, getElementsToolDefinition } from './tools/get-elements.tool';\nimport { launchChromeTool, launchChromeToolDefinition } from './tools/launch-chrome.tool';\nimport { emulateDeviceTool, emulateDeviceToolDefinition } from './tools/emulate-device.tool';\nimport { withRecording } from './recording/step-recorder';\nimport {\n accessibilityResource,\n appStateResource,\n browserstackLocalBinaryResource,\n capabilitiesResource,\n contextResource,\n contextsResource,\n cookiesResource,\n elementsResource,\n geolocationResource,\n screenshotResource,\n sessionCodeResource,\n sessionCurrentCodeResource,\n sessionCurrentStepsResource,\n sessionsIndexResource,\n sessionStepsResource,\n tabsResource,\n} from './resources';\nimport {\n closeSessionTool,\n closeSessionToolDefinition,\n startSessionTool,\n startSessionToolDefinition\n} from './tools/session.tool';\nimport { switchTabTool, switchTabToolDefinition } from './tools/tabs.tool';\nimport {\n listAppsTool,\n listAppsToolDefinition,\n uploadAppTool,\n uploadAppToolDefinition,\n} from './tools/browserstack.tool';\n\nconsole.log = (...args) => console.error('[LOG]', ...args);\nconsole.info = (...args) => console.error('[INFO]', ...args);\nconsole.warn = (...args) => console.error('[WARN]', ...args);\nconsole.debug = (...args) => console.error('[DEBUG]', ...args);\n\nconst server = new McpServer({\n title: 'WebdriverIO MCP Server',\n name: pkg.name,\n version: pkg.version,\n description: pkg.description,\n websiteUrl: 'https://github.com/webdriverio/mcp',\n}, {\n instructions: 'MCP server for browser and mobile app automation using WebDriverIO. Supports Chrome, Firefox, Edge, and Safari browser control plus iOS/Android native app testing via Appium.',\n capabilities: {\n tools: {},\n resources: {},\n },\n});\n\nconst registerTool = (definition: ToolDefinition, callback: ToolCallback) =>\n server.registerTool(definition.name, {\n description: definition.description,\n inputSchema: definition.inputSchema,\n }, callback);\n\nconst registerResource = (definition: ResourceDefinition) => {\n if ('uri' in definition) {\n server.registerResource(\n definition.name,\n definition.uri,\n { description: definition.description },\n definition.handler,\n );\n } else {\n server.registerResource(\n definition.name,\n definition.template,\n { description: definition.description },\n definition.handler,\n );\n }\n};\n\nregisterTool(startSessionToolDefinition, withRecording('start_session', startSessionTool));\nregisterTool(closeSessionToolDefinition, closeSessionTool);\nregisterTool(launchChromeToolDefinition, withRecording('launch_chrome', launchChromeTool));\nregisterTool(emulateDeviceToolDefinition, emulateDeviceTool);\nregisterTool(navigateToolDefinition, withRecording('navigate', navigateTool));\n\nregisterTool(switchTabToolDefinition, switchTabTool);\n\nregisterTool(scrollToolDefinition, withRecording('scroll', scrollTool));\n\nregisterTool(clickToolDefinition, withRecording('click_element', clickTool));\nregisterTool(setValueToolDefinition, withRecording('set_value', setValueTool));\n\nregisterTool(setCookieToolDefinition, setCookieTool);\nregisterTool(deleteCookiesToolDefinition, deleteCookiesTool);\n\nregisterTool(tapElementToolDefinition, withRecording('tap_element', tapElementTool));\nregisterTool(swipeToolDefinition, withRecording('swipe', swipeTool));\nregisterTool(dragAndDropToolDefinition, withRecording('drag_and_drop', dragAndDropTool));\n\nregisterTool(switchContextToolDefinition, switchContextTool);\n\nregisterTool(rotateDeviceToolDefinition, rotateDeviceTool);\nregisterTool(hideKeyboardToolDefinition, hideKeyboardTool);\nregisterTool(setGeolocationToolDefinition, setGeolocationTool);\n\nregisterTool(executeScriptToolDefinition, withRecording('execute_script', executeScriptTool));\nregisterTool(getElementsToolDefinition, getElementsTool);\n\nregisterTool(listAppsToolDefinition, listAppsTool);\nregisterTool(uploadAppToolDefinition, uploadAppTool);\n\nregisterResource(sessionsIndexResource);\nregisterResource(sessionCurrentStepsResource);\nregisterResource(sessionCurrentCodeResource);\nregisterResource(sessionStepsResource);\nregisterResource(sessionCodeResource);\n\nregisterResource(browserstackLocalBinaryResource);\nregisterResource(capabilitiesResource);\nregisterResource(elementsResource);\nregisterResource(accessibilityResource);\nregisterResource(screenshotResource);\nregisterResource(cookiesResource);\nregisterResource(appStateResource);\nregisterResource(contextsResource);\nregisterResource(contextResource);\nregisterResource(geolocationResource);\nregisterResource(tabsResource);\n\nasync function main() {\n const transport = new StdioServerTransport();\n await server.connect(transport);\n console.error('WebdriverIO MCP Server running on stdio');\n}\n\nmain().catch((error) => {\n console.error('Fatal error in main():', error);\n process.exit(1);\n});","import { getBrowser } from '../session/state';\nimport { z } from 'zod';\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ToolDefinition } from '../types/tool';\n\nexport const navigateToolDefinition: ToolDefinition = {\n name: 'navigate',\n description: 'navigates to a URL',\n inputSchema: {\n url: z.string().min(1).describe('The URL to navigate to'),\n },\n};\n\nexport const navigateAction = async (url: string): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n await browser.url(url);\n return {\n content: [{ type: 'text', text: `Navigated to ${url}` }],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error navigating: ${e}` }],\n };\n }\n};\n\nexport const navigateTool: ToolCallback = async ({ url }: { url: string }) => navigateAction(url);\n","import { getBrowser } from '../session/state';\nimport { z } from 'zod';\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ToolDefinition } from '../types/tool';\nimport { coerceBoolean } from '../utils/zod-helpers';\n\nconst defaultTimeout: number = 3000;\n\nexport const clickToolDefinition: ToolDefinition = {\n name: 'click_element',\n description: 'clicks an element',\n inputSchema: {\n selector: z.string().describe('Value for the selector, in the form of css selector or xpath (\"button.my-class\" or \"//button[@class=\\'my-class\\']\" or \"button=Exact text with spaces\" or \"a*=Link containing text\")'),\n scrollToView: coerceBoolean.optional().describe('Whether to scroll the element into view before clicking').default(true),\n timeout: z.number().optional().describe('Maximum time to wait for element in milliseconds'),\n },\n};\n\nexport const clickAction = async (selector: string, timeout: number, scrollToView = true): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n await browser.waitUntil(browser.$(selector).isExisting, { timeout });\n if (scrollToView) {\n await browser.$(selector).scrollIntoView({ block: 'center', inline: 'center' });\n }\n await browser.$(selector).click();\n return {\n content: [{ type: 'text', text: `Element clicked (selector: ${selector})` }],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error clicking element: ${e}` }],\n };\n }\n};\n\nexport const clickTool: ToolCallback = async ({ selector, scrollToView, timeout = defaultTimeout }: {\n selector: string;\n scrollToView?: boolean;\n timeout?: number\n}): Promise<CallToolResult> => clickAction(selector, timeout, scrollToView);\n","import { z } from 'zod';\n\nexport const coerceBoolean = z.preprocess((val) => {\n if (typeof val === 'boolean') return val;\n if (typeof val === 'string') {\n if (val === 'false' || val === '0') return false;\n if (val === 'true' || val === '1') return true;\n return Boolean(val);\n }\n return val;\n}, z.boolean());","import { getBrowser } from '../session/state';\nimport { z } from 'zod';\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ToolDefinition } from '../types/tool';\nimport { coerceBoolean } from '../utils/zod-helpers';\n\nconst defaultTimeout: number = 3000;\n\nexport const setValueToolDefinition: ToolDefinition = {\n name: 'set_value',\n description: 'set value to an element, aka typing',\n inputSchema: {\n selector: z.string().describe('Value for the selector, in the form of css selector or xpath (\"button.my-class\" or \"//button[@class=\\'my-class\\']\")'),\n value: z.string().describe('Text to enter into the element'),\n scrollToView: coerceBoolean.optional().describe('Whether to scroll the element into view before typing').default(true),\n timeout: z.number().optional().describe('Maximum time to wait for element in milliseconds'),\n },\n};\n\nexport const setValueAction = async (\n selector: string,\n value: string,\n scrollToView = true,\n timeout = defaultTimeout,\n): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n await browser.waitUntil(browser.$(selector).isExisting, { timeout });\n if (scrollToView) {\n await browser.$(selector).scrollIntoView({ block: 'center', inline: 'center' });\n }\n await browser.$(selector).clearValue();\n await browser.$(selector).setValue(value);\n return {\n content: [{ type: 'text', text: `Text \"${value}\" entered into element` }],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error entering text: ${e}` }],\n };\n }\n};\n\nexport const setValueTool: ToolCallback = async ({ selector, value, scrollToView = true, timeout = defaultTimeout }: {\n selector: string;\n value: string;\n scrollToView?: boolean;\n timeout?: number\n}) => setValueAction(selector, value, scrollToView, timeout);","import { getBrowser, getState } from '../session/state';\nimport { z } from 'zod';\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ToolDefinition } from '../types/tool';\n\nexport const scrollToolDefinition: ToolDefinition = {\n name: 'scroll',\n description: 'scrolls the page by specified pixels (browser only). For mobile, use the swipe tool.',\n inputSchema: {\n direction: z.enum(['up', 'down']).describe('Scroll direction'),\n pixels: z.number().optional().default(500).describe('Number of pixels to scroll'),\n },\n};\n\nexport const scrollAction = async (direction: 'up' | 'down', pixels = 500): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n const state = getState();\n const metadata = state.sessionMetadata.get(state.currentSession);\n const sessionType = metadata?.type;\n\n if (sessionType !== 'browser') {\n throw new Error('scroll only works in browser sessions. For mobile, use the swipe tool.');\n }\n\n const scrollAmount = direction === 'down' ? pixels : -pixels;\n await browser.execute((amount) => {\n window.scrollBy(0, amount);\n }, scrollAmount);\n\n return {\n content: [{ type: 'text', text: `Scrolled ${direction} ${pixels} pixels` }],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error scrolling: ${e}` }],\n };\n }\n};\n\nexport const scrollTool: ToolCallback = async ({ direction, pixels = 500 }: { direction: 'up' | 'down'; pixels?: number }) =>\n scrollAction(direction, pixels);","import type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ToolDefinition } from '../types/tool';\nimport { z } from 'zod';\nimport type { Cookie } from '@wdio/protocols';\nimport { coerceBoolean } from '../utils/zod-helpers';\n\nexport const setCookieToolDefinition: ToolDefinition = {\n name: 'set_cookie',\n description: 'sets a cookie with specified name, value, and optional attributes',\n inputSchema: {\n name: z.string().describe('Cookie name'),\n value: z.string().describe('Cookie value'),\n domain: z.string().optional().describe('Cookie domain (defaults to current domain)'),\n path: z.string().optional().describe('Cookie path (defaults to \"/\")'),\n expiry: z.number().optional().describe('Expiry date as Unix timestamp in seconds'),\n httpOnly: coerceBoolean.optional().describe('HttpOnly flag'),\n secure: coerceBoolean.optional().describe('Secure flag'),\n sameSite: z.enum(['strict', 'lax', 'none']).optional().describe('SameSite attribute'),\n },\n};\n\nexport const setCookieTool: ToolCallback = async ({\n name,\n value,\n domain,\n path = '/',\n expiry,\n httpOnly,\n secure,\n sameSite,\n}: Cookie): Promise<CallToolResult> => {\n try {\n const cookie: Cookie = { name, value, path, domain, expiry, httpOnly, secure, sameSite };\n const { getBrowser } = await import('../session/state');\n const browser = getBrowser();\n await browser.setCookies(cookie);\n\n return {\n content: [{ type: 'text', text: `Cookie \"${name}\" set successfully` }],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error setting cookie: ${e}` }],\n };\n }\n};\n\nexport const deleteCookiesToolDefinition: ToolDefinition = {\n name: 'delete_cookies',\n description: 'deletes all cookies or a specific cookie by name',\n inputSchema: {\n name: z.string().optional().describe('Optional cookie name to delete a specific cookie. If not provided, deletes all cookies'),\n },\n};\n\nexport const deleteCookiesTool: ToolCallback = async ({ name }: { name?: string }): Promise<CallToolResult> => {\n try {\n const { getBrowser } = await import('../session/state');\n const browser = getBrowser();\n\n if (name) {\n await browser.deleteCookies([name]);\n return {\n content: [{ type: 'text', text: `Cookie \"${name}\" deleted successfully` }],\n };\n }\n await browser.deleteCookies();\n return {\n content: [{ type: 'text', text: 'All cookies deleted successfully' }],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error deleting cookies: ${e}` }],\n };\n }\n};","import type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ToolDefinition } from '../types/tool';\nimport { z } from 'zod';\nimport { getBrowser } from '../session/state';\n\n// Tap Tool\nexport const tapElementToolDefinition: ToolDefinition = {\n name: 'tap_element',\n description: 'taps an element by selector or screen coordinates (mobile)',\n inputSchema: {\n selector: z\n .string()\n .optional()\n .describe('Element selector (CSS, XPath, accessibility ID, or UiAutomator)'),\n x: z.number().optional().describe('X coordinate for screen tap (if no selector provided)'),\n y: z.number().optional().describe('Y coordinate for screen tap (if no selector provided)'),\n },\n};\n\nexport const tapAction = async (args: {\n selector?: string;\n x?: number;\n y?: number;\n}): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n const { selector, x, y } = args;\n\n if (selector) {\n const element = await browser.$(selector);\n await element.tap();\n return {\n content: [{ type: 'text', text: `Tapped element: ${selector}` }],\n };\n } else if (x !== undefined && y !== undefined) {\n await browser.tap({ x, y });\n return {\n content: [{ type: 'text', text: `Tapped at coordinates: (${x}, ${y})` }],\n };\n }\n\n return {\n isError: true,\n content: [{ type: 'text', text: 'Error: Must provide either selector or x,y coordinates' }],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error tapping: ${e}` }],\n };\n }\n};\n\nexport const tapElementTool: ToolCallback = async (args: {\n selector?: string;\n x?: number;\n y?: number;\n}): Promise<CallToolResult> => tapAction(args);\n\n// Swipe Tool\nexport const swipeToolDefinition: ToolDefinition = {\n name: 'swipe',\n description: 'performs a swipe gesture in specified direction (mobile)',\n inputSchema: {\n direction: z.enum(['up', 'down', 'left', 'right']).describe('Swipe direction'),\n duration: z\n .number()\n .min(100)\n .max(5000)\n .optional()\n .describe('Swipe duration in milliseconds (default: 500)'),\n percent: z\n .number()\n .min(0)\n .max(1)\n .optional()\n .describe('Percentage of screen to swipe (0-1, default: 0.5 for up/down, 0.95 for left/right)'),\n },\n};\n\n// Map content direction to finger direction (inverted)\n// \"swipe left\" = content moves left = finger moves right\nconst contentToFingerDirection: Record<string, 'up' | 'down' | 'left' | 'right'> = {\n up: 'down',\n down: 'up',\n left: 'right',\n right: 'left',\n};\n\nexport const swipeAction = async (args: {\n direction: 'up' | 'down' | 'left' | 'right';\n duration?: number;\n percent?: number;\n}): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n const { direction, duration, percent } = args;\n\n // Direction-specific defaults: vertical (up/down) = 0.5, horizontal (left/right) = 0.95\n const isVertical = direction === 'up' || direction === 'down';\n const defaultPercent = isVertical ? 0.5 : 0.95;\n const effectivePercent = percent ?? defaultPercent;\n const effectiveDuration = duration ?? 500;\n\n // Convert content direction to finger direction\n const fingerDirection = contentToFingerDirection[direction];\n await browser.swipe({ direction: fingerDirection, duration: effectiveDuration, percent: effectivePercent });\n\n return {\n content: [{ type: 'text', text: `Swiped ${direction}` }],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error swiping: ${e}` }],\n };\n }\n};\n\nexport const swipeTool: ToolCallback = async (args: {\n direction: 'up' | 'down' | 'left' | 'right';\n duration?: number;\n percent?: number;\n}): Promise<CallToolResult> => swipeAction(args);\n\n// Drag and Drop Tool\nexport const dragAndDropToolDefinition: ToolDefinition = {\n name: 'drag_and_drop',\n description: 'drags an element to another element or coordinates (mobile)',\n inputSchema: {\n sourceSelector: z.string().describe('Source element selector to drag'),\n targetSelector: z.string().optional().describe('Target element selector to drop onto'),\n x: z.number().optional().describe('Target X offset (if no targetSelector)'),\n y: z.number().optional().describe('Target Y offset (if no targetSelector)'),\n duration: z.number().min(100).max(5000).optional().describe('Drag duration in milliseconds'),\n },\n};\n\nexport const dragAndDropAction = async (args: {\n sourceSelector: string;\n targetSelector?: string;\n x?: number;\n y?: number;\n duration?: number;\n}): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n const { sourceSelector, targetSelector, x, y, duration } = args;\n\n const sourceElement = await browser.$(sourceSelector);\n\n if (targetSelector) {\n const targetElement = await browser.$(targetSelector);\n await sourceElement.dragAndDrop(targetElement, { duration });\n return {\n content: [{ type: 'text', text: `Dragged ${sourceSelector} to ${targetSelector}` }],\n };\n } else if (x !== undefined && y !== undefined) {\n await sourceElement.dragAndDrop({ x, y }, { duration });\n return {\n content: [{ type: 'text', text: `Dragged ${sourceSelector} by (${x}, ${y})` }],\n };\n }\n\n return {\n isError: true,\n content: [{ type: 'text', text: 'Error: Must provide either targetSelector or x,y coordinates' }],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error dragging: ${e}` }],\n };\n }\n};\n\nexport const dragAndDropTool: ToolCallback = async (args: {\n sourceSelector: string;\n targetSelector?: string;\n x?: number;\n y?: number;\n duration?: number;\n}): Promise<CallToolResult> => dragAndDropAction(args);","import type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ToolDefinition } from '../types/tool';\nimport { z } from 'zod';\nimport { getBrowser } from '../session/state';\n\nexport const switchContextToolDefinition: ToolDefinition = {\n name: 'switch_context',\n description: 'switches between native and webview contexts',\n inputSchema: {\n context: z\n .string()\n .describe(\n 'Context name to switch to (e.g., \"NATIVE_APP\", \"WEBVIEW_com.example.app\", or use index from wdio://session/current/contexts resource)',\n ),\n },\n};\n\nexport const switchContextTool: ToolCallback = async (args: {\n context: string;\n}): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n const { context } = args;\n\n if (/^\\d+$/.test(context)) {\n const contexts = await browser.getContexts();\n const index = Number.parseInt(context, 10) - 1;\n if (index >= 0 && index < contexts.length) {\n const targetContext = contexts[index] as string;\n await browser.switchContext(targetContext);\n return { content: [{ type: 'text', text: `Switched to context: ${targetContext}` }] };\n }\n throw new Error(`Error: Invalid context index ${context}. Available contexts: ${contexts.length}`);\n\n }\n\n await browser.switchContext(context);\n\n return {\n content: [{ type: 'text', text: `Switched to context: ${context}` }],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error switching context: ${e}` }],\n };\n }\n};","import type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ToolDefinition } from '../types/tool';\nimport { z } from 'zod';\nimport { getBrowser } from '../session/state';\n\nexport const hideKeyboardToolDefinition: ToolDefinition = {\n name: 'hide_keyboard',\n description: 'hides the on-screen keyboard',\n inputSchema: {},\n};\n\nexport const rotateDeviceToolDefinition: ToolDefinition = {\n name: 'rotate_device',\n description: 'rotates device to portrait or landscape orientation',\n inputSchema: {\n orientation: z.enum(['PORTRAIT', 'LANDSCAPE']).describe('Device orientation'),\n },\n};\n\nexport const setGeolocationToolDefinition: ToolDefinition = {\n name: 'set_geolocation',\n description: 'sets device geolocation (latitude, longitude, altitude)',\n inputSchema: {\n latitude: z.number().min(-90).max(90).describe('Latitude coordinate'),\n longitude: z.number().min(-180).max(180).describe('Longitude coordinate'),\n altitude: z.number().optional().describe('Altitude in meters (optional)'),\n },\n};\n\nexport const rotateDeviceTool: ToolCallback = async (args: {\n orientation: 'PORTRAIT' | 'LANDSCAPE';\n}): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n const { orientation } = args;\n\n await browser.setOrientation(orientation);\n\n return {\n content: [{ type: 'text', text: `Device rotated to: ${orientation}` }],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error rotating device: ${e}` }],\n };\n }\n};\n\nexport const hideKeyboardTool: ToolCallback = async (): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n\n await browser.hideKeyboard();\n\n return {\n content: [{ type: 'text', text: 'Keyboard hidden' }],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error hiding keyboard: ${e}` }],\n };\n }\n};\n\nexport const setGeolocationTool: ToolCallback = async (args: {\n latitude: number;\n longitude: number;\n altitude?: number;\n}): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n const { latitude, longitude, altitude } = args;\n\n await browser.setGeoLocation({ latitude, longitude, altitude });\n\n return {\n content: [\n {\n type: 'text',\n text: `Geolocation set to:\\n Latitude: ${latitude}\\n Longitude: ${longitude}${altitude ? `\\n Altitude: ${altitude}m` : ''}`,\n },\n ],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error setting geolocation: ${e}` }],\n };\n }\n};","import type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ToolDefinition } from '../types/tool';\nimport { z } from 'zod';\nimport { getBrowser } from '../session/state';\n\nexport const executeScriptToolDefinition: ToolDefinition = {\n name: 'execute_script',\n description: `Executes JavaScript in browser or mobile commands via Appium.\n\n**Option B for browser interaction** — prefer get_visible_elements or click_element/set_value with a selector instead. Use execute_script only when no dedicated tool covers the action (e.g. reading computed values, triggering custom events, scrolling to a position).\n\n**Browser:** Runs JavaScript in page context. Use 'return' to get values back.\n - Example: execute_script({ script: \"return document.title\" })\n - Example: execute_script({ script: \"return window.scrollY\" })\n - Example: execute_script({ script: \"arguments[0].click()\", args: [\"#myButton\"] })\n\n**Mobile (Appium):** Executes mobile-specific commands using 'mobile: <command>' syntax.\n - Press key (Android): execute_script({ script: \"mobile: pressKey\", args: [{ keycode: 4 }] }) // BACK=4, HOME=3\n - Activate app: execute_script({ script: \"mobile: activateApp\", args: [{ appId: \"com.example\" }] })\n - Terminate app: execute_script({ script: \"mobile: terminateApp\", args: [{ appId: \"com.example\" }] })\n - Deep link: execute_script({ script: \"mobile: deepLink\", args: [{ url: \"myapp://screen\", package: \"com.example\" }] })\n - Shell command (Android): execute_script({ script: \"mobile: shell\", args: [{ command: \"dumpsys\", args: [\"battery\"] }] })`,\n inputSchema: {\n script: z.string().describe('JavaScript code (browser) or mobile command string like \"mobile: pressKey\" (Appium)'),\n args: z.array(z.any()).optional().describe('Arguments to pass to the script. For browser: element selectors or values. For mobile commands: command-specific parameters as objects.'),\n },\n};\n\nexport const executeScriptTool: ToolCallback = async (args: {\n script: string;\n args?: unknown[];\n}): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n const { script, args: scriptArgs = [] } = args;\n\n // For browser scripts with selector arguments, resolve them to elements\n const resolvedArgs = await Promise.all(\n scriptArgs.map(async (arg) => {\n // If it's a string that looks like a selector and we're in browser context, try to resolve it\n if (typeof arg === 'string' && !script.startsWith('mobile:')) {\n try {\n const element = await browser.$(arg);\n if (await element.isExisting()) {\n return element;\n }\n } catch {\n // Not a valid selector, pass as-is\n }\n }\n return arg;\n })\n );\n\n const result = await browser.execute(script, ...resolvedArgs);\n\n // Format result for display\n let resultText: string;\n if (result === undefined || result === null) {\n resultText = 'Script executed successfully (no return value)';\n } else if (typeof result === 'object') {\n try {\n resultText = `Result: ${JSON.stringify(result, null, 2)}`;\n } catch {\n resultText = `Result: ${String(result)}`;\n }\n } else {\n resultText = `Result: ${result}`;\n }\n\n return {\n content: [{ type: 'text', text: resultText }],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error executing script: ${e}` }],\n };\n }\n};\n","import { z } from 'zod';\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ToolDefinition } from '../types/tool';\nimport { getBrowser } from '../session/state';\nimport { getElements } from '../scripts/get-elements';\nimport { encode } from '@toon-format/toon';\nimport { coerceBoolean } from '../utils/zod-helpers';\n\nexport const getElementsToolDefinition: ToolDefinition = {\n name: 'get_elements',\n description: 'Get interactable elements on the current page. Use when wdio://session/current/elements does not return the desired elements.',\n inputSchema: {\n inViewportOnly: coerceBoolean.optional().default(false).describe('Only return elements visible in the current viewport (default: false).'),\n includeContainers: coerceBoolean.optional().default(false).describe('Include container elements like divs and sections (default: false)'),\n includeBounds: coerceBoolean.optional().default(false).describe('Include element bounding box coordinates (default: false)'),\n limit: z.number().optional().default(0).describe('Maximum number of elements to return (0 = no limit)'),\n offset: z.number().optional().default(0).describe('Number of elements to skip (for pagination)'),\n },\n};\n\nexport const getElementsTool: ToolCallback = async ({\n inViewportOnly = false,\n includeContainers = false,\n includeBounds = false,\n limit = 0,\n offset = 0,\n}: {\n inViewportOnly?: boolean;\n includeContainers?: boolean;\n includeBounds?: boolean;\n limit?: number;\n offset?: number;\n}) => {\n try {\n const browser = getBrowser();\n const result = await getElements(browser, { inViewportOnly, includeContainers, includeBounds, limit, offset });\n const text = encode(result).replace(/,\"\"/g, ',').replace(/\"\",/g, ',');\n return { content: [{ type: 'text' as const, text }] };\n } catch (e) {\n return { isError: true as const, content: [{ type: 'text' as const, text: `Error getting elements: ${e}` }] };\n }\n};\n","/**\n * Browser element detection\n * Single browser.execute() call: querySelectorAll → flat interactable element list\n *\n * NOTE: This script runs in browser context via browser.execute()\n * It must be self-contained with no external dependencies\n */\n\nexport interface BrowserElementInfo {\n tagName: string;\n name: string; // computed accessible name (ARIA spec)\n type: string;\n value: string;\n href: string;\n selector: string;\n isInViewport: boolean;\n boundingBox?: { x: number; y: number; width: number; height: number };\n}\n\nexport interface GetBrowserElementsOptions {\n includeBounds?: boolean;\n}\n\nconst elementsScript = (includeBounds: boolean) => (function () {\n const interactableSelectors = [\n 'a[href]',\n 'button',\n 'input:not([type=\"hidden\"])',\n 'select',\n 'textarea',\n '[role=\"button\"]',\n '[role=\"link\"]',\n '[role=\"checkbox\"]',\n '[role=\"radio\"]',\n '[role=\"tab\"]',\n '[role=\"menuitem\"]',\n '[role=\"combobox\"]',\n '[role=\"option\"]',\n '[role=\"switch\"]',\n '[role=\"slider\"]',\n '[role=\"textbox\"]',\n '[role=\"searchbox\"]',\n '[role=\"spinbutton\"]',\n '[contenteditable=\"true\"]',\n '[tabindex]:not([tabindex=\"-1\"])',\n ].join(',');\n\n function isVisible(element: HTMLElement): boolean {\n if (typeof element.checkVisibility === 'function') {\n return element.checkVisibility({ opacityProperty: true, visibilityProperty: true, contentVisibilityAuto: true });\n }\n const style = window.getComputedStyle(element);\n return style.display !== 'none' &&\n style.visibility !== 'hidden' &&\n style.opacity !== '0' &&\n element.offsetWidth > 0 &&\n element.offsetHeight > 0;\n }\n\n function getAccessibleName(el: HTMLElement): string {\n // 1. aria-label\n const ariaLabel = el.getAttribute('aria-label');\n if (ariaLabel) return ariaLabel.trim();\n\n // 2. aria-labelledby — resolve referenced elements\n const labelledBy = el.getAttribute('aria-labelledby');\n if (labelledBy) {\n const texts = labelledBy.split(/\\s+/)\n .map(id => document.getElementById(id)?.textContent?.trim() || '')\n .filter(Boolean);\n if (texts.length > 0) return texts.join(' ').slice(0, 100);\n }\n\n const tag = el.tagName.toLowerCase();\n\n // 3. alt for images and input[type=image]\n if (tag === 'img' || (tag === 'input' && el.getAttribute('type') === 'image')) {\n const alt = el.getAttribute('alt');\n if (alt !== null) return alt.trim();\n }\n\n // 4. label[for=id] for form elements\n if (['input', 'select', 'textarea'].includes(tag)) {\n const id = el.getAttribute('id');\n if (id) {\n const label = document.querySelector(`label[for=\"${CSS.escape(id)}\"]`);\n if (label) return label.textContent?.trim() || '';\n }\n // 5. Wrapping label — clone, strip inputs, read text\n const parentLabel = el.closest('label');\n if (parentLabel) {\n const clone = parentLabel.cloneNode(true) as HTMLElement;\n clone.querySelectorAll('input,select,textarea').forEach(n => n.remove());\n const lt = clone.textContent?.trim();\n if (lt) return lt;\n }\n }\n\n // 6. placeholder\n const ph = el.getAttribute('placeholder');\n if (ph) return ph.trim();\n\n // 7. title\n const title = el.getAttribute('title');\n if (title) return title.trim();\n\n // 8. text content (truncated, whitespace normalized)\n return (el.textContent?.trim().replace(/\\s+/g, ' ') || '').slice(0, 100);\n }\n\n function getSelector(element: HTMLElement): string {\n const tag = element.tagName.toLowerCase();\n\n // 1. tag*=Text — best per WebdriverIO docs\n const text = element.textContent?.trim().replace(/\\s+/g, ' ');\n if (text && text.length > 0 && text.length <= 50) {\n const sameTagElements = document.querySelectorAll(tag);\n let matchCount = 0;\n sameTagElements.forEach(el => {\n if (el.textContent?.includes(text)) matchCount++;\n });\n if (matchCount === 1) return `${tag}*=${text}`;\n }\n\n // 2. aria/label\n const ariaLabel = element.getAttribute('aria-label');\n if (ariaLabel && ariaLabel.length <= 80) return `aria/${ariaLabel}`;\n\n // 3. data-testid\n const testId = element.getAttribute('data-testid');\n if (testId) {\n const sel = `[data-testid=\"${CSS.escape(testId)}\"]`;\n if (document.querySelectorAll(sel).length === 1) return sel;\n }\n\n // 4. #id\n if (element.id) return `#${CSS.escape(element.id)}`;\n\n // 5. [name] — form elements\n const nameAttr = element.getAttribute('name');\n if (nameAttr) {\n const sel = `${tag}[name=\"${CSS.escape(nameAttr)}\"]`;\n if (document.querySelectorAll(sel).length === 1) return sel;\n }\n\n // 6. tag.class — try each class individually, then first-two combination\n if (element.className && typeof element.className === 'string') {\n const classes = element.className.trim().split(/\\s+/).filter(Boolean);\n for (const cls of classes) {\n const sel = `${tag}.${CSS.escape(cls)}`;\n if (document.querySelectorAll(sel).length === 1) return sel;\n }\n if (classes.length >= 2) {\n const sel = `${tag}${classes.slice(0, 2).map(c => `.${CSS.escape(c)}`).join('')}`;\n if (document.querySelectorAll(sel).length === 1) return sel;\n }\n }\n\n // 7. CSS path fallback\n let current: HTMLElement | null = element;\n const path: string[] = [];\n while (current && current !== document.documentElement) {\n let seg = current.tagName.toLowerCase();\n if (current.id) {\n path.unshift(`#${CSS.escape(current.id)}`);\n break;\n }\n const parent = current.parentElement;\n if (parent) {\n const siblings = Array.from(parent.children).filter(c => c.tagName === current!.tagName);\n if (siblings.length > 1) seg += `:nth-of-type(${siblings.indexOf(current) + 1})`;\n }\n path.unshift(seg);\n current = current.parentElement;\n if (path.length >= 4) break;\n }\n return path.join(' > ');\n }\n\n const elements: Record<string, unknown>[] = [];\n const seen = new Set<Element>();\n\n document.querySelectorAll(interactableSelectors).forEach((el) => {\n if (seen.has(el)) return;\n seen.add(el);\n\n const htmlEl = el as HTMLElement;\n if (!isVisible(htmlEl)) return;\n\n const inputEl = htmlEl as HTMLInputElement;\n const rect = htmlEl.getBoundingClientRect();\n const isInViewport = (\n rect.top >= 0 &&\n rect.left >= 0 &&\n rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&\n rect.right <= (window.innerWidth || document.documentElement.clientWidth)\n );\n\n const entry: Record<string, unknown> = {\n tagName: htmlEl.tagName.toLowerCase(),\n name: getAccessibleName(htmlEl),\n type: htmlEl.getAttribute('type') || '',\n value: inputEl.value || '',\n href: htmlEl.getAttribute('href') || '',\n selector: getSelector(htmlEl),\n isInViewport,\n };\n\n if (includeBounds) {\n entry.boundingBox = {\n x: rect.x + window.scrollX,\n y: rect.y + window.scrollY,\n width: rect.width,\n height: rect.height,\n };\n }\n\n elements.push(entry);\n });\n\n return elements;\n})();\n\n/**\n * Get interactable browser elements via querySelectorAll.\n */\nexport async function getInteractableBrowserElements(\n browser: WebdriverIO.Browser,\n options: GetBrowserElementsOptions = {},\n): Promise<BrowserElementInfo[]> {\n const { includeBounds = false } = options;\n return (browser as any).execute(elementsScript, includeBounds) as unknown as Promise<BrowserElementInfo[]>;\n}\n\nexport default elementsScript;\n","/**\n * Platform-specific element tag constants for mobile automation\n */\n\nexport const ANDROID_INTERACTABLE_TAGS = [\n // Input elements\n 'android.widget.EditText',\n 'android.widget.AutoCompleteTextView',\n 'android.widget.MultiAutoCompleteTextView',\n 'android.widget.SearchView',\n\n // Button-like elements\n 'android.widget.Button',\n 'android.widget.ImageButton',\n 'android.widget.ToggleButton',\n 'android.widget.CompoundButton',\n 'android.widget.RadioButton',\n 'android.widget.CheckBox',\n 'android.widget.Switch',\n 'android.widget.FloatingActionButton',\n 'com.google.android.material.button.MaterialButton',\n 'com.google.android.material.floatingactionbutton.FloatingActionButton',\n\n // Text elements (often tappable)\n 'android.widget.TextView',\n 'android.widget.CheckedTextView',\n\n // Image elements (often tappable)\n 'android.widget.ImageView',\n 'android.widget.QuickContactBadge',\n\n // Selection elements\n 'android.widget.Spinner',\n 'android.widget.SeekBar',\n 'android.widget.RatingBar',\n 'android.widget.ProgressBar',\n 'android.widget.DatePicker',\n 'android.widget.TimePicker',\n 'android.widget.NumberPicker',\n\n // List/grid items\n 'android.widget.AdapterView',\n];\n\nexport const ANDROID_LAYOUT_CONTAINERS = [\n // Core ViewGroup classes\n 'android.view.ViewGroup',\n 'android.view.View',\n 'android.widget.FrameLayout',\n 'android.widget.LinearLayout',\n 'android.widget.RelativeLayout',\n 'android.widget.GridLayout',\n 'android.widget.TableLayout',\n 'android.widget.TableRow',\n 'android.widget.AbsoluteLayout',\n\n // AndroidX layout classes\n 'androidx.constraintlayout.widget.ConstraintLayout',\n 'androidx.coordinatorlayout.widget.CoordinatorLayout',\n 'androidx.appcompat.widget.LinearLayoutCompat',\n 'androidx.cardview.widget.CardView',\n 'androidx.appcompat.widget.ContentFrameLayout',\n 'androidx.appcompat.widget.FitWindowsFrameLayout',\n\n // Scrolling containers\n 'android.widget.ScrollView',\n 'android.widget.HorizontalScrollView',\n 'android.widget.NestedScrollView',\n 'androidx.core.widget.NestedScrollView',\n 'androidx.recyclerview.widget.RecyclerView',\n 'android.widget.ListView',\n 'android.widget.GridView',\n 'android.widget.AbsListView',\n\n // App chrome / system elements\n 'android.widget.ActionBarContainer',\n 'android.widget.ActionBarOverlayLayout',\n 'android.view.ViewStub',\n 'androidx.appcompat.widget.ActionBarContainer',\n 'androidx.appcompat.widget.ActionBarContextView',\n 'androidx.appcompat.widget.ActionBarOverlayLayout',\n\n // Decor views\n 'com.android.internal.policy.DecorView',\n 'android.widget.DecorView',\n];\n\nexport const IOS_INTERACTABLE_TAGS = [\n // Input elements\n 'XCUIElementTypeTextField',\n 'XCUIElementTypeSecureTextField',\n 'XCUIElementTypeTextView',\n 'XCUIElementTypeSearchField',\n\n // Button-like elements\n 'XCUIElementTypeButton',\n 'XCUIElementTypeLink',\n\n // Text elements (often tappable)\n 'XCUIElementTypeStaticText',\n\n // Image elements\n 'XCUIElementTypeImage',\n 'XCUIElementTypeIcon',\n\n // Selection elements\n 'XCUIElementTypeSwitch',\n 'XCUIElementTypeSlider',\n 'XCUIElementTypeStepper',\n 'XCUIElementTypeSegmentedControl',\n 'XCUIElementTypePicker',\n 'XCUIElementTypePickerWheel',\n 'XCUIElementTypeDatePicker',\n 'XCUIElementTypePageIndicator',\n\n // Table/list items\n 'XCUIElementTypeCell',\n 'XCUIElementTypeMenuItem',\n 'XCUIElementTypeMenuBarItem',\n\n // Toggle elements\n 'XCUIElementTypeCheckBox',\n 'XCUIElementTypeRadioButton',\n 'XCUIElementTypeToggle',\n\n // Other interactive\n 'XCUIElementTypeKey',\n 'XCUIElementTypeKeyboard',\n 'XCUIElementTypeAlert',\n 'XCUIElementTypeSheet',\n];\n\nexport const IOS_LAYOUT_CONTAINERS = [\n // Generic containers\n 'XCUIElementTypeOther',\n 'XCUIElementTypeGroup',\n 'XCUIElementTypeLayoutItem',\n\n // Scroll containers\n 'XCUIElementTypeScrollView',\n 'XCUIElementTypeTable',\n 'XCUIElementTypeCollectionView',\n 'XCUIElementTypeScrollBar',\n\n // Navigation chrome\n 'XCUIElementTypeNavigationBar',\n 'XCUIElementTypeTabBar',\n 'XCUIElementTypeToolbar',\n 'XCUIElementTypeStatusBar',\n 'XCUIElementTypeMenuBar',\n\n // Windows and views\n 'XCUIElementTypeWindow',\n 'XCUIElementTypeSheet',\n 'XCUIElementTypeDrawer',\n 'XCUIElementTypeDialog',\n 'XCUIElementTypePopover',\n 'XCUIElementTypePopUpButton',\n\n // Outline elements\n 'XCUIElementTypeOutline',\n 'XCUIElementTypeOutlineRow',\n 'XCUIElementTypeBrowser',\n 'XCUIElementTypeSplitGroup',\n 'XCUIElementTypeSplitter',\n\n // Application root\n 'XCUIElementTypeApplication',\n];\n","/**\n * XML parsing utilities for mobile element source\n */\n\nimport { DOMParser } from '@xmldom/xmldom';\nimport xpath from 'xpath';\nimport type { ElementAttributes, JSONElement, Bounds, UniquenessResult } from './types';\n\n/**\n * Get child nodes that are elements (not text nodes, comments, etc.)\n */\nfunction childNodesOf(node: Node): Node[] {\n const children: Node[] = [];\n if (node.childNodes) {\n for (let i = 0; i < node.childNodes.length; i++) {\n const child = node.childNodes.item(i);\n if (child?.nodeType === 1) {\n children.push(child);\n }\n }\n }\n return children;\n}\n\n/**\n * Recursively translate DOM node to JSONElement\n */\nfunction translateRecursively(\n domNode: Node,\n parentPath: string = '',\n index: number | null = null,\n): JSONElement {\n const attributes: ElementAttributes = {};\n\n const element = domNode as Element;\n if (element.attributes) {\n for (let attrIdx = 0; attrIdx < element.attributes.length; attrIdx++) {\n const attr = element.attributes.item(attrIdx);\n if (attr) {\n attributes[attr.name] = attr.value.replace(/(\\n)/gm, '\\\\n');\n }\n }\n }\n\n const path = index === null ? '' : `${parentPath ? parentPath + '.' : ''}${index}`;\n\n return {\n children: childNodesOf(domNode).map((childNode, childIndex) =>\n translateRecursively(childNode, path, childIndex),\n ),\n tagName: domNode.nodeName,\n attributes,\n path,\n };\n}\n\n/**\n * Compare two nodes for equality by platform-specific attributes\n * (reference equality via === may fail when nodes come from different traversals)\n */\nfunction isSameElement(node1: Node, node2: Node): boolean {\n if (node1.nodeType !== 1 || node2.nodeType !== 1) return false;\n const el1 = node1 as Element;\n const el2 = node2 as Element;\n\n if (el1.nodeName !== el2.nodeName) return false;\n\n // For Android, compare by bounds (unique per element)\n const bounds1 = el1.getAttribute('bounds');\n const bounds2 = el2.getAttribute('bounds');\n if (bounds1 && bounds2) {\n return bounds1 === bounds2;\n }\n\n // For iOS, compare by x, y, width, height\n const x1 = el1.getAttribute('x');\n const y1 = el1.getAttribute('y');\n const x2 = el2.getAttribute('x');\n const y2 = el2.getAttribute('y');\n if (x1 && y1 && x2 && y2) {\n return (\n x1 === x2 &&\n y1 === y2 &&\n el1.getAttribute('width') === el2.getAttribute('width') &&\n el1.getAttribute('height') === el2.getAttribute('height')\n );\n }\n\n return false;\n}\n\n/**\n * Convert XML page source to JSON tree structure\n */\nexport function xmlToJSON(sourceXML: string): JSONElement | null {\n try {\n const parser = new DOMParser();\n const sourceDoc = parser.parseFromString(sourceXML, 'text/xml');\n\n const parseErrors = sourceDoc.getElementsByTagName('parsererror');\n if (parseErrors.length > 0) {\n console.error('[xmlToJSON] XML parsing error:', parseErrors[0].textContent);\n return null;\n }\n\n const children = childNodesOf(sourceDoc);\n const firstChild =\n children[0] ||\n (sourceDoc.documentElement ? childNodesOf(sourceDoc.documentElement)[0] : null);\n\n return firstChild\n ? translateRecursively(firstChild)\n : { children: [], tagName: '', attributes: {}, path: '' };\n } catch (e) {\n console.error('[xmlToJSON] Failed to parse XML:', e);\n return null;\n }\n}\n\n/**\n * Parse XML source to DOM Document for XPath evaluation\n */\nexport function xmlToDOM(sourceXML: string): Document | null {\n try {\n const parser = new DOMParser();\n const doc = parser.parseFromString(sourceXML, 'text/xml');\n\n const parseErrors = doc.getElementsByTagName('parsererror');\n if (parseErrors.length > 0) {\n console.error('[xmlToDOM] XML parsing error:', parseErrors[0].textContent);\n return null;\n }\n\n return doc;\n } catch (e) {\n console.error('[xmlToDOM] Failed to parse XML:', e);\n return null;\n }\n}\n\n/**\n * Execute XPath query on DOM document\n */\nexport function evaluateXPath(doc: Document, xpathExpr: string): Node[] {\n try {\n const nodes = xpath.select(xpathExpr, doc);\n if (Array.isArray(nodes)) {\n return nodes as Node[];\n }\n return [];\n } catch (e) {\n console.error(`[evaluateXPath] Failed to evaluate \"${xpathExpr}\":`, e);\n return [];\n }\n}\n\n/**\n * Check if an XPath selector is unique and get index if not\n */\nexport function checkXPathUniqueness(\n doc: Document,\n xpathExpr: string,\n targetNode?: Node,\n): UniquenessResult {\n try {\n const nodes = evaluateXPath(doc, xpathExpr);\n const totalMatches = nodes.length;\n\n if (totalMatches === 0) {\n return { isUnique: false };\n }\n\n if (totalMatches === 1) {\n return { isUnique: true };\n }\n\n // Not unique - find index of target node if provided\n if (targetNode) {\n for (let i = 0; i < nodes.length; i++) {\n if (nodes[i] === targetNode || isSameElement(nodes[i], targetNode)) {\n return {\n isUnique: false,\n index: i + 1, // 1-based index for XPath\n totalMatches,\n };\n }\n }\n }\n\n return { isUnique: false, totalMatches };\n } catch (e) {\n console.error(`[checkXPathUniqueness] Error checking \"${xpathExpr}\":`, e);\n return { isUnique: false };\n }\n}\n\n/**\n * Find DOM node by JSONElement path (e.g., \"0.2.1\")\n */\nexport function findDOMNodeByPath(doc: Document, path: string): Node | null {\n if (!path) return doc.documentElement;\n\n const indices = path.split('.').map(Number);\n let current: Node | null = doc.documentElement;\n\n for (const index of indices) {\n if (!current) return null;\n\n const children: Node[] = [];\n if (current.childNodes) {\n for (let i = 0; i < current.childNodes.length; i++) {\n const child = current.childNodes.item(i);\n if (child?.nodeType === 1) {\n children.push(child);\n }\n }\n }\n\n current = children[index] || null;\n }\n\n return current;\n}\n\n/**\n * Parse Android bounds string \"[x1,y1][x2,y2]\" to coordinates\n */\nexport function parseAndroidBounds(bounds: string): Bounds {\n const match = bounds.match(/\\[(\\d+),(\\d+)\\]\\[(\\d+),(\\d+)\\]/);\n if (!match) {\n return { x: 0, y: 0, width: 0, height: 0 };\n }\n\n const x1 = parseInt(match[1], 10);\n const y1 = parseInt(match[2], 10);\n const x2 = parseInt(match[3], 10);\n const y2 = parseInt(match[4], 10);\n\n return {\n x: x1,\n y: y1,\n width: x2 - x1,\n height: y2 - y1,\n };\n}\n\n/**\n * Parse iOS element bounds from individual x, y, width, height attributes\n */\nexport function parseIOSBounds(attributes: ElementAttributes): Bounds {\n return {\n x: parseInt(attributes.x || '0', 10),\n y: parseInt(attributes.y || '0', 10),\n width: parseInt(attributes.width || '0', 10),\n height: parseInt(attributes.height || '0', 10),\n };\n}\n\n/**\n * Flatten JSON element tree to array (depth-first)\n */\nexport function flattenElementTree(root: JSONElement): JSONElement[] {\n const result: JSONElement[] = [];\n\n function traverse(element: JSONElement) {\n result.push(element);\n for (const child of element.children) {\n traverse(child);\n }\n }\n\n traverse(root);\n return result;\n}\n\n/**\n * Count occurrences of an attribute value in the source XML\n */\nexport function countAttributeOccurrences(\n sourceXML: string,\n attribute: string,\n value: string,\n): number {\n const escapedValue = value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const pattern = new RegExp(`${attribute}=[\"']${escapedValue}[\"']`, 'g');\n const matches = sourceXML.match(pattern);\n return matches ? matches.length : 0;\n}\n\n/**\n * Check if an attribute value is unique in the source (fast regex-based check)\n */\nexport function isAttributeUnique(\n sourceXML: string,\n attribute: string,\n value: string,\n): boolean {\n return countAttributeOccurrences(sourceXML, attribute, value) === 1;\n}\n","/**\n * Element filtering logic for mobile automation\n */\n\nimport type { JSONElement, FilterOptions } from './types';\nimport {\n ANDROID_INTERACTABLE_TAGS,\n IOS_INTERACTABLE_TAGS,\n ANDROID_LAYOUT_CONTAINERS,\n IOS_LAYOUT_CONTAINERS,\n} from './constants';\n\n/**\n * Check if element tag matches any in the list (handles partial matches)\n */\nfunction matchesTagList(tagName: string, tagList: string[]): boolean {\n if (tagList.includes(tagName)) {\n return true;\n }\n\n for (const tag of tagList) {\n if (tagName.endsWith(tag) || tagName.includes(tag)) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Check if element matches tag name filters\n */\nfunction matchesTagFilters(\n element: JSONElement,\n includeTagNames: string[],\n excludeTagNames: string[],\n): boolean {\n if (includeTagNames.length > 0 && !matchesTagList(element.tagName, includeTagNames)) {\n return false;\n }\n\n if (matchesTagList(element.tagName, excludeTagNames)) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Check if element matches attribute-based filters\n */\nfunction matchesAttributeFilters(\n element: JSONElement,\n requireAttributes: string[],\n minAttributeCount: number,\n): boolean {\n if (requireAttributes.length > 0) {\n const hasRequiredAttr = requireAttributes.some((attr) => element.attributes?.[attr]);\n if (!hasRequiredAttr) return false;\n }\n\n if (element.attributes && minAttributeCount > 0) {\n const attrCount = Object.values(element.attributes).filter(\n (v) => v !== undefined && v !== null && v !== '',\n ).length;\n if (attrCount < minAttributeCount) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Check if element is interactable based on platform\n */\nexport function isInteractableElement(\n element: JSONElement,\n isNative: boolean,\n automationName: string,\n): boolean {\n const isAndroid = automationName.toLowerCase().includes('uiautomator');\n const interactableTags = isAndroid ? ANDROID_INTERACTABLE_TAGS : IOS_INTERACTABLE_TAGS;\n\n if (matchesTagList(element.tagName, interactableTags)) {\n return true;\n }\n\n if (isAndroid) {\n if (\n element.attributes?.clickable === 'true' ||\n element.attributes?.focusable === 'true' ||\n element.attributes?.checkable === 'true' ||\n element.attributes?.['long-clickable'] === 'true'\n ) {\n return true;\n }\n }\n\n if (!isAndroid) {\n if (element.attributes?.accessible === 'true') {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Check if element is a layout container\n */\nexport function isLayoutContainer(element: JSONElement, platform: 'android' | 'ios'): boolean {\n const containerList = platform === 'android' ? ANDROID_LAYOUT_CONTAINERS : IOS_LAYOUT_CONTAINERS;\n return matchesTagList(element.tagName, containerList);\n}\n\n/**\n * Check if element has meaningful content (text, accessibility info)\n */\nexport function hasMeaningfulContent(\n element: JSONElement,\n platform: 'android' | 'ios',\n): boolean {\n const attrs = element.attributes;\n\n if (attrs.text && attrs.text.trim() !== '' && attrs.text !== 'null') {\n return true;\n }\n\n if (platform === 'android') {\n if (attrs['content-desc'] && attrs['content-desc'].trim() !== '' && attrs['content-desc'] !== 'null') {\n return true;\n }\n } else {\n if (attrs.label && attrs.label.trim() !== '' && attrs.label !== 'null') {\n return true;\n }\n if (attrs.name && attrs.name.trim() !== '' && attrs.name !== 'null') {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Determine if an element should be included based on all filter criteria\n */\nexport function shouldIncludeElement(\n element: JSONElement,\n filters: FilterOptions,\n isNative: boolean,\n automationName: string,\n): boolean {\n const {\n includeTagNames = [],\n excludeTagNames = ['hierarchy'],\n requireAttributes = [],\n minAttributeCount = 0,\n fetchableOnly = false,\n clickableOnly = false,\n visibleOnly = true,\n } = filters;\n\n if (!matchesTagFilters(element, includeTagNames, excludeTagNames)) {\n return false;\n }\n\n if (!matchesAttributeFilters(element, requireAttributes, minAttributeCount)) {\n return false;\n }\n\n if (clickableOnly && element.attributes?.clickable !== 'true') {\n return false;\n }\n\n if (visibleOnly) {\n const isAndroid = automationName.toLowerCase().includes('uiautomator');\n if (isAndroid && element.attributes?.displayed === 'false') {\n return false;\n }\n if (!isAndroid && element.attributes?.visible === 'false') {\n return false;\n }\n }\n\n if (fetchableOnly && !isInteractableElement(element, isNative, automationName)) {\n return false;\n }\n\n return true;\n}\n\n/**\n * Get default filter options for a platform\n */\nexport function getDefaultFilters(\n platform: 'android' | 'ios',\n includeContainers: boolean = false,\n): FilterOptions {\n const layoutContainers = platform === 'android' ? ANDROID_LAYOUT_CONTAINERS : IOS_LAYOUT_CONTAINERS;\n\n return {\n excludeTagNames: includeContainers ? ['hierarchy'] : ['hierarchy', ...layoutContainers],\n fetchableOnly: !includeContainers,\n visibleOnly: true,\n clickableOnly: false,\n };\n}\n","/**\n * Locator strategy generation for mobile elements\n */\n\nimport type { JSONElement, LocatorStrategy, LocatorContext, UniquenessResult } from './types';\nimport { checkXPathUniqueness, evaluateXPath, isAttributeUnique } from './xml-parsing';\n\n/**\n * Check if a string value is valid for use in a locator\n */\nfunction isValidValue(value: string | undefined): value is string {\n return value !== undefined && value !== null && value !== 'null' && value.trim() !== '';\n}\n\n/**\n * Escape special characters in text for use in selectors\n */\nfunction escapeText(text: string): string {\n return text.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"').replace(/\\n/g, '\\\\n');\n}\n\n/**\n * Escape value for use in XPath expressions\n */\nfunction escapeXPathValue(value: string): string {\n if (!value.includes(\"'\")) {\n return `'${value}'`;\n }\n if (!value.includes('\"')) {\n return `\"${value}\"`;\n }\n const parts: string[] = [];\n let current = '';\n for (const char of value) {\n if (char === \"'\") {\n if (current) parts.push(`'${current}'`);\n parts.push('\"\\'\"');\n current = '';\n } else {\n current += char;\n }\n }\n if (current) parts.push(`'${current}'`);\n return `concat(${parts.join(',')})`;\n}\n\n/**\n * Wrap non-unique XPath with index\n */\nfunction generateIndexedXPath(baseXPath: string, index: number): string {\n return `(${baseXPath})[${index}]`;\n}\n\n/**\n * Add .instance(n) for UiAutomator (0-based)\n */\nfunction generateIndexedUiAutomator(baseSelector: string, index: number): string {\n return `${baseSelector}.instance(${index - 1})`;\n}\n\n/**\n * Check uniqueness, falling back to regex if no DOM available\n */\nfunction checkUniqueness(\n ctx: LocatorContext,\n xpath: string,\n targetNode?: Node,\n): UniquenessResult {\n if (ctx.parsedDOM) {\n return checkXPathUniqueness(ctx.parsedDOM, xpath, targetNode);\n }\n\n const match = xpath.match(/\\/\\/\\*\\[@([^=]+)=\"([^\"]+)\"\\]/);\n if (match) {\n const [, attr, value] = match;\n return { isUnique: isAttributeUnique(ctx.sourceXML, attr, value) };\n }\n return { isUnique: false };\n}\n\n/**\n * Get sibling index (1-based) among same-tag siblings\n */\nfunction getSiblingIndex(element: Element): number {\n const parent = element.parentNode;\n if (!parent) return 1;\n\n const tagName = element.nodeName;\n let index = 0;\n\n for (let i = 0; i < parent.childNodes.length; i++) {\n const child = parent.childNodes.item(i);\n if (child?.nodeType === 1 && child.nodeName === tagName) {\n index++;\n if (child === element) return index;\n }\n }\n\n return 1;\n}\n\n/**\n * Count siblings with same tag name\n */\nfunction countSiblings(element: Element): number {\n const parent = element.parentNode;\n if (!parent) return 1;\n\n const tagName = element.nodeName;\n let count = 0;\n\n for (let i = 0; i < parent.childNodes.length; i++) {\n const child = parent.childNodes.item(i);\n if (child?.nodeType === 1 && child.nodeName === tagName) {\n count++;\n }\n }\n\n return count;\n}\n\n/**\n * Find unique attribute for element in XPath format\n */\nfunction findUniqueAttribute(element: Element, ctx: LocatorContext): string | null {\n const attrs = ctx.isAndroid\n ? ['resource-id', 'content-desc', 'text']\n : ['name', 'label', 'value'];\n\n for (const attr of attrs) {\n const value = element.getAttribute(attr);\n if (value && value.trim()) {\n const xpath = `//*[@${attr}=${escapeXPathValue(value)}]`;\n const result = ctx.parsedDOM\n ? checkXPathUniqueness(ctx.parsedDOM, xpath)\n : { isUnique: isAttributeUnique(ctx.sourceXML, attr, value) };\n\n if (result.isUnique) {\n return `@${attr}=${escapeXPathValue(value)}`;\n }\n }\n }\n\n return null;\n}\n\n/**\n * Build hierarchical XPath by traversing up the DOM tree\n */\nfunction buildHierarchicalXPath(\n ctx: LocatorContext,\n element: Element,\n maxDepth: number = 3,\n): string | null {\n if (!ctx.parsedDOM) return null;\n\n const pathParts: string[] = [];\n let current: Element | null = element;\n let depth = 0;\n\n while (current && depth < maxDepth) {\n const tagName = current.nodeName;\n const uniqueAttr = findUniqueAttribute(current, ctx);\n\n if (uniqueAttr) {\n pathParts.unshift(`//${tagName}[${uniqueAttr}]`);\n break;\n } else {\n const siblingIndex = getSiblingIndex(current);\n const siblingCount = countSiblings(current);\n\n if (siblingCount > 1) {\n pathParts.unshift(`${tagName}[${siblingIndex}]`);\n } else {\n pathParts.unshift(tagName);\n }\n }\n\n const parent = current.parentNode as Element | null;\n current = parent && parent.nodeType === 1 ? parent : null;\n depth++;\n }\n\n if (pathParts.length === 0) return null;\n\n let result = pathParts[0];\n for (let i = 1; i < pathParts.length; i++) {\n result += '/' + pathParts[i];\n }\n\n if (!result.startsWith('//')) {\n result = '//' + result;\n }\n\n return result;\n}\n\n/**\n * Add XPath locator with uniqueness checking and fallbacks\n */\nfunction addXPathLocator(\n results: [LocatorStrategy, string][],\n xpath: string,\n ctx: LocatorContext,\n targetNode?: Node,\n): void {\n const uniqueness = checkUniqueness(ctx, xpath, targetNode);\n if (uniqueness.isUnique) {\n results.push(['xpath', xpath]);\n } else if (uniqueness.index) {\n results.push(['xpath', generateIndexedXPath(xpath, uniqueness.index)]);\n } else {\n if (targetNode && ctx.parsedDOM) {\n const hierarchical = buildHierarchicalXPath(ctx, targetNode as Element);\n if (hierarchical) {\n results.push(['xpath', hierarchical]);\n }\n }\n results.push(['xpath', xpath]);\n }\n}\n\n/**\n * Check if element is within UiAutomator scope\n */\nfunction isInUiAutomatorScope(element: JSONElement, doc: Document | null): boolean {\n if (!doc) return true;\n\n const hierarchyNodes = evaluateXPath(doc, '/hierarchy/*');\n if (hierarchyNodes.length === 0) return true;\n\n const lastIndex = hierarchyNodes.length;\n const pathParts = element.path.split('.');\n if (pathParts.length === 0 || pathParts[0] === '') return true;\n\n const firstIndex = parseInt(pathParts[0], 10);\n return firstIndex === lastIndex - 1;\n}\n\n/**\n * Build Android UiAutomator selector with multiple attributes\n */\nfunction buildUiAutomatorSelector(element: JSONElement): string | null {\n const attrs = element.attributes;\n const parts: string[] = [];\n\n if (isValidValue(attrs['resource-id'])) {\n parts.push(`resourceId(\"${attrs['resource-id']}\")`);\n }\n if (isValidValue(attrs.text) && attrs.text!.length < 100) {\n parts.push(`text(\"${escapeText(attrs.text!)}\")`);\n }\n if (isValidValue(attrs['content-desc'])) {\n parts.push(`description(\"${attrs['content-desc']}\")`);\n }\n if (isValidValue(attrs.class)) {\n parts.push(`className(\"${attrs.class}\")`);\n }\n\n if (parts.length === 0) return null;\n\n return `android=new UiSelector().${parts.join('.')}`;\n}\n\n/**\n * Build iOS predicate string with multiple conditions\n */\nfunction buildPredicateString(element: JSONElement): string | null {\n const attrs = element.attributes;\n const conditions: string[] = [];\n\n if (isValidValue(attrs.name)) {\n conditions.push(`name == \"${escapeText(attrs.name!)}\"`);\n }\n if (isValidValue(attrs.label)) {\n conditions.push(`label == \"${escapeText(attrs.label!)}\"`);\n }\n if (isValidValue(attrs.value)) {\n conditions.push(`value == \"${escapeText(attrs.value!)}\"`);\n }\n if (attrs.visible === 'true') {\n conditions.push('visible == 1');\n }\n if (attrs.enabled === 'true') {\n conditions.push('enabled == 1');\n }\n\n if (conditions.length === 0) return null;\n\n return `-ios predicate string:${conditions.join(' AND ')}`;\n}\n\n/**\n * Build iOS class chain selector\n */\nfunction buildClassChain(element: JSONElement): string | null {\n const attrs = element.attributes;\n const tagName = element.tagName;\n\n if (!tagName.startsWith('XCUI')) return null;\n\n let selector = `**/${tagName}`;\n\n if (isValidValue(attrs.label)) {\n selector += `[\\`label == \"${escapeText(attrs.label!)}\"\\`]`;\n } else if (isValidValue(attrs.name)) {\n selector += `[\\`name == \"${escapeText(attrs.name!)}\"\\`]`;\n }\n\n return `-ios class chain:${selector}`;\n}\n\n/**\n * Build XPath for element with unique identification\n */\nfunction buildXPath(element: JSONElement, sourceXML: string, isAndroid: boolean): string | null {\n const attrs = element.attributes;\n const tagName = element.tagName;\n const conditions: string[] = [];\n\n if (isAndroid) {\n if (isValidValue(attrs['resource-id'])) {\n conditions.push(`@resource-id=\"${attrs['resource-id']}\"`);\n }\n if (isValidValue(attrs['content-desc'])) {\n conditions.push(`@content-desc=\"${attrs['content-desc']}\"`);\n }\n if (isValidValue(attrs.text) && attrs.text!.length < 100) {\n conditions.push(`@text=\"${escapeText(attrs.text!)}\"`);\n }\n } else {\n if (isValidValue(attrs.name)) {\n conditions.push(`@name=\"${attrs.name}\"`);\n }\n if (isValidValue(attrs.label)) {\n conditions.push(`@label=\"${attrs.label}\"`);\n }\n if (isValidValue(attrs.value)) {\n conditions.push(`@value=\"${attrs.value}\"`);\n }\n }\n\n if (conditions.length === 0) {\n return `//${tagName}`;\n }\n\n return `//${tagName}[${conditions.join(' and ')}]`;\n}\n\n/**\n * Get simple locators based on single attributes\n */\nfunction getSimpleSuggestedLocators(\n element: JSONElement,\n ctx: LocatorContext,\n automationName: string,\n targetNode?: Node,\n): [LocatorStrategy, string][] {\n const results: [LocatorStrategy, string][] = [];\n const isAndroid = automationName.toLowerCase().includes('uiautomator');\n const attrs = element.attributes;\n const inUiAutomatorScope = isAndroid ? isInUiAutomatorScope(element, ctx.parsedDOM) : true;\n\n if (isAndroid) {\n // Resource ID\n const resourceId = attrs['resource-id'];\n if (isValidValue(resourceId)) {\n const xpath = `//*[@resource-id=\"${resourceId}\"]`;\n const uniqueness = checkUniqueness(ctx, xpath, targetNode);\n\n if (uniqueness.isUnique && inUiAutomatorScope) {\n results.push(['id', `android=new UiSelector().resourceId(\"${resourceId}\")`]);\n } else if (uniqueness.index && inUiAutomatorScope) {\n const base = `android=new UiSelector().resourceId(\"${resourceId}\")`;\n results.push(['id', generateIndexedUiAutomator(base, uniqueness.index)]);\n }\n }\n\n // Content Description\n const contentDesc = attrs['content-desc'];\n if (isValidValue(contentDesc)) {\n const xpath = `//*[@content-desc=\"${contentDesc}\"]`;\n const uniqueness = checkUniqueness(ctx, xpath, targetNode);\n\n if (uniqueness.isUnique) {\n results.push(['accessibility-id', `~${contentDesc}`]);\n }\n }\n\n // Text\n const text = attrs.text;\n if (isValidValue(text) && text.length < 100) {\n const xpath = `//*[@text=\"${escapeText(text)}\"]`;\n const uniqueness = checkUniqueness(ctx, xpath, targetNode);\n\n if (uniqueness.isUnique && inUiAutomatorScope) {\n results.push(['text', `android=new UiSelector().text(\"${escapeText(text)}\")`]);\n } else if (uniqueness.index && inUiAutomatorScope) {\n const base = `android=new UiSelector().text(\"${escapeText(text)}\")`;\n results.push(['text', generateIndexedUiAutomator(base, uniqueness.index)]);\n }\n }\n } else {\n // iOS: Accessibility ID (name)\n const name = attrs.name;\n if (isValidValue(name)) {\n const xpath = `//*[@name=\"${name}\"]`;\n const uniqueness = checkUniqueness(ctx, xpath, targetNode);\n\n if (uniqueness.isUnique) {\n results.push(['accessibility-id', `~${name}`]);\n }\n }\n\n // iOS: Label\n const label = attrs.label;\n if (isValidValue(label) && label !== attrs.name) {\n const xpath = `//*[@label=\"${escapeText(label)}\"]`;\n const uniqueness = checkUniqueness(ctx, xpath, targetNode);\n\n if (uniqueness.isUnique) {\n results.push(['predicate-string', `-ios predicate string:label == \"${escapeText(label)}\"`]);\n }\n }\n\n // iOS: Value\n const value = attrs.value;\n if (isValidValue(value)) {\n const xpath = `//*[@value=\"${escapeText(value)}\"]`;\n const uniqueness = checkUniqueness(ctx, xpath, targetNode);\n\n if (uniqueness.isUnique) {\n results.push(['predicate-string', `-ios predicate string:value == \"${escapeText(value)}\"`]);\n }\n }\n }\n\n return results;\n}\n\n/**\n * Get complex locators (combinations, XPath, etc.)\n */\nfunction getComplexSuggestedLocators(\n element: JSONElement,\n ctx: LocatorContext,\n automationName: string,\n targetNode?: Node,\n): [LocatorStrategy, string][] {\n const results: [LocatorStrategy, string][] = [];\n const isAndroid = automationName.toLowerCase().includes('uiautomator');\n const inUiAutomatorScope = isAndroid ? isInUiAutomatorScope(element, ctx.parsedDOM) : true;\n\n if (isAndroid) {\n if (inUiAutomatorScope) {\n const uiAutomator = buildUiAutomatorSelector(element);\n if (uiAutomator) {\n results.push(['uiautomator', uiAutomator]);\n }\n }\n\n const xpath = buildXPath(element, ctx.sourceXML, true);\n if (xpath) {\n addXPathLocator(results, xpath, ctx, targetNode);\n }\n\n if (inUiAutomatorScope && isValidValue(element.attributes.class)) {\n results.push([\n 'class-name',\n `android=new UiSelector().className(\"${element.attributes.class}\")`,\n ]);\n }\n } else {\n const predicate = buildPredicateString(element);\n if (predicate) {\n results.push(['predicate-string', predicate]);\n }\n\n const classChain = buildClassChain(element);\n if (classChain) {\n results.push(['class-chain', classChain]);\n }\n\n const xpath = buildXPath(element, ctx.sourceXML, false);\n if (xpath) {\n addXPathLocator(results, xpath, ctx, targetNode);\n }\n\n const type = element.tagName;\n if (type.startsWith('XCUIElementType')) {\n results.push(['class-name', `-ios class chain:**/${type}`]);\n }\n }\n\n return results;\n}\n\n/**\n * Get all suggested locators for an element\n */\nexport function getSuggestedLocators(\n element: JSONElement,\n sourceXML: string,\n automationName: string,\n ctx?: LocatorContext,\n targetNode?: Node,\n): [LocatorStrategy, string][] {\n const locatorCtx = ctx ?? {\n sourceXML,\n parsedDOM: null,\n isAndroid: automationName.toLowerCase().includes('uiautomator'),\n };\n\n const simpleLocators = getSimpleSuggestedLocators(element, locatorCtx, automationName, targetNode);\n const complexLocators = getComplexSuggestedLocators(element, locatorCtx, automationName, targetNode);\n\n const seen = new Set<string>();\n const results: [LocatorStrategy, string][] = [];\n\n for (const locator of [...simpleLocators, ...complexLocators]) {\n if (!seen.has(locator[1])) {\n seen.add(locator[1]);\n results.push(locator);\n }\n }\n\n return results;\n}\n\n/**\n * Get the best (first priority) locator for an element\n */\nexport function getBestLocator(\n element: JSONElement,\n sourceXML: string,\n automationName: string,\n): string | null {\n const locators = getSuggestedLocators(element, sourceXML, automationName);\n return locators.length > 0 ? locators[0][1] : null;\n}\n\n/**\n * Convert locator array to object format\n */\nexport function locatorsToObject(locators: [LocatorStrategy, string][]): Record<string, string> {\n const result: Record<string, string> = {};\n for (const [strategy, value] of locators) {\n if (!result[strategy]) {\n result[strategy] = value;\n }\n }\n return result;\n}\n","/**\n * Mobile element locator generation\n *\n * Main orchestrator module that coordinates XML parsing, element filtering,\n * and locator generation for mobile automation.\n *\n * Based on: https://github.com/appium/appium-mcp\n */\n\n// Types\nexport type {\n ElementAttributes,\n JSONElement,\n Bounds,\n FilterOptions,\n UniquenessResult,\n LocatorStrategy,\n LocatorContext,\n ElementWithLocators,\n GenerateLocatorsOptions,\n} from './types';\n\n// Constants\nexport {\n ANDROID_INTERACTABLE_TAGS,\n IOS_INTERACTABLE_TAGS,\n ANDROID_LAYOUT_CONTAINERS,\n IOS_LAYOUT_CONTAINERS,\n} from './constants';\n\n// XML Parsing\nexport {\n xmlToJSON,\n xmlToDOM,\n evaluateXPath,\n checkXPathUniqueness,\n findDOMNodeByPath,\n parseAndroidBounds,\n parseIOSBounds,\n flattenElementTree,\n countAttributeOccurrences,\n isAttributeUnique,\n} from './xml-parsing';\n\n// Element Filtering\nexport {\n isInteractableElement,\n isLayoutContainer,\n hasMeaningfulContent,\n shouldIncludeElement,\n getDefaultFilters,\n} from './element-filter';\n\n// Locator Generation\nexport {\n getSuggestedLocators,\n getBestLocator,\n locatorsToObject,\n} from './locator-generation';\n\nimport type {\n JSONElement,\n FilterOptions,\n LocatorStrategy,\n ElementWithLocators,\n GenerateLocatorsOptions,\n} from './types';\n\nimport { xmlToJSON, xmlToDOM, parseAndroidBounds, parseIOSBounds, findDOMNodeByPath } from './xml-parsing';\nimport { shouldIncludeElement, isLayoutContainer, hasMeaningfulContent } from './element-filter';\nimport { getSuggestedLocators, locatorsToObject } from './locator-generation';\n\ninterface ProcessingContext {\n sourceXML: string;\n platform: 'android' | 'ios';\n automationName: string;\n isNative: boolean;\n viewportSize: { width: number; height: number };\n filters: FilterOptions;\n results: ElementWithLocators[];\n parsedDOM: Document | null;\n}\n\n/**\n * Parse element bounds based on platform\n */\nfunction parseBounds(\n element: JSONElement,\n platform: 'android' | 'ios',\n): { x: number; y: number; width: number; height: number } {\n return platform === 'android'\n ? parseAndroidBounds(element.attributes.bounds || '')\n : parseIOSBounds(element.attributes);\n}\n\n/**\n * Check if bounds are within viewport\n */\nfunction isWithinViewport(\n bounds: { x: number; y: number; width: number; height: number },\n viewport: { width: number; height: number },\n): boolean {\n return (\n bounds.x >= 0 &&\n bounds.y >= 0 &&\n bounds.width > 0 &&\n bounds.height > 0 &&\n bounds.x + bounds.width <= viewport.width &&\n bounds.y + bounds.height <= viewport.height\n );\n}\n\n/**\n * Transform JSONElement to ElementWithLocators\n */\nfunction transformElement(\n element: JSONElement,\n locators: [LocatorStrategy, string][],\n ctx: ProcessingContext,\n): ElementWithLocators {\n const attrs = element.attributes;\n const bounds = parseBounds(element, ctx.platform);\n\n return {\n tagName: element.tagName,\n locators: locatorsToObject(locators),\n text: attrs.text || attrs.label || '',\n contentDesc: attrs['content-desc'] || '',\n resourceId: attrs['resource-id'] || '',\n accessibilityId: attrs.name || attrs['content-desc'] || '',\n label: attrs.label || '',\n value: attrs.value || '',\n className: attrs.class || element.tagName,\n clickable: attrs.clickable === 'true' || attrs.accessible === 'true' || attrs['long-clickable'] === 'true',\n enabled: attrs.enabled !== 'false',\n displayed: ctx.platform === 'android' ? attrs.displayed !== 'false' : attrs.visible !== 'false',\n bounds,\n isInViewport: isWithinViewport(bounds, ctx.viewportSize),\n };\n}\n\n/**\n * Check if element should be processed\n */\nfunction shouldProcess(element: JSONElement, ctx: ProcessingContext): boolean {\n if (shouldIncludeElement(element, ctx.filters, ctx.isNative, ctx.automationName)) {\n return true;\n }\n return isLayoutContainer(element, ctx.platform) && hasMeaningfulContent(element, ctx.platform);\n}\n\n/**\n * Process a single element and add to results if valid\n */\nfunction processElement(element: JSONElement, ctx: ProcessingContext): void {\n if (!shouldProcess(element, ctx)) return;\n\n try {\n const targetNode = ctx.parsedDOM ? findDOMNodeByPath(ctx.parsedDOM, element.path) : undefined;\n\n const locators = getSuggestedLocators(\n element,\n ctx.sourceXML,\n ctx.automationName,\n { sourceXML: ctx.sourceXML, parsedDOM: ctx.parsedDOM, isAndroid: ctx.platform === 'android' },\n targetNode || undefined,\n );\n if (locators.length === 0) return;\n\n const transformed = transformElement(element, locators, ctx);\n if (Object.keys(transformed.locators).length === 0) return;\n\n ctx.results.push(transformed);\n } catch (error) {\n console.error(`[processElement] Error at path ${element.path}:`, error);\n }\n}\n\n/**\n * Recursively traverse and process element tree\n */\nfunction traverseTree(element: JSONElement | null, ctx: ProcessingContext): void {\n if (!element) return;\n\n processElement(element, ctx);\n\n for (const child of element.children || []) {\n traverseTree(child, ctx);\n }\n}\n\n/**\n * Generate locators for all elements from page source XML\n */\nexport function generateAllElementLocators(\n sourceXML: string,\n options: GenerateLocatorsOptions,\n): ElementWithLocators[] {\n const sourceJSON = xmlToJSON(sourceXML);\n\n if (!sourceJSON) {\n console.error('[generateAllElementLocators] Failed to parse page source XML');\n return [];\n }\n\n const parsedDOM = xmlToDOM(sourceXML);\n\n const ctx: ProcessingContext = {\n sourceXML,\n platform: options.platform,\n automationName: options.platform === 'android' ? 'uiautomator2' : 'xcuitest',\n isNative: options.isNative ?? true,\n viewportSize: options.viewportSize ?? { width: 9999, height: 9999 },\n filters: options.filters ?? {},\n results: [],\n parsedDOM,\n };\n\n traverseTree(sourceJSON, ctx);\n\n return ctx.results;\n}\n","/**\n * Mobile element detection utilities for iOS and Android\n *\n * Uses page source parsing for optimal performance (2 HTTP calls vs 600+ for 50 elements)\n */\n\nimport type { ElementWithLocators, FilterOptions, LocatorStrategy } from '../locators';\nimport { generateAllElementLocators, getDefaultFilters } from '../locators';\n\n/**\n * Element info returned by getMobileVisibleElements\n * Uses uniform fields (all elements have same keys) to enable TOON tabular format\n */\nexport interface MobileElementInfo {\n selector: string;\n tagName: string;\n isInViewport: boolean;\n text: string;\n resourceId: string;\n accessibilityId: string;\n isEnabled: boolean;\n altSelector: string; // Single alternative selector (flattened for tabular format)\n // Only present when includeBounds=true\n bounds?: { x: number; y: number; width: number; height: number };\n}\n\n/**\n * Options for getMobileVisibleElements\n */\nexport interface GetMobileElementsOptions {\n includeContainers?: boolean;\n includeBounds?: boolean;\n filterOptions?: FilterOptions;\n}\n\n/**\n * Locator strategy priority order for selecting best selector\n * Earlier = higher priority\n */\nconst LOCATOR_PRIORITY: LocatorStrategy[] = [\n 'accessibility-id', // Most stable, cross-platform\n 'id', // Android resource-id\n 'text', // Text-based (can be fragile but readable)\n 'predicate-string', // iOS predicate\n 'class-chain', // iOS class chain\n 'uiautomator', // Android UiAutomator compound\n 'xpath', // XPath (last resort, brittle)\n // 'class-name' intentionally excluded - too generic\n];\n\n/**\n * Select best locators from available strategies\n * Returns [primarySelector, ...alternativeSelectors]\n */\nfunction selectBestLocators(locators: Record<string, string>): string[] {\n const selected: string[] = [];\n\n // Find primary selector based on priority\n for (const strategy of LOCATOR_PRIORITY) {\n if (locators[strategy]) {\n selected.push(locators[strategy]);\n break;\n }\n }\n\n // Add one alternative if available (different strategy)\n for (const strategy of LOCATOR_PRIORITY) {\n if (locators[strategy] && !selected.includes(locators[strategy])) {\n selected.push(locators[strategy]);\n break;\n }\n }\n\n return selected;\n}\n\n/**\n * Convert ElementWithLocators to MobileElementInfo\n * Uses uniform fields (all elements have same keys) to enable CSV tabular format\n */\nfunction toMobileElementInfo(element: ElementWithLocators, includeBounds: boolean): MobileElementInfo {\n const selectedLocators = selectBestLocators(element.locators);\n\n // Use contentDesc for accessibilityId on Android, or name on iOS\n const accessId = element.accessibilityId || element.contentDesc;\n\n // Build object with ALL fields for uniform schema (enables CSV tabular format)\n // Empty string '' used for missing values to keep schema consistent\n const info: MobileElementInfo = {\n selector: selectedLocators[0] || '',\n tagName: element.tagName,\n isInViewport: element.isInViewport,\n text: element.text || '',\n resourceId: element.resourceId || '',\n accessibilityId: accessId || '',\n isEnabled: element.enabled !== false,\n altSelector: selectedLocators[1] || '', // Single alternative (flattened for tabular)\n };\n\n // Only include bounds if explicitly requested (adds 4 extra columns)\n if (includeBounds) {\n info.bounds = element.bounds;\n }\n\n return info;\n}\n\n/**\n * Get viewport size from browser\n */\nasync function getViewportSize(browser: WebdriverIO.Browser): Promise<{ width: number; height: number }> {\n try {\n const size = await browser.getWindowSize();\n return { width: size.width, height: size.height };\n } catch {\n return { width: 9999, height: 9999 };\n }\n}\n\n/**\n * Get all visible elements from a mobile app\n *\n * Performance: 2 HTTP calls (getWindowSize + getPageSource) vs 12+ per element with legacy approach\n */\nexport async function getMobileVisibleElements(\n browser: WebdriverIO.Browser,\n platform: 'ios' | 'android',\n options: GetMobileElementsOptions = {},\n): Promise<MobileElementInfo[]> {\n const { includeContainers = false, includeBounds = false, filterOptions } = options;\n\n const viewportSize = await getViewportSize(browser);\n const pageSource = await browser.getPageSource();\n\n const filters: FilterOptions = {\n ...getDefaultFilters(platform, includeContainers),\n ...filterOptions,\n };\n\n const elements = generateAllElementLocators(pageSource, {\n platform,\n viewportSize,\n filters,\n });\n\n return elements.map((el) => toMobileElementInfo(el, includeBounds));\n}\n","import { getInteractableBrowserElements } from './get-interactable-browser-elements';\nimport { getMobileVisibleElements } from './get-visible-mobile-elements';\n\nexport type VisibleElementsResult = {\n total: number;\n showing: number;\n hasMore: boolean;\n elements: unknown[];\n};\n\nexport async function getElements(\n browser: WebdriverIO.Browser,\n params: {\n inViewportOnly?: boolean;\n includeContainers?: boolean;\n includeBounds?: boolean;\n limit?: number;\n offset?: number;\n },\n): Promise<VisibleElementsResult> {\n const {\n inViewportOnly = true,\n includeContainers = false,\n includeBounds = false,\n limit = 0,\n offset = 0,\n } = params;\n\n let elements: { isInViewport?: boolean }[];\n\n if (browser.isAndroid || browser.isIOS) {\n const platform = browser.isAndroid ? 'android' : 'ios';\n elements = await getMobileVisibleElements(browser, platform, { includeContainers, includeBounds });\n } else {\n elements = await getInteractableBrowserElements(browser, { includeBounds });\n }\n\n if (inViewportOnly) {\n elements = elements.filter((el) => el.isInViewport !== false);\n }\n\n const total = elements.length;\n\n if (offset > 0) {\n elements = elements.slice(offset);\n }\n if (limit > 0) {\n elements = elements.slice(0, limit);\n }\n\n return {\n total,\n showing: elements.length,\n hasMore: offset + elements.length < total,\n elements,\n };\n}\n","import { spawn } from 'node:child_process';\nimport { copyFileSync, cpSync, existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs';\nimport { homedir, platform, tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ToolDefinition } from '../types/tool';\nimport { z } from 'zod';\nimport { coerceBoolean } from '../utils/zod-helpers';\n\nconst USER_DATA_DIR = join(tmpdir(), 'chrome-debug');\n\nexport const launchChromeToolDefinition: ToolDefinition = {\n name: 'launch_chrome',\n description: `Prepares and launches Chrome with remote debugging enabled so attach_browser() can connect.\n\nTwo modes:\n\n newInstance (default): Opens a Chrome window alongside your existing one using a separate\n profile dir. Your current Chrome session is untouched.\n\n freshSession: Launches Chrome with an empty profile (no cookies, no logins).\n\nUse copyProfileFiles: true to carry over your cookies and logins into the debug session.\nNote: changes made during the session won't sync back to your main profile.\n\nAfter this tool succeeds, call attach_browser() to connect.`,\n inputSchema: {\n port: z.number().default(9222).describe('Remote debugging port (default: 9222)'),\n mode: z.enum(['newInstance', 'freshSession']).default('newInstance').describe(\n 'newInstance: open alongside existing Chrome | freshSession: clean profile'\n ),\n copyProfileFiles: coerceBoolean.default(false).describe(\n 'Copy your Default Chrome profile (cookies, logins) into the debug session.'\n ),\n },\n};\n\nfunction isMac(): boolean {\n return platform() === 'darwin';\n}\n\nfunction chromeExec(): string {\n if (isMac()) return '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome';\n if (platform() === 'win32') {\n const candidates = [\n join('C:', 'Program Files', 'Google', 'Chrome', 'Application', 'chrome.exe'),\n join('C:', 'Program Files (x86)', 'Google', 'Chrome', 'Application', 'chrome.exe'),\n ];\n return candidates.find((p) => existsSync(p)) ?? candidates[0];\n }\n return 'google-chrome';\n}\n\nfunction defaultProfileDir(): string {\n const home = homedir();\n if (isMac()) return join(home, 'Library', 'Application Support', 'Google', 'Chrome');\n if (platform() === 'win32') return join(home, 'AppData', 'Local', 'Google', 'Chrome', 'User Data');\n return join(home, '.config', 'google-chrome');\n}\n\nfunction copyProfile(): void {\n const srcDir = defaultProfileDir();\n rmSync(USER_DATA_DIR, { recursive: true, force: true });\n mkdirSync(USER_DATA_DIR, { recursive: true });\n copyFileSync(join(srcDir, 'Local State'), join(USER_DATA_DIR, 'Local State'));\n cpSync(join(srcDir, 'Default'), join(USER_DATA_DIR, 'Default'), { recursive: true });\n\n // Remove singleton/lock files from the source Chrome instance.\n for (const f of ['SingletonLock', 'SingletonCookie', 'SingletonSocket']) {\n rmSync(join(USER_DATA_DIR, f), { force: true });\n }\n\n // Remove session files — they reference the original profile's state and trigger\n // \"Something went wrong when opening your profile\" when Chrome opens the copy.\n for (const f of ['Current Session', 'Current Tabs', 'Last Session', 'Last Tabs']) {\n rmSync(join(USER_DATA_DIR, 'Default', f), { force: true });\n }\n\n // First Run sentinel tells Chrome this is a fresh start — suppresses first-run dialogs.\n writeFileSync(join(USER_DATA_DIR, 'First Run'), '');\n}\n\nfunction launchChrome(port: number): void {\n spawn(chromeExec(), [\n `--remote-debugging-port=${port}`,\n `--user-data-dir=${USER_DATA_DIR}`,\n '--profile-directory=Default',\n '--no-first-run',\n '--disable-session-crashed-bubble',\n ], { detached: true, stdio: 'ignore' }).unref();\n}\n\nasync function waitForCDP(port: number, timeoutMs = 15000): Promise<void> {\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n try {\n const res = await fetch(`http://localhost:${port}/json/version`);\n if (res.ok) return;\n } catch {\n // not ready yet\n }\n await new Promise((r) => setTimeout(r, 300));\n }\n throw new Error(`Chrome did not expose CDP on port ${port} within ${timeoutMs}ms`);\n}\n\nexport const launchChromeTool: ToolCallback = async ({\n port = 9222,\n mode = 'newInstance',\n copyProfileFiles = false,\n}: {\n port?: number;\n mode?: 'newInstance' | 'freshSession';\n copyProfileFiles?: boolean;\n}): Promise<CallToolResult> => {\n const warnings: string[] = [];\n const notes: string[] = [];\n\n try {\n if (copyProfileFiles) {\n warnings.push('⚠️ Cookies and logins were copied at this moment. Changes during this session won\\'t sync back to your main profile.');\n copyProfile();\n } else {\n notes.push(mode === 'newInstance'\n ? 'No profile copied — this instance starts with no cookies or logins.'\n : 'Fresh profile — no existing cookies or logins.');\n rmSync(USER_DATA_DIR, { recursive: true, force: true });\n mkdirSync(USER_DATA_DIR, { recursive: true });\n }\n\n launchChrome(port);\n await waitForCDP(port);\n\n const lines = [\n `Chrome launched on port ${port} (mode: ${mode}).`,\n ...warnings,\n ...notes,\n ];\n\n return { content: [{ type: 'text', text: lines.join('\\n') }] };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error launching Chrome: ${e}` }],\n };\n }\n};","import type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ToolDefinition } from '../types/tool';\n// DeviceName is not in webdriverio's public exports but is required to satisfy browser.emulate('device', ...) overloads.\n// This is a type-only import — it is stripped at build time by tsup and has no runtime impact.\nimport type { DeviceName } from 'webdriverio/build/deviceDescriptorsSource.js';\nimport { z } from 'zod';\nimport { getBrowser, getState } from '../session/state';\n\n// Stores restore functions returned by browser.emulate(), keyed by sessionId\nconst restoreFunctions = new Map<string, () => Promise<void>>();\n\nexport const emulateDeviceToolDefinition: ToolDefinition = {\n name: 'emulate_device',\n description: `Emulate a mobile or tablet device in the current browser session (sets viewport, DPR, user-agent, touch events).\n\nRequires a BiDi-enabled session: start_browser({ capabilities: { webSocketUrl: true } })\n\nUsage:\n emulate_device() — list available device presets\n emulate_device({ device: \"iPhone 15\" }) — activate emulation\n emulate_device({ device: \"reset\" }) — restore desktop defaults`,\n inputSchema: {\n device: z.string().optional().describe(\n 'Device preset name (e.g. \"iPhone 15\", \"Pixel 7\"). Omit to list available presets. Pass \"reset\" to restore desktop defaults.'\n ),\n },\n};\n\nexport const emulateDeviceTool: ToolCallback = async ({\n device,\n}: {\n device?: string;\n}): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n const state = getState();\n const sessionId = state.currentSession;\n const metadata = state.sessionMetadata.get(sessionId);\n\n // Guard: mobile sessions\n if (metadata?.type === 'ios' || metadata?.type === 'android') {\n return {\n isError: true,\n content: [{\n type: 'text',\n text: 'Error: emulate_device is only supported for web browser sessions, not iOS/Android.'\n }],\n };\n }\n\n // Guard: BiDi required\n if (!browser.isBidi) {\n return {\n isError: true,\n content: [{\n type: 'text',\n text: 'Error: emulate_device requires a BiDi-enabled session.\\nRestart the browser with: start_browser({ capabilities: { webSocketUrl: true } })',\n }],\n };\n }\n\n // List presets by triggering a known-bad device name and parsing the error\n if (!device) {\n try {\n await browser.emulate('device', '\\u0000' as DeviceName);\n } catch (e) {\n const msg = String(e);\n const match = msg.match(/please use one of the following: (.+)$/);\n if (match) {\n const names = match[1].split(', ').sort();\n return {\n content: [{ type: 'text', text: `Available devices (${names.length}):\\n${names.join('\\n')}` }],\n };\n }\n return { isError: true, content: [{ type: 'text', text: `Error listing devices: ${e}` }] };\n }\n return { content: [{ type: 'text', text: 'Could not retrieve device list.' }] };\n }\n\n // Reset\n if (device === 'reset') {\n const restoreFn = restoreFunctions.get(sessionId);\n if (!restoreFn) {\n return { content: [{ type: 'text', text: 'No active device emulation to reset.' }] };\n }\n await restoreFn();\n restoreFunctions.delete(sessionId);\n return { content: [{ type: 'text', text: 'Device emulation reset to desktop defaults.' }] };\n }\n\n // Emulate device\n try {\n const restoreFn = await browser.emulate('device', device as DeviceName);\n restoreFunctions.set(sessionId, restoreFn as () => Promise<void>);\n return {\n content: [{ type: 'text', text: `Emulating \"${device}\".` }],\n };\n } catch (e) {\n const msg = String(e);\n if (msg.includes('Unknown device name')) {\n return {\n content: [{\n type: 'text',\n text: `Error: Unknown device \"${device}\". Call emulate_device() with no arguments to list valid names.`,\n }],\n };\n }\n return { isError: true, content: [{ type: 'text', text: `Error: ${e}` }] };\n }\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error: ${e}` }],\n };\n }\n};\n","// src/recording/step-recorder.ts\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { RecordedStep, SessionHistory } from '../types/recording';\nimport { getState } from '../session/state';\n\nexport function appendStep(\n toolName: string,\n params: Record<string, unknown>,\n status: 'ok' | 'error',\n durationMs: number,\n error?: string,\n): void {\n const state = getState();\n const sessionId = state.currentSession;\n if (!sessionId) return;\n\n const history = state.sessionHistory.get(sessionId);\n if (!history) return;\n\n const step: RecordedStep = {\n index: history.steps.length + 1,\n tool: toolName,\n params,\n status,\n durationMs,\n timestamp: new Date().toISOString(),\n ...(error !== undefined && { error }),\n };\n history.steps.push(step);\n}\n\nexport function getSessionHistory(): Map<string, SessionHistory> {\n return getState().sessionHistory;\n}\n\nfunction extractErrorText(result: Awaited<ReturnType<ToolCallback>>): string {\n const textContent = result.content.find((c: any) => c.type === 'text');\n return textContent ? (textContent as any).text : 'Unknown error';\n}\n\nexport function withRecording(toolName: string, callback: ToolCallback): ToolCallback {\n return async (params, extra) => {\n const start = Date.now();\n const result = await callback(params, extra);\n const isError = (result as any).isError === true;\n appendStep(\n toolName,\n params as Record<string, unknown>,\n isError ? 'error' : 'ok',\n Date.now() - start,\n isError ? extractErrorText(result) : undefined,\n );\n return result;\n };\n}\n","import type { ResourceDefinition } from '../types/resource';\n\nfunction getLocalBinaryInfo(): {\n downloadUrl: string;\n platform: string;\n arch: string;\n binaryName: string;\n note?: string;\n} {\n const platform = process.platform;\n const arch = process.arch;\n\n if (platform === 'darwin') {\n return {\n downloadUrl: 'https://local-downloads.browserstack.com/BrowserStackLocal-darwin-x64.zip',\n platform: 'macOS',\n arch: arch === 'arm64' ? 'Apple Silicon (via Rosetta 2)' : 'Intel x64',\n binaryName: 'BrowserStackLocal',\n note: arch === 'arm64' ? 'macOS binary is Intel-only. Rosetta 2 must be installed (it is on most Apple Silicon Macs by default).' : undefined,\n };\n }\n\n if (platform === 'win32') {\n return {\n downloadUrl: 'https://local-downloads.browserstack.com/BrowserStackLocal-win32.zip',\n platform: 'Windows',\n arch: 'x86/x64',\n binaryName: 'BrowserStackLocal.exe',\n };\n }\n\n // Linux\n if (arch === 'arm64') {\n return {\n downloadUrl: 'https://local-downloads.browserstack.com/BrowserStackLocal-linux-arm64.zip',\n platform: 'Linux',\n arch: 'ARM64',\n binaryName: 'BrowserStackLocal',\n };\n }\n\n if (arch === 'ia32') {\n return {\n downloadUrl: 'https://local-downloads.browserstack.com/BrowserStackLocal-linux-ia32.zip',\n platform: 'Linux',\n arch: 'x86 32-bit',\n binaryName: 'BrowserStackLocal',\n };\n }\n\n return {\n downloadUrl: 'https://local-downloads.browserstack.com/BrowserStackLocal-linux-x64.zip',\n platform: 'Linux',\n arch: 'x64',\n binaryName: 'BrowserStackLocal',\n };\n}\n\nexport const browserstackLocalBinaryResource: ResourceDefinition = {\n name: 'browserstack-local-binary',\n uri: 'wdio://browserstack/local-binary',\n description: 'BrowserStack Local binary download URL and daemon setup instructions for the current platform. MUST be read and followed before using browserstackLocal: true in start_session.',\n handler: async () => {\n const info = getLocalBinaryInfo();\n const accessKey = process.env.BROWSERSTACK_ACCESS_KEY ?? '<BROWSERSTACK_ACCESS_KEY>';\n\n const content = {\n requirement: 'MUST start the BrowserStack Local daemon BEFORE calling start_session with browserstackLocal: true. Without it, all navigation to local/internal URLs will fail with ERR_TUNNEL_CONNECTION_FAILED.',\n platform: info.platform,\n arch: info.arch,\n downloadUrl: info.downloadUrl,\n ...(info.note ? { note: info.note } : {}),\n setup: [\n `1. Download: curl -O ${info.downloadUrl}`,\n `2. Unzip: unzip ${info.downloadUrl.split('/').pop()}`,\n `3. Make executable (macOS/Linux): chmod +x ${info.binaryName}`,\n `4. Start daemon: ./${info.binaryName} --key ${accessKey} --force-local --daemon start`,\n ],\n commands: {\n start: `./${info.binaryName} --key ${accessKey} --force-local --daemon start`,\n stop: `./${info.binaryName} --key ${accessKey} --daemon stop`,\n status: `./${info.binaryName} --daemon list`,\n },\n afterDaemonIsRunning: 'Call start_session with browserstackLocal: true to route BrowserStack traffic through the tunnel.',\n };\n\n return {\n contents: [{\n uri: 'wdio://browserstack/local-binary',\n mimeType: 'application/json',\n text: JSON.stringify(content, null, 2),\n }],\n };\n },\n};","import type { ResourceDefinition } from '../types/resource';\nimport { ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { SessionHistory } from '../types/recording';\nimport { generateCode } from '../recording/code-generator';\nimport { getSessionHistory } from '../recording/step-recorder';\nimport { getState } from '../session/state';\n\nfunction getCurrentSessionId(): string | null {\n return getState().currentSession;\n}\n\nexport interface SessionStepsPayload {\n stepsJson: string;\n generatedJs: string;\n}\n\nexport function buildSessionsIndex(): string {\n const histories = getSessionHistory();\n const currentId = getCurrentSessionId();\n const sessions = Array.from(histories.values()).map((h) => ({\n sessionId: h.sessionId,\n type: h.type,\n startedAt: h.startedAt,\n ...(h.endedAt ? { endedAt: h.endedAt } : {}),\n stepCount: h.steps.length,\n isCurrent: h.sessionId === currentId,\n }));\n return JSON.stringify({ sessions });\n}\n\nexport function buildCurrentSessionSteps(): SessionStepsPayload | null {\n const currentId = getCurrentSessionId();\n if (!currentId) return null;\n\n return buildSessionStepsById(currentId);\n}\n\nexport function buildSessionStepsById(sessionId: string): SessionStepsPayload | null {\n const history = getSessionHistory().get(sessionId);\n if (!history) return null;\n\n return buildSessionPayload(history);\n}\n\nfunction buildSessionPayload(history: SessionHistory): SessionStepsPayload {\n const stepsJson = JSON.stringify({\n sessionId: history.sessionId,\n type: history.type,\n startedAt: history.startedAt,\n ...(history.endedAt ? { endedAt: history.endedAt } : {}),\n stepCount: history.steps.length,\n steps: history.steps,\n });\n\n return { stepsJson, generatedJs: generateCode(history) };\n}\n\nexport const sessionsIndexResource: ResourceDefinition = {\n name: 'sessions',\n uri: 'wdio://sessions',\n description: 'JSON index of all browser and app sessions with metadata and step counts',\n handler: async () => ({\n contents: [{ uri: 'wdio://sessions', mimeType: 'application/json', text: buildSessionsIndex() }],\n }),\n};\n\nexport const sessionCurrentStepsResource: ResourceDefinition = {\n name: 'session-current-steps',\n uri: 'wdio://session/current/steps',\n description: 'JSON step log for the currently active session',\n handler: async () => {\n const payload = buildCurrentSessionSteps();\n return {\n contents: [{\n uri: 'wdio://session/current/steps',\n mimeType: 'application/json',\n text: payload?.stepsJson ?? '{\"error\":\"No active session\"}',\n }],\n };\n },\n};\n\nexport const sessionCurrentCodeResource: ResourceDefinition = {\n name: 'session-current-code',\n uri: 'wdio://session/current/code',\n description: 'Generated WebdriverIO JS code for the currently active session',\n handler: async () => {\n const payload = buildCurrentSessionSteps();\n return {\n contents: [{\n uri: 'wdio://session/current/code',\n mimeType: 'text/plain',\n text: payload?.generatedJs ?? '// No active session',\n }],\n };\n },\n};\n\nexport const sessionStepsResource: ResourceDefinition = {\n name: 'session-steps',\n template: new ResourceTemplate('wdio://session/{sessionId}/steps', { list: undefined }),\n description: 'JSON step log for a specific session by ID',\n handler: async (uri, { sessionId }) => {\n const payload = buildSessionStepsById(sessionId as string);\n return {\n contents: [{\n uri: uri.href,\n mimeType: 'application/json',\n text: payload?.stepsJson ?? `{\"error\":\"Session not found: ${sessionId}\"}`,\n }],\n };\n },\n};\n\nexport const sessionCodeResource: ResourceDefinition = {\n name: 'session-code',\n template: new ResourceTemplate('wdio://session/{sessionId}/code', { list: undefined }),\n description: 'Generated WebdriverIO JS code for a specific session by ID',\n handler: async (uri, { sessionId }) => {\n const payload = buildSessionStepsById(sessionId as string);\n return {\n contents: [{\n uri: uri.href,\n mimeType: 'text/plain',\n text: payload?.generatedJs ?? `// Session not found: ${sessionId}`,\n }],\n };\n },\n};","// src/recording/code-generator.ts\nimport type { RecordedStep, SessionHistory } from '../types/recording';\n\n/** Escape single quotes so generated JS string literals are valid. */\nfunction escapeStr(value: unknown): string {\n return String(value).replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n}\n\nfunction formatParams(params: Record<string, unknown>): string {\n return Object.entries(params)\n .map(([k, v]) => `${k}=\"${v}\"`)\n .join(' ');\n}\n\nfunction indentJson(value: unknown): string {\n return JSON.stringify(value, null, 2)\n .split('\\n')\n .map((line, i) => (i > 0 ? ` ${line}` : line))\n .join('\\n');\n}\n\nfunction generateStep(step: RecordedStep, history: SessionHistory): string {\n if (step.tool === '__session_transition__') {\n const newId = (step.params.newSessionId as string) ?? 'unknown';\n return `// --- new session: ${newId} started at ${step.timestamp} ---`;\n }\n\n if (step.status === 'error') {\n return `// [error] ${step.tool}: ${formatParams(step.params)} — ${step.error ?? 'unknown error'}`;\n }\n\n const p = step.params;\n switch (step.tool) {\n case 'start_session': {\n const platform = p.platform as string;\n const isBrowserStack = 'bstack:options' in history.capabilities;\n const capJson = indentJson(history.capabilities)\n .split('\\n')\n .map((line, i) => (i > 0 ? ` ${line}` : line))\n .join('\\n');\n\n if (isBrowserStack) {\n const nav =\n platform === 'browser' && p.navigationUrl\n ? `\\nawait browser.url('${escapeStr(p.navigationUrl)}');`\n : '';\n return [\n 'const browser = await remote({',\n \" protocol: 'https',\",\n \" hostname: 'hub.browserstack.com',\",\n ' port: 443,',\n \" path: '/wd/hub',\",\n ' user: process.env.BS_USER,',\n ' key: process.env.BS_KEY,',\n ` capabilities: ${capJson}`,\n `});${nav}`,\n ].join('\\n');\n }\n\n if (platform === 'browser') {\n const nav = p.navigationUrl ? `\\nawait browser.url('${escapeStr(p.navigationUrl)}');` : '';\n return `const browser = await remote({\\n capabilities: ${indentJson(history.capabilities)}\\n});${nav}`;\n }\n // Mobile (ios/android)\n const config: Record<string, unknown> = {\n protocol: 'http',\n hostname: history.appiumConfig?.hostname ?? 'localhost',\n port: history.appiumConfig?.port ?? 4723,\n path: history.appiumConfig?.path ?? '/',\n capabilities: history.capabilities,\n };\n return `const browser = await remote(${indentJson(config)});`;\n }\n case 'close_session':\n return '// Session closed';\n case 'navigate':\n return `await browser.url('${escapeStr(p.url)}');`;\n case 'click_element':\n return `await browser.$('${escapeStr(p.selector)}').click();`;\n case 'set_value':\n return `await browser.$('${escapeStr(p.selector)}').setValue('${escapeStr(p.value)}');`;\n case 'scroll': {\n const scrollAmount = (p.direction as string) === 'down' ? (p.pixels as number) : -(p.pixels as number);\n return `await browser.execute(() => window.scrollBy(0, ${scrollAmount}));`;\n }\n case 'tap_element':\n if (p.selector !== undefined) {\n return `await browser.$('${escapeStr(p.selector)}').click();`;\n }\n return `await browser.tap({ x: ${p.x}, y: ${p.y} });`;\n case 'swipe':\n return `await browser.execute('mobile: swipe', { direction: '${escapeStr(p.direction)}' });`;\n case 'drag_and_drop':\n if (p.targetSelector !== undefined) {\n return `await browser.$('${escapeStr(p.sourceSelector)}').dragAndDrop(browser.$('${escapeStr(p.targetSelector)}'));`;\n }\n return `await browser.$('${escapeStr(p.sourceSelector)}').dragAndDrop({ x: ${p.x}, y: ${p.y} });`;\n case 'execute_script': {\n const scriptCode = `'${escapeStr(p.script)}'`;\n const scriptArgs = (p.args as unknown[])?.length ? `, ${indentJson(p.args)}` : '';\n return `await browser.execute(${scriptCode}${scriptArgs});`;\n }\n default:\n return `// [unknown tool] ${step.tool}`;\n }\n}\n\nfunction bsStatusUpdateLines(sessionType: 'browser' | 'ios' | 'android'): string[] {\n const apiUrl = sessionType === 'browser'\n ? 'https://api.browserstack.com/automate/sessions/'\n : 'https://api-cloud.browserstack.com/app-automate/sessions/';\n return [\n \" const bsAuth = Buffer.from(`${process.env.BS_USER}:${process.env.BS_KEY}`).toString('base64');\",\n ` await fetch('${apiUrl}' + browser.sessionId + '.json', {`,\n \" method: 'PUT',\",\n \" headers: { Authorization: 'Basic ' + bsAuth, 'Content-Type': 'application/json' },\",\n ' body: JSON.stringify({ status: bsStatus, ...(bsReason ? { reason: bsReason } : {}) })',\n ' });',\n ];\n}\n\nexport function generateCode(history: SessionHistory): string {\n const bstackOptions = history.capabilities['bstack:options'] as Record<string, unknown> | undefined;\n const isBrowserStack = bstackOptions !== undefined;\n const usesBrowserstackLocal = bstackOptions?.local === true;\n\n const steps = history.steps\n .map(step => generateStep(step, history))\n .join('\\n')\n .split('\\n')\n .map(line => ` ${line}`)\n .join('\\n');\n\n if (isBrowserStack) {\n const bsSteps = steps.replace(/const browser = await remote\\(/g, 'browser = await remote(');\n const statusUpdate = bsStatusUpdateLines(history.type).join('\\n');\n const preamble = 'let browser;\\nlet bsStatus = \\'passed\\';\\nlet bsReason;';\n const catchBlock = '} catch (e) {\\n bsStatus = \\'failed\\';\\n bsReason = String(e);\\n throw e;';\n const finallyBody = ` if (browser) {\\n${statusUpdate}\\n await browser.deleteSession();\\n }`;\n\n if (usesBrowserstackLocal) {\n const tunnelSetup = [\n '',\n 'const tunnel = new BrowserstackTunnel();',\n 'const startTunnel = promisify(tunnel.start.bind(tunnel));',\n 'const stopTunnel = promisify(tunnel.stop.bind(tunnel));',\n 'await startTunnel({ key: process.env.BROWSERSTACK_ACCESS_KEY });',\n '',\n ].join('\\n');\n\n return [\n \"import { remote } from 'webdriverio';\",\n \"import { Local as BrowserstackTunnel } from 'browserstack-local';\",\n \"import { promisify } from 'node:util';\",\n tunnelSetup,\n preamble,\n 'try {',\n bsSteps,\n catchBlock,\n '} finally {',\n finallyBody,\n ' await stopTunnel();',\n '}',\n ].join('\\n');\n }\n\n return [\n \"import { remote } from 'webdriverio';\",\n '',\n preamble,\n 'try {',\n bsSteps,\n catchBlock,\n '} finally {',\n finallyBody,\n '}',\n ].join('\\n');\n }\n\n return `import { remote } from 'webdriverio';\\n\\ntry {\\n${steps}\\n} finally {\\n await browser.deleteSession();\\n}`;\n}\n","import type { ResourceDefinition } from '../types/resource';\nimport { getBrowser } from '../session/state';\n\nexport const capabilitiesResource: ResourceDefinition = {\n name: 'session-current-capabilities',\n uri: 'wdio://session/current/capabilities',\n description: 'Raw capabilities returned by the WebDriver/Appium server for the current session. Use for debugging — shows the actual values the driver accepted, including defaults applied by BrowserStack or Appium.',\n handler: async () => {\n try {\n const browser = getBrowser();\n return {\n contents: [{\n uri: 'wdio://session/current/capabilities',\n mimeType: 'application/json',\n text: JSON.stringify(browser.capabilities, null, 2),\n }],\n };\n } catch (e) {\n return {\n contents: [{\n uri: 'wdio://session/current/capabilities',\n mimeType: 'application/json',\n text: JSON.stringify({ error: String(e) }),\n }],\n };\n }\n },\n};\n","import type { ResourceDefinition } from '../types/resource';\nimport { getBrowser } from '../session/state';\nimport { getElements } from '../scripts/get-elements';\nimport { encode } from '@toon-format/toon';\n\nexport const elementsResource: ResourceDefinition = {\n name: 'session-current-elements',\n uri: 'wdio://session/current/elements',\n description: 'Interactable elements on the current page. Prefer this over screenshot — returns ready-to-use selectors, faster, and far fewer tokens. Only use screenshot for visual verification or debugging.',\n handler: async () => {\n try {\n const browser = getBrowser();\n const result = await getElements(browser, {});\n const text = encode(result).replace(/,\"\"/g, ',').replace(/\"\",/g, ',');\n return { contents: [{ uri: 'wdio://session/current/elements', mimeType: 'text/plain', text }] };\n } catch (e) {\n return {\n contents: [{\n uri: 'wdio://session/current/elements',\n mimeType: 'text/plain',\n text: `Error getting visible elements: ${e}`\n }]\n };\n }\n },\n};\n","import type { ResourceDefinition } from '../types/resource';\nimport { getBrowser } from '../session/state';\nimport { getBrowserAccessibilityTree } from '../scripts/get-browser-accessibility-tree';\nimport { encode } from '@toon-format/toon';\n\nexport async function readAccessibilityTree(params: {\n limit?: number;\n offset?: number;\n roles?: string[];\n}): Promise<{ mimeType: string; text: string }> {\n try {\n const browser = getBrowser();\n\n if (browser.isAndroid || browser.isIOS) {\n return {\n mimeType: 'text/plain',\n text: 'Error: accessibility is browser-only. For mobile apps, use elements resource instead.',\n };\n }\n\n const { limit = 0, offset = 0, roles } = params;\n\n let nodes = await getBrowserAccessibilityTree(browser);\n\n if (nodes.length === 0) {\n return { mimeType: 'text/plain', text: 'No accessibility tree available' };\n }\n\n nodes = nodes.filter((n) => n.name && n.name.trim() !== '');\n\n if (roles && roles.length > 0) {\n const roleSet = new Set(roles.map((r) => r.toLowerCase()));\n nodes = nodes.filter((n) => n.role && roleSet.has(n.role.toLowerCase()));\n }\n\n const total = nodes.length;\n\n if (offset > 0) {\n nodes = nodes.slice(offset);\n }\n if (limit > 0) {\n nodes = nodes.slice(0, limit);\n }\n\n const stateKeys = ['level', 'disabled', 'checked', 'expanded', 'selected', 'pressed', 'required', 'readonly'] as const;\n const usedKeys = stateKeys.filter((k) => nodes.some((n) => n[k] !== ''));\n const trimmed = nodes.map(({ role, name, selector, ...state }) => {\n const node: Record<string, unknown> = { role, name, selector };\n for (const k of usedKeys) node[k] = state[k];\n return node;\n });\n\n const result = {\n total,\n showing: trimmed.length,\n hasMore: offset + trimmed.length < total,\n nodes: trimmed,\n };\n\n const toon = encode(result).replace(/,\"\"/g, ',').replace(/\"\",/g, ',');\n\n return { mimeType: 'text/plain', text: toon };\n } catch (e) {\n return { mimeType: 'text/plain', text: `Error getting accessibility tree: ${e}` };\n }\n}\n\nexport const accessibilityResource: ResourceDefinition = {\n name: 'session-current-accessibility',\n uri: 'wdio://session/current/accessibility',\n description: 'Accessibility tree for the current page. Returns all elements by default.',\n handler: async () => {\n const result = await readAccessibilityTree({});\n return { contents: [{ uri: 'wdio://session/current/accessibility', mimeType: result.mimeType, text: result.text }] };\n },\n};","/**\n * Browser accessibility tree\n * Single browser.execute() call: DOM walk → flat accessibility node list\n *\n * NOTE: This script runs in browser context via browser.execute()\n * It must be self-contained with no external dependencies\n */\n\nexport interface AccessibilityNode {\n role: string;\n name: string;\n selector: string;\n level: number | string;\n disabled: string;\n checked: string;\n expanded: string;\n selected: string;\n pressed: string;\n required: string;\n readonly: string;\n}\n\nconst accessibilityTreeScript = () => (function () {\n\n const INPUT_TYPE_ROLES: Record<string, string> = {\n text: 'textbox', search: 'searchbox', email: 'textbox', url: 'textbox',\n tel: 'textbox', password: 'textbox', number: 'spinbutton',\n checkbox: 'checkbox', radio: 'radio', range: 'slider',\n submit: 'button', reset: 'button', image: 'button', file: 'button', color: 'button',\n };\n\n const LANDMARK_ROLES = new Set([\n 'navigation', 'main', 'banner', 'contentinfo', 'complementary', 'form', 'dialog', 'region',\n ]);\n\n // Container roles: named only via aria-label/aria-labelledby, not textContent\n const CONTAINER_ROLES = new Set([\n 'navigation', 'banner', 'contentinfo', 'complementary', 'main', 'form',\n 'region', 'group', 'list', 'listitem', 'table', 'row', 'rowgroup', 'generic',\n ]);\n\n function getRole(el: HTMLElement): string | null {\n const explicit = el.getAttribute('role');\n if (explicit) return explicit.split(' ')[0];\n\n const tag = el.tagName.toLowerCase();\n\n switch (tag) {\n case 'button': return 'button';\n case 'a': return el.hasAttribute('href') ? 'link' : null;\n case 'input': {\n const type = (el.getAttribute('type') || 'text').toLowerCase();\n if (type === 'hidden') return null;\n return INPUT_TYPE_ROLES[type] || 'textbox';\n }\n case 'select': return 'combobox';\n case 'textarea': return 'textbox';\n case 'h1': case 'h2': case 'h3': case 'h4': case 'h5': case 'h6': return 'heading';\n case 'img': return 'img';\n case 'nav': return 'navigation';\n case 'main': return 'main';\n case 'header': return !el.closest('article,aside,main,nav,section') ? 'banner' : null;\n case 'footer': return !el.closest('article,aside,main,nav,section') ? 'contentinfo' : null;\n case 'aside': return 'complementary';\n case 'dialog': return 'dialog';\n case 'form': return 'form';\n case 'section': return (el.hasAttribute('aria-label') || el.hasAttribute('aria-labelledby')) ? 'region' : null;\n case 'summary': return 'button';\n case 'details': return 'group';\n case 'progress': return 'progressbar';\n case 'meter': return 'meter';\n case 'ul': case 'ol': return 'list';\n case 'li': return 'listitem';\n case 'table': return 'table';\n }\n\n if ((el as HTMLElement & { contentEditable: string }).contentEditable === 'true') return 'textbox';\n if (el.hasAttribute('tabindex') && parseInt(el.getAttribute('tabindex') || '-1', 10) >= 0) return 'generic';\n\n return null;\n }\n\n function getAccessibleName(el: HTMLElement, role: string | null): string {\n const ariaLabel = el.getAttribute('aria-label');\n if (ariaLabel) return ariaLabel.trim();\n\n const labelledBy = el.getAttribute('aria-labelledby');\n if (labelledBy) {\n const texts = labelledBy.split(/\\s+/)\n .map(id => document.getElementById(id)?.textContent?.trim() || '')\n .filter(Boolean);\n if (texts.length > 0) return texts.join(' ').slice(0, 100);\n }\n\n const tag = el.tagName.toLowerCase();\n\n if (tag === 'img' || (tag === 'input' && el.getAttribute('type') === 'image')) {\n const alt = el.getAttribute('alt');\n if (alt !== null) return alt.trim();\n }\n\n if (['input', 'select', 'textarea'].includes(tag)) {\n const id = el.getAttribute('id');\n if (id) {\n const label = document.querySelector(`label[for=\"${CSS.escape(id)}\"]`);\n if (label) return label.textContent?.trim() || '';\n }\n const parentLabel = el.closest('label');\n if (parentLabel) {\n const clone = parentLabel.cloneNode(true) as HTMLElement;\n clone.querySelectorAll('input,select,textarea').forEach(n => n.remove());\n const lt = clone.textContent?.trim();\n if (lt) return lt;\n }\n }\n\n const ph = el.getAttribute('placeholder');\n if (ph) return ph.trim();\n\n const title = el.getAttribute('title');\n if (title) return title.trim();\n\n if (role && CONTAINER_ROLES.has(role)) return '';\n return (el.textContent?.trim().replace(/\\s+/g, ' ') || '').slice(0, 100);\n }\n\n function getSelector(element: HTMLElement): string {\n const tag = element.tagName.toLowerCase();\n\n const text = element.textContent?.trim().replace(/\\s+/g, ' ');\n if (text && text.length > 0 && text.length <= 50) {\n const sameTagElements = document.querySelectorAll(tag);\n let matchCount = 0;\n sameTagElements.forEach(el => { if (el.textContent?.includes(text)) matchCount++; });\n if (matchCount === 1) return `${tag}*=${text}`;\n }\n\n const ariaLabel = element.getAttribute('aria-label');\n if (ariaLabel && ariaLabel.length <= 80) return `aria/${ariaLabel}`;\n\n const testId = element.getAttribute('data-testid');\n if (testId) {\n const sel = `[data-testid=\"${CSS.escape(testId)}\"]`;\n if (document.querySelectorAll(sel).length === 1) return sel;\n }\n\n if (element.id) return `#${CSS.escape(element.id)}`;\n\n const nameAttr = element.getAttribute('name');\n if (nameAttr) {\n const sel = `${tag}[name=\"${CSS.escape(nameAttr)}\"]`;\n if (document.querySelectorAll(sel).length === 1) return sel;\n }\n\n if (element.className && typeof element.className === 'string') {\n const classes = element.className.trim().split(/\\s+/).filter(Boolean);\n for (const cls of classes) {\n const sel = `${tag}.${CSS.escape(cls)}`;\n if (document.querySelectorAll(sel).length === 1) return sel;\n }\n if (classes.length >= 2) {\n const sel = `${tag}${classes.slice(0, 2).map(c => `.${CSS.escape(c)}`).join('')}`;\n if (document.querySelectorAll(sel).length === 1) return sel;\n }\n }\n\n let current: HTMLElement | null = element;\n const path: string[] = [];\n while (current && current !== document.documentElement) {\n let seg = current.tagName.toLowerCase();\n if (current.id) { path.unshift(`#${CSS.escape(current.id)}`); break; }\n const parent = current.parentElement;\n if (parent) {\n const siblings = Array.from(parent.children).filter(c => c.tagName === current!.tagName);\n if (siblings.length > 1) seg += `:nth-of-type(${siblings.indexOf(current) + 1})`;\n }\n path.unshift(seg);\n current = current.parentElement;\n if (path.length >= 4) break;\n }\n return path.join(' > ');\n }\n\n function isVisible(el: HTMLElement): boolean {\n if (typeof el.checkVisibility === 'function') {\n return el.checkVisibility({ opacityProperty: true, visibilityProperty: true, contentVisibilityAuto: true });\n }\n const style = window.getComputedStyle(el);\n return style.display !== 'none' &&\n style.visibility !== 'hidden' &&\n style.opacity !== '0' &&\n el.offsetWidth > 0 &&\n el.offsetHeight > 0;\n }\n\n function getLevel(el: HTMLElement): number | undefined {\n const m = el.tagName.toLowerCase().match(/^h([1-6])$/);\n if (m) return parseInt(m[1], 10);\n const ariaLevel = el.getAttribute('aria-level');\n if (ariaLevel) return parseInt(ariaLevel, 10);\n return undefined;\n }\n\n function getState(el: HTMLElement): Record<string, string> {\n const inputEl = el as HTMLInputElement;\n const isCheckable = ['input', 'menuitemcheckbox', 'menuitemradio'].includes(el.tagName.toLowerCase()) ||\n ['checkbox', 'radio', 'switch'].includes(el.getAttribute('role') || '');\n return {\n disabled: (el.getAttribute('aria-disabled') === 'true' || inputEl.disabled) ? 'true' : '',\n checked: (isCheckable && inputEl.checked) ? 'true' : el.getAttribute('aria-checked') || '',\n expanded: el.getAttribute('aria-expanded') || '',\n selected: el.getAttribute('aria-selected') || '',\n pressed: el.getAttribute('aria-pressed') || '',\n required: (inputEl.required || el.getAttribute('aria-required') === 'true') ? 'true' : '',\n readonly: (inputEl.readOnly || el.getAttribute('aria-readonly') === 'true') ? 'true' : '',\n };\n }\n\n type RawNode = Record<string, unknown>;\n\n const result: RawNode[] = [];\n\n function walk(el: HTMLElement, depth = 0): void {\n if (depth > 200) return;\n if (!isVisible(el)) return;\n\n const role = getRole(el);\n\n if (!role) {\n for (const child of Array.from(el.children)) {\n walk(child as HTMLElement, depth + 1);\n }\n return;\n }\n\n const name = getAccessibleName(el, role);\n const isLandmark = LANDMARK_ROLES.has(role);\n const hasIdentity = !!(name || isLandmark);\n const selector = hasIdentity ? getSelector(el) : '';\n const node: RawNode = { role, name, selector, level: getLevel(el) ?? '', ...getState(el) };\n result.push(node);\n\n for (const child of Array.from(el.children)) {\n walk(child as HTMLElement, depth + 1);\n }\n }\n\n for (const child of Array.from(document.body.children)) {\n walk(child as HTMLElement, 0);\n }\n\n return result;\n})();\n\n/**\n * Get browser accessibility tree via a single DOM walk.\n */\nexport async function getBrowserAccessibilityTree(\n browser: WebdriverIO.Browser,\n): Promise<AccessibilityNode[]> {\n return (browser as any).execute(accessibilityTreeScript) as unknown as Promise<AccessibilityNode[]>;\n}\n","import type { ResourceDefinition } from '../types/resource';\nimport { getBrowser } from '../session/state';\nimport sharp from 'sharp';\n\nconst MAX_DIMENSION = 2000;\nconst MAX_FILE_SIZE_BYTES = 1024 * 1024;\n\nasync function processScreenshot(screenshotBase64: string): Promise<{ data: Buffer; mimeType: string }> {\n const inputBuffer = Buffer.from(screenshotBase64, 'base64');\n let image = sharp(inputBuffer);\n const metadata = await image.metadata();\n\n const width = metadata.width ?? 0;\n const height = metadata.height ?? 0;\n\n if (width > MAX_DIMENSION || height > MAX_DIMENSION) {\n const resizeOptions = width > height ? { width: MAX_DIMENSION } : { height: MAX_DIMENSION };\n image = image.resize(resizeOptions);\n }\n\n let outputBuffer = await image.png({ compressionLevel: 9 }).toBuffer();\n\n if (outputBuffer.length > MAX_FILE_SIZE_BYTES) {\n let quality = 90;\n while (quality >= 10 && outputBuffer.length > MAX_FILE_SIZE_BYTES) {\n outputBuffer = await image.jpeg({ quality, mozjpeg: true }).toBuffer();\n quality -= 10;\n }\n return { data: outputBuffer, mimeType: 'image/jpeg' };\n }\n\n return { data: outputBuffer, mimeType: 'image/png' };\n}\n\nasync function readScreenshot(): Promise<{ mimeType: string; blob: string }> {\n try {\n const browser = getBrowser();\n const screenshot = await browser.takeScreenshot();\n const { data, mimeType } = await processScreenshot(screenshot);\n return { mimeType, blob: data.toString('base64') };\n } catch (e) {\n return { mimeType: 'text/plain', blob: Buffer.from(`Error: ${e}`).toString('base64') };\n }\n}\n\nexport const screenshotResource: ResourceDefinition = {\n name: 'session-current-screenshot',\n uri: 'wdio://session/current/screenshot',\n description: 'Screenshot of the current page',\n handler: async () => {\n const result = await readScreenshot();\n return { contents: [{ uri: 'wdio://session/current/screenshot', mimeType: result.mimeType, blob: result.blob }] };\n },\n};","import type { ResourceDefinition } from '../types/resource';\nimport { getBrowser } from '../session/state';\n\nasync function readCookies(name?: string): Promise<{ mimeType: string; text: string }> {\n try {\n const browser = getBrowser();\n\n if (name) {\n const cookie = await browser.getCookies([name]);\n if (cookie.length === 0) {\n return { mimeType: 'application/json', text: JSON.stringify(null) };\n }\n return { mimeType: 'application/json', text: JSON.stringify(cookie[0]) };\n }\n const cookies = await browser.getCookies();\n return { mimeType: 'application/json', text: JSON.stringify(cookies) };\n } catch (e) {\n return { mimeType: 'application/json', text: JSON.stringify({ error: String(e) }) };\n }\n}\n\nexport const cookiesResource: ResourceDefinition = {\n name: 'session-current-cookies',\n uri: 'wdio://session/current/cookies',\n description: 'Cookies for the current session',\n handler: async () => {\n const result = await readCookies();\n return { contents: [{ uri: 'wdio://session/current/cookies', mimeType: result.mimeType, text: result.text }] };\n },\n};","import type { ResourceDefinition } from '../types/resource';\nimport { ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { getBrowser } from '../session/state';\n\nasync function readAppState(bundleId: string): Promise<{ mimeType: string; text: string }> {\n try {\n const browser = getBrowser();\n\n const appIdentifier = browser.isAndroid\n ? { appId: bundleId }\n : { bundleId: bundleId };\n\n const state: string = await browser.execute('mobile: queryAppState', appIdentifier);\n\n const stateMap: Record<string, string> = {\n 0: 'not installed',\n 1: 'not running',\n 2: 'running in background (suspended)',\n 3: 'running in background',\n 4: 'running in foreground',\n };\n\n return {\n mimeType: 'text/plain',\n text: `App state for ${bundleId}: ${stateMap[state] || 'unknown: ' + state}`,\n };\n } catch (e) {\n return { mimeType: 'text/plain', text: `Error getting app state: ${e}` };\n }\n}\n\nexport const appStateResource: ResourceDefinition = {\n name: 'session-current-app-state',\n template: new ResourceTemplate('wdio://session/current/app-state/{bundleId}', { list: undefined }),\n description: 'App state for a given bundle ID',\n handler: async (uri, variables) => {\n const result = await readAppState(variables.bundleId as string);\n return { contents: [{ uri: uri.href, mimeType: result.mimeType, text: result.text }] };\n },\n};","import type { ResourceDefinition } from '../types/resource';\nimport { getBrowser } from '../session/state';\n\nasync function readContexts(): Promise<{ mimeType: string; text: string }> {\n try {\n const browser = getBrowser();\n const contexts = await browser.getContexts();\n return { mimeType: 'application/json', text: JSON.stringify(contexts) };\n } catch (e) {\n return { mimeType: 'text/plain', text: `Error: ${e}` };\n }\n}\n\nasync function readCurrentContext(): Promise<{ mimeType: string; text: string }> {\n try {\n const browser = getBrowser();\n const currentContext = await browser.getContext();\n return { mimeType: 'application/json', text: JSON.stringify(currentContext) };\n } catch (e) {\n return { mimeType: 'text/plain', text: `Error: ${e}` };\n }\n}\n\nexport const contextsResource: ResourceDefinition = {\n name: 'session-current-contexts',\n uri: 'wdio://session/current/contexts',\n description: 'Available contexts (NATIVE_APP, WEBVIEW)',\n handler: async () => {\n const result = await readContexts();\n return { contents: [{ uri: 'wdio://session/current/contexts', mimeType: result.mimeType, text: result.text }] };\n },\n};\n\nexport const contextResource: ResourceDefinition = {\n name: 'session-current-context',\n uri: 'wdio://session/current/context',\n description: 'Currently active context',\n handler: async () => {\n const result = await readCurrentContext();\n return { contents: [{ uri: 'wdio://session/current/context', mimeType: result.mimeType, text: result.text }] };\n },\n};","import type { ResourceDefinition } from '../types/resource';\nimport { getBrowser } from '../session/state';\n\nasync function readGeolocation(): Promise<{ mimeType: string; text: string }> {\n try {\n const browser = getBrowser();\n const location = await browser.getGeoLocation();\n return { mimeType: 'application/json', text: JSON.stringify(location) };\n } catch (e) {\n return { mimeType: 'text/plain', text: `Error: ${e}` };\n }\n}\n\nexport const geolocationResource: ResourceDefinition = {\n name: 'session-current-geolocation',\n uri: 'wdio://session/current/geolocation',\n description: 'Current device geolocation',\n handler: async () => {\n const result = await readGeolocation();\n return { contents: [{ uri: 'wdio://session/current/geolocation', mimeType: result.mimeType, text: result.text }] };\n },\n};","import type { ResourceDefinition } from '../types/resource';\nimport { getBrowser } from '../session/state';\n\nasync function readTabs(): Promise<{ mimeType: string; text: string }> {\n try {\n const browser = getBrowser();\n const handles = await browser.getWindowHandles();\n const currentHandle = await browser.getWindowHandle();\n const tabs = [];\n for (const handle of handles) {\n await browser.switchToWindow(handle);\n tabs.push({\n handle,\n title: await browser.getTitle(),\n url: await browser.getUrl(),\n isActive: handle === currentHandle,\n });\n }\n await browser.switchToWindow(currentHandle);\n return { mimeType: 'application/json', text: JSON.stringify(tabs) };\n } catch (e) {\n return { mimeType: 'text/plain', text: `Error: ${e}` };\n }\n}\n\nexport const tabsResource: ResourceDefinition = {\n name: 'session-current-tabs',\n uri: 'wdio://session/current/tabs',\n description: 'Browser tabs in the current session',\n handler: async () => {\n const result = await readTabs();\n return { contents: [{ uri: 'wdio://session/current/tabs', mimeType: result.mimeType, text: result.text }] };\n },\n};","import { remote } from 'webdriverio';\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ToolDefinition } from '../types/tool';\nimport { z } from 'zod';\nimport type { SessionMetadata } from '../session/state';\nimport { getBrowser, getState } from '../session/state';\nimport { closeSession, registerSession } from '../session/lifecycle';\nimport { getProvider } from '../providers/registry';\nimport { coerceBoolean } from '../utils/zod-helpers';\n\nconst platformEnum = z.enum(['browser', 'ios', 'android']);\nconst browserEnum = z.enum(['chrome', 'firefox', 'edge', 'safari']);\nconst automationEnum = z.enum(['XCUITest', 'UiAutomator2']);\n\nexport const startSessionToolDefinition: ToolDefinition = {\n name: 'start_session',\n description: 'Starts a browser or mobile app session. For local browser, use browser platform. For mobile apps, use ios or android platform. Use attach mode to connect to an existing Chrome instance.',\n inputSchema: {\n provider: z.enum(['local', 'browserstack']).optional().default('local').describe('Session provider (default: local)'),\n platform: platformEnum.describe('Session platform type'),\n browser: browserEnum.optional().describe('Browser to launch (required for browser platform)'),\n browserVersion: z.string().optional().describe('Browser version (BrowserStack only, default: latest)'),\n os: z.string().optional().describe('Operating system (BrowserStack browser only, e.g. \"Windows\", \"OS X\")'),\n osVersion: z.string().optional().describe('OS version (BrowserStack browser only, e.g. \"11\", \"Sequoia\")'),\n app: z.string().optional().describe('BrowserStack app URL (bs://...) or custom_id for mobile sessions'),\n reporting: z.object({\n project: z.string().optional(),\n build: z.string().optional(),\n session: z.string().optional(),\n }).optional().describe('BrowserStack reporting labels (project, build, session)'),\n headless: coerceBoolean.optional().default(true).describe('Run browser in headless mode (default: true)'),\n windowWidth: z.number().min(400).max(3840).optional().default(1920).describe('Browser window width'),\n windowHeight: z.number().min(400).max(2160).optional().default(1080).describe('Browser window height'),\n deviceName: z.string().optional().describe('Mobile device/emulator/simulator name (required for ios/android)'),\n platformVersion: z.string().optional().describe('OS version (e.g., \"17.0\", \"14\")'),\n appPath: z.string().optional().describe('Path to app file (.app/.apk/.ipa)'),\n automationName: automationEnum.optional().describe('Automation driver'),\n autoGrantPermissions: coerceBoolean.optional().describe('Auto-grant app permissions (default: true)'),\n autoAcceptAlerts: coerceBoolean.optional().describe('Auto-accept alerts (default: true)'),\n autoDismissAlerts: coerceBoolean.optional().describe('Auto-dismiss alerts (default: false)'),\n appWaitActivity: z.string().optional().describe('Activity to wait for on Android launch'),\n udid: z.string().optional().describe('Unique Device Identifier for iOS real device'),\n noReset: coerceBoolean.optional().describe('Preserve app data between sessions'),\n fullReset: coerceBoolean.optional().describe('Uninstall app before/after session'),\n newCommandTimeout: z.number().min(0).optional().default(300).describe('Appium command timeout in seconds'),\n attach: coerceBoolean.optional().default(false).describe('Attach to existing Chrome instead of launching'),\n attachConfig: z.object({\n port: z.number().optional().default(9222),\n host: z.string().optional().default('localhost'),\n }).optional().describe('Chrome remote debugging connection (attach mode only, defaults: port 9222, host localhost)'),\n appiumConfig: z.object({\n host: z.string().optional(),\n port: z.number().optional(),\n path: z.string().optional(),\n }).optional().describe('Appium server connection (local provider only)'),\n browserstackLocal: z.union([coerceBoolean, z.literal('external')]).optional().default(false).describe('Enable BrowserStack Local tunnel routing (BrowserStack only, default: false). true = auto-start tunnel before session and stop on close. \"external\" = tunnel already running externally, set local: true in capabilities only.'),\n navigationUrl: z.string().optional().describe('URL to navigate to after starting'),\n capabilities: z.record(z.string(), z.unknown()).optional().describe('Additional capabilities to merge'),\n },\n};\n\ntype StartSessionArgs = {\n provider?: 'local' | 'browserstack';\n platform: 'browser' | 'ios' | 'android';\n browser?: 'chrome' | 'firefox' | 'edge' | 'safari';\n browserVersion?: string;\n os?: string;\n osVersion?: string;\n app?: string;\n reporting?: { project?: string; build?: string; session?: string };\n headless?: boolean;\n windowWidth?: number;\n windowHeight?: number;\n deviceName?: string;\n platformVersion?: string;\n appPath?: string;\n automationName?: 'XCUITest' | 'UiAutomator2';\n autoGrantPermissions?: boolean;\n autoAcceptAlerts?: boolean;\n autoDismissAlerts?: boolean;\n appWaitActivity?: string;\n udid?: string;\n noReset?: boolean;\n fullReset?: boolean;\n newCommandTimeout?: number;\n attach?: boolean;\n attachConfig?: { port?: number; host?: string };\n appiumConfig?: { host?: string; port?: number; path?: string };\n browserstackLocal?: boolean | 'external';\n navigationUrl?: string;\n capabilities?: Record<string, unknown>;\n};\n\nexport const closeSessionToolDefinition: ToolDefinition = {\n name: 'close_session',\n description: 'Closes or detaches from the current browser or app session',\n inputSchema: {\n detach: coerceBoolean.optional().describe('If true, disconnect without terminating (preserves app state). Default: false'),\n },\n};\n\ntype TabSnapshot = { activeTabUrl: string | undefined; allTabUrls: string[] };\n\nasync function closeStaleMappers(host: string, port: number): Promise<TabSnapshot> {\n try {\n const res = await fetch(`http://${host}:${port}/json`);\n const targets = await res.json() as { id: string; title: string; type: string; url: string }[];\n const mappers = targets.filter((t) => t.title?.includes('BiDi'));\n await Promise.all(mappers.map((t) => fetch(`http://${host}:${port}/json/close/${t.id}`)));\n const pages = targets.filter((t) => t.type === 'page' && !t.title?.includes('BiDi'));\n return { activeTabUrl: pages[0]?.url, allTabUrls: pages.map((t) => t.url) };\n } catch {\n return { activeTabUrl: undefined, allTabUrls: [] };\n }\n}\n\nasync function restoreAndSwitchToActiveTab(browser: WebdriverIO.Browser, activeTabUrl: string, allTabUrls: string[]): Promise<void> {\n const handles = await browser.getWindowHandles();\n const currentUrls: string[] = [];\n for (const handle of handles) {\n await browser.switchToWindow(handle);\n currentUrls.push(await browser.getUrl());\n }\n\n const missingUrls = allTabUrls.filter((u) => !currentUrls.includes(u));\n let missingIdx = 0;\n for (let i = 0; i < handles.length; i++) {\n if (currentUrls[i] === 'about:blank' && missingIdx < missingUrls.length) {\n await browser.switchToWindow(handles[i]);\n await browser.url(missingUrls[missingIdx]);\n currentUrls[i] = missingUrls[missingIdx++];\n }\n }\n\n for (let i = 0; i < handles.length; i++) {\n if (currentUrls[i] === activeTabUrl) {\n await browser.switchToWindow(handles[i]);\n break;\n }\n }\n}\n\nasync function waitForCDP(host: string, port: number, timeoutMs = 10000): Promise<void> {\n const deadline = Date.now() + timeoutMs;\n while (Date.now() < deadline) {\n try {\n const res = await fetch(`http://${host}:${port}/json/version`);\n if (res.ok) return;\n } catch {\n // not ready yet\n }\n await new Promise((r) => setTimeout(r, 300));\n }\n throw new Error(`Chrome did not expose CDP on ${host}:${port} within ${timeoutMs}ms`);\n}\n\nasync function startBrowserSession(args: StartSessionArgs): Promise<CallToolResult> {\n const {\n browser = 'chrome',\n headless = true,\n windowWidth = 1920,\n windowHeight = 1080,\n navigationUrl,\n capabilities: userCapabilities = {},\n } = args;\n\n const browserDisplayNames: Record<string, string> = {\n chrome: 'Chrome',\n firefox: 'Firefox',\n edge: 'Edge',\n safari: 'Safari',\n };\n\n const headlessSupported = browser !== 'safari';\n const effectiveHeadless = headless && headlessSupported;\n\n const provider = getProvider(args.provider ?? 'local', 'browser');\n const connectionConfig = provider.getConnectionConfig(args as Record<string, unknown>);\n const mergedCapabilities = provider.buildCapabilities({\n ...args as Record<string, unknown>,\n browser,\n headless,\n windowWidth,\n windowHeight,\n capabilities: userCapabilities,\n });\n\n const tunnelHandle = args.browserstackLocal === true\n ? await provider.startTunnel?.(args as Record<string, unknown>)\n : undefined;\n\n const wdioBrowser = await remote({ ...connectionConfig, capabilities: mergedCapabilities });\n const { sessionId } = wdioBrowser;\n\n const sessionMetadata: SessionMetadata = {\n type: 'browser',\n capabilities: mergedCapabilities,\n isAttached: false,\n provider: args.provider ?? 'local',\n tunnelHandle,\n };\n\n registerSession(sessionId, wdioBrowser, sessionMetadata, {\n sessionId,\n type: 'browser',\n startedAt: new Date().toISOString(),\n capabilities: mergedCapabilities,\n steps: [],\n });\n\n let sizeNote = '';\n try {\n await wdioBrowser.setWindowSize(windowWidth, windowHeight);\n } catch (e) {\n sizeNote = `\\nNote: Unable to set window size (${windowWidth}x${windowHeight}). ${e}`;\n }\n\n if (navigationUrl) {\n await wdioBrowser.url(navigationUrl);\n }\n\n const modeText = effectiveHeadless ? 'headless' : 'headed';\n const urlText = navigationUrl ? ` and navigated to ${navigationUrl}` : '';\n const headlessNote = headless && !headlessSupported\n ? '\\nNote: Safari does not support headless mode. Started in headed mode.'\n : '';\n\n return {\n content: [{\n type: 'text',\n text: `${browserDisplayNames[browser]} browser started in ${modeText} mode with sessionId: ${sessionId} (${windowWidth}x${windowHeight})${urlText}${headlessNote}${sizeNote}`,\n }],\n };\n}\n\nasync function startMobileSession(args: StartSessionArgs): Promise<CallToolResult> {\n const { platform, appPath, app, deviceName, noReset } = args;\n\n if (!appPath && !app && noReset !== true) {\n return {\n content: [{\n type: 'text',\n text: 'Error: Either \"appPath\" must be provided to install an app, or \"noReset: true\" must be set to connect to an already-running app.',\n }],\n };\n }\n\n const provider = getProvider(args.provider ?? 'local', args.platform);\n const serverConfig = provider.getConnectionConfig(args as Record<string, unknown>);\n const mergedCapabilities = provider.buildCapabilities(args as Record<string, unknown>);\n\n const tunnelHandle = args.browserstackLocal === true\n ? await provider.startTunnel?.(args as Record<string, unknown>)\n : undefined;\n\n const browser = await remote({ ...serverConfig, capabilities: mergedCapabilities });\n\n const { sessionId } = browser;\n const shouldAutoDetach = provider.shouldAutoDetach(args as Record<string, unknown>);\n const sessionType = provider.getSessionType(args as Record<string, unknown>);\n\n const metadata: SessionMetadata = {\n type: sessionType,\n capabilities: mergedCapabilities,\n isAttached: shouldAutoDetach,\n provider: args.provider ?? 'local',\n tunnelHandle,\n };\n\n registerSession(sessionId, browser, metadata, {\n sessionId,\n type: sessionType,\n startedAt: new Date().toISOString(),\n capabilities: mergedCapabilities,\n appiumConfig: { hostname: serverConfig.hostname, port: serverConfig.port, path: serverConfig.path },\n steps: [],\n });\n\n const appInfo = appPath ? `\\nApp: ${appPath}` : '\\nApp: (connected to running app)';\n const detachNote = shouldAutoDetach\n ? '\\n\\n(Auto-detach enabled: session will be preserved on close. Use close_session({ detach: false }) to force terminate.)'\n : '';\n\n return {\n content: [\n {\n type: 'text',\n text: `${platform} app session started with sessionId: ${sessionId}\\nDevice: ${deviceName}${appInfo}\\nAppium Server: ${serverConfig.hostname}:${serverConfig.port}${serverConfig.path}${detachNote}`,\n },\n ],\n };\n}\n\nasync function attachBrowserSession(args: StartSessionArgs): Promise<CallToolResult> {\n const { port = 9222, host = 'localhost' } = args.attachConfig ?? {};\n const { navigationUrl } = args;\n\n await waitForCDP(host, port);\n const { activeTabUrl, allTabUrls } = await closeStaleMappers(host, port);\n\n const capabilities = {\n browserName: 'chrome',\n unhandledPromptBehavior: 'dismiss',\n webSocketUrl: false,\n 'goog:chromeOptions': {\n debuggerAddress: `${host}:${port}`,\n },\n };\n\n const browser = await remote({\n connectionRetryTimeout: 30000,\n connectionRetryCount: 3,\n capabilities,\n });\n\n const { sessionId } = browser;\n\n const sessionMetadata: SessionMetadata = {\n type: 'browser',\n capabilities,\n isAttached: true,\n provider: 'local',\n };\n\n registerSession(sessionId, browser, sessionMetadata, {\n sessionId,\n type: 'browser',\n startedAt: new Date().toISOString(),\n capabilities,\n steps: [],\n });\n\n if (navigationUrl) {\n await browser.url(navigationUrl);\n } else if (activeTabUrl) {\n await restoreAndSwitchToActiveTab(browser, activeTabUrl, allTabUrls);\n }\n\n const title = await browser.getTitle();\n const url = await browser.getUrl();\n\n return {\n content: [{\n type: 'text',\n text: `Attached to Chrome on ${host}:${port}\\nSession ID: ${sessionId}\\nCurrent page: \"${title}\" (${url})`,\n }],\n };\n}\n\nexport const startSessionTool: ToolCallback = async (args: StartSessionArgs): Promise<CallToolResult> => {\n try {\n if (args.platform === 'browser') {\n if (args.attach) {\n return await attachBrowserSession(args);\n }\n return await startBrowserSession(args);\n }\n return await startMobileSession(args);\n } catch (e) {\n return { isError: true, content: [{ type: 'text', text: `Error starting session: ${e}` }] };\n }\n};\n\nexport const closeSessionTool: ToolCallback = async (args: { detach?: boolean } = {}): Promise<CallToolResult> => {\n try {\n getBrowser();\n const state = getState();\n const sessionId = state.currentSession;\n const metadata = state.sessionMetadata.get(sessionId);\n\n const isAttached = !!metadata?.isAttached;\n const detach = args.detach ?? false;\n\n // Determine if this is a force-close (auto-detached session + explicit close)\n const force = !detach && isAttached;\n\n const effectiveDetach = detach || isAttached;\n await closeSession(sessionId, detach, isAttached, force);\n\n const action = effectiveDetach && !force ? 'detached from' : 'closed';\n const note = detach && !isAttached\n ? '\\nNote: Session will remain active on Appium server.'\n : '';\n\n return {\n content: [{ type: 'text', text: `Session ${sessionId} ${action}${note}` }],\n };\n } catch (e) {\n return { isError: true, content: [{ type: 'text', text: `Error closing session: ${e}` }] };\n }\n};\n","import type { SessionHistory } from '../types/recording';\nimport type { SessionResult } from '../providers/types';\nimport type { SessionMetadata } from './state';\nimport { getState } from './state';\nimport { getProvider } from '../providers/registry';\n\nfunction getSessionResult(history: SessionHistory | undefined): SessionResult {\n const errorStep = history?.steps.find(s => s.status === 'error');\n return errorStep\n ? { status: 'failed', reason: errorStep.error }\n : { status: 'passed' };\n}\n\nexport function handleSessionTransition(newSessionId: string): void {\n const state = getState();\n if (state.currentSession && state.currentSession !== newSessionId) {\n const outgoing = state.sessionHistory.get(state.currentSession);\n if (outgoing) {\n outgoing.steps.push({\n index: outgoing.steps.length + 1,\n tool: '__session_transition__',\n params: { newSessionId },\n status: 'ok',\n durationMs: 0,\n timestamp: new Date().toISOString(),\n });\n outgoing.endedAt = new Date().toISOString();\n }\n }\n}\n\nexport function registerSession(\n sessionId: string,\n browser: WebdriverIO.Browser,\n metadata: SessionMetadata,\n historyEntry: SessionHistory,\n): void {\n const state = getState();\n const oldSessionId = state.currentSession;\n if (oldSessionId && oldSessionId !== sessionId) {\n handleSessionTransition(sessionId);\n }\n state.browsers.set(sessionId, browser);\n state.sessionMetadata.set(sessionId, metadata);\n state.sessionHistory.set(sessionId, historyEntry);\n state.currentSession = sessionId;\n\n // If there was a previous session, terminate it to prevent orphaning\n if (oldSessionId && oldSessionId !== sessionId) {\n const oldBrowser = state.browsers.get(oldSessionId);\n const oldMetadata = state.sessionMetadata.get(oldSessionId);\n if (oldBrowser) {\n // Fire and forget — don't block registration on close\n void (async () => {\n if (oldMetadata?.provider) {\n const oldHistory = state.sessionHistory.get(oldSessionId);\n const provider = getProvider(oldMetadata.provider, oldMetadata.type);\n await provider.onSessionClose?.(oldSessionId, oldMetadata.type, getSessionResult(oldHistory), oldMetadata.tunnelHandle).catch(() => {});\n }\n await oldBrowser.deleteSession().catch(() => {\n // Ignore errors during force-close of orphaned session\n });\n })();\n state.browsers.delete(oldSessionId);\n state.sessionMetadata.delete(oldSessionId);\n }\n }\n}\n\nexport async function closeSession(sessionId: string, detach: boolean, isAttached: boolean, force?: boolean): Promise<void> {\n const state = getState();\n const browser = state.browsers.get(sessionId);\n if (!browser) return;\n\n const history = state.sessionHistory.get(sessionId);\n if (history) {\n history.endedAt = new Date().toISOString();\n }\n\n const metadata = state.sessionMetadata.get(sessionId);\n\n // Terminate the WebDriver session if:\n // - force is true (override), OR\n // - detach is false AND isAttached is false (normal close)\n if (force || (!detach && !isAttached)) {\n if (metadata?.provider) {\n try {\n const provider = getProvider(metadata.provider, metadata.type);\n await provider.onSessionClose?.(sessionId, metadata.type, getSessionResult(history), metadata.tunnelHandle);\n } catch (e) {\n console.error('[WARN] Failed to run provider onSessionClose:', e);\n }\n }\n await browser.deleteSession();\n }\n\n state.browsers.delete(sessionId);\n state.sessionMetadata.delete(sessionId);\n\n // Only clear currentSession if it matches the session being closed\n if (state.currentSession === sessionId) {\n state.currentSession = null;\n }\n}\n","import type { SessionProvider, ConnectionConfig } from './types';\n\nexport type LocalBrowserOptions = {\n browser?: 'chrome' | 'firefox' | 'edge' | 'safari';\n headless?: boolean;\n windowWidth?: number;\n windowHeight?: number;\n capabilities?: Record<string, unknown>;\n};\n\nexport class LocalBrowserProvider implements SessionProvider {\n name = 'local-browser';\n\n getConnectionConfig(_options: Record<string, unknown>): ConnectionConfig {\n return {}; // local — use WebdriverIO defaults\n }\n\n buildCapabilities(options: Record<string, unknown>): Record<string, unknown> {\n const selectedBrowser = (options.browser as string | undefined) ?? 'chrome';\n const headless = (options.headless as boolean | undefined) ?? true;\n const windowWidth = (options.windowWidth as number | undefined) ?? 1920;\n const windowHeight = (options.windowHeight as number | undefined) ?? 1080;\n const userCapabilities = (options.capabilities as Record<string, unknown> | undefined) ?? {};\n\n const headlessSupported = selectedBrowser !== 'safari';\n const effectiveHeadless = headless && headlessSupported;\n\n const chromiumArgs = [\n `--window-size=${windowWidth},${windowHeight}`,\n '--no-sandbox',\n '--disable-search-engine-choice-screen',\n '--disable-infobars',\n '--log-level=3',\n '--use-fake-device-for-media-stream',\n '--use-fake-ui-for-media-stream',\n '--disable-web-security',\n '--allow-running-insecure-content',\n ];\n\n if (effectiveHeadless) {\n chromiumArgs.push('--headless=new');\n chromiumArgs.push('--disable-gpu');\n chromiumArgs.push('--disable-dev-shm-usage');\n }\n\n const firefoxArgs: string[] = [];\n if (effectiveHeadless && selectedBrowser === 'firefox') {\n firefoxArgs.push('-headless');\n }\n\n const capabilities: Record<string, any> = {\n acceptInsecureCerts: true,\n };\n\n switch (selectedBrowser) {\n case 'chrome':\n capabilities.browserName = 'chrome';\n capabilities['goog:chromeOptions'] = { args: chromiumArgs };\n break;\n case 'edge':\n capabilities.browserName = 'msedge';\n capabilities['ms:edgeOptions'] = { args: chromiumArgs };\n break;\n case 'firefox':\n capabilities.browserName = 'firefox';\n if (firefoxArgs.length > 0) {\n capabilities['moz:firefoxOptions'] = { args: firefoxArgs };\n }\n break;\n case 'safari':\n capabilities.browserName = 'safari';\n break;\n }\n\n const mergedCapabilities: Record<string, unknown> = {\n ...capabilities,\n ...userCapabilities,\n 'goog:chromeOptions': this.mergeCapabilityOptions(capabilities['goog:chromeOptions'], userCapabilities['goog:chromeOptions']),\n 'ms:edgeOptions': this.mergeCapabilityOptions(capabilities['ms:edgeOptions'], userCapabilities['ms:edgeOptions']),\n 'moz:firefoxOptions': this.mergeCapabilityOptions(capabilities['moz:firefoxOptions'], userCapabilities['moz:firefoxOptions']),\n };\n\n for (const [key, value] of Object.entries(mergedCapabilities)) {\n if (value === undefined) {\n delete mergedCapabilities[key];\n }\n }\n\n return mergedCapabilities;\n }\n\n getSessionType(_options: Record<string, unknown>): 'browser' {\n return 'browser';\n }\n\n shouldAutoDetach(_options: Record<string, unknown>): boolean {\n return false;\n }\n\n private mergeCapabilityOptions(defaultOptions: unknown, customOptions: unknown): unknown {\n if (!defaultOptions || typeof defaultOptions !== 'object' || !customOptions || typeof customOptions !== 'object') {\n return customOptions ?? defaultOptions;\n }\n\n const defaultRecord = defaultOptions as Record<string, unknown>;\n const customRecord = customOptions as Record<string, unknown>;\n const merged = { ...defaultRecord, ...customRecord };\n if (Array.isArray(defaultRecord.args) || Array.isArray(customRecord.args)) {\n merged.args = [\n ...(Array.isArray(defaultRecord.args) ? defaultRecord.args : []),\n ...(Array.isArray(customRecord.args) ? customRecord.args : []),\n ];\n }\n return merged;\n }\n}\n\nexport const localBrowserProvider = new LocalBrowserProvider();\n","/**\n * Appium server configuration and capability builders\n */\n\nexport interface AppiumServerConfig {\n hostname: string;\n port: number;\n path: string;\n}\n\nexport interface IOSCapabilityOptions {\n deviceName: string;\n platformVersion?: string;\n automationName?: 'XCUITest';\n autoGrantPermissions?: boolean;\n autoAcceptAlerts?: boolean;\n autoDismissAlerts?: boolean;\n udid?: string;\n noReset?: boolean;\n fullReset?: boolean;\n newCommandTimeout?: number;\n\n [key: string]: any;\n}\n\nexport interface AndroidCapabilityOptions {\n deviceName: string;\n platformVersion?: string;\n automationName?: 'UiAutomator2' | 'Espresso';\n autoGrantPermissions?: boolean;\n autoAcceptAlerts?: boolean;\n autoDismissAlerts?: boolean;\n appWaitActivity?: string;\n noReset?: boolean;\n fullReset?: boolean;\n newCommandTimeout?: number;\n\n [key: string]: any;\n}\n\n/**\n * Get Appium server configuration from environment variables or defaults\n */\nexport function getAppiumServerConfig(overrides?: Partial<AppiumServerConfig>): AppiumServerConfig {\n return {\n hostname: overrides?.hostname || process.env.APPIUM_URL || '127.0.0.1',\n port: overrides?.port || Number(process.env.APPIUM_URL_PORT) || 4723,\n path: overrides?.path || process.env.APPIUM_PATH || '/',\n };\n}\n\n/**\n * Build iOS capabilities for Appium session\n */\nexport function buildIOSCapabilities(\n appPath: string | undefined,\n options: IOSCapabilityOptions,\n): Record<string, any> {\n const capabilities: Record<string, any> = {\n platformName: 'iOS',\n 'appium:platformVersion': options.platformVersion,\n 'appium:deviceName': options.deviceName,\n 'appium:automationName': options.automationName || 'XCUITest',\n };\n\n // Only set app path if provided (allows connecting to already-running app)\n if (appPath) {\n capabilities['appium:app'] = appPath;\n }\n\n // Set UDID for real device testing (required for physical iOS devices)\n if (options.udid) {\n capabilities['appium:udid'] = options.udid;\n }\n\n // Set reset behavior (for preserving app state)\n if (options.noReset !== undefined) {\n capabilities['appium:noReset'] = options.noReset;\n }\n if (options.fullReset !== undefined) {\n capabilities['appium:fullReset'] = options.fullReset;\n }\n\n // Set session timeout (how long Appium waits for new commands)\n if (options.newCommandTimeout !== undefined) {\n capabilities['appium:newCommandTimeout'] = options.newCommandTimeout;\n }\n\n capabilities['appium:autoGrantPermissions'] = options.autoGrantPermissions ?? true;\n capabilities['appium:autoAcceptAlerts'] = options.autoAcceptAlerts ?? true;\n\n if (options.autoDismissAlerts !== undefined) {\n capabilities['appium:autoDismissAlerts'] = options.autoDismissAlerts;\n capabilities['appium:autoAcceptAlerts'] = undefined;\n }\n\n // Add any additional custom options\n for (const [key, value] of Object.entries(options)) {\n if (\n !['deviceName', 'platformVersion', 'automationName', 'autoGrantPermissions', 'autoAcceptAlerts', 'autoDismissAlerts', 'udid', 'noReset', 'fullReset', 'newCommandTimeout'].includes(\n key,\n )\n ) {\n capabilities[`appium:${key}`] = value;\n }\n }\n\n return capabilities;\n}\n\n/**\n * Build Android capabilities for Appium session\n */\nexport function buildAndroidCapabilities(\n appPath: string | undefined,\n options: AndroidCapabilityOptions,\n): Record<string, any> {\n const capabilities: Record<string, any> = {\n platformName: 'Android',\n 'appium:platformVersion': options.platformVersion,\n 'appium:deviceName': options.deviceName,\n 'appium:automationName': options.automationName || 'UiAutomator2',\n };\n\n // Only set app path if provided (allows connecting to already-running app)\n if (appPath) {\n capabilities['appium:app'] = appPath;\n }\n\n // Set reset behavior (for preserving app state)\n if (options.noReset !== undefined) {\n capabilities['appium:noReset'] = options.noReset;\n }\n if (options.fullReset !== undefined) {\n capabilities['appium:fullReset'] = options.fullReset;\n }\n\n // Set session timeout (how long Appium waits for new commands)\n if (options.newCommandTimeout !== undefined) {\n capabilities['appium:newCommandTimeout'] = options.newCommandTimeout;\n }\n\n // Optional Android-specific settings\n capabilities['appium:autoGrantPermissions'] = options.autoGrantPermissions ?? true;\n capabilities['appium:autoAcceptAlerts'] = options.autoAcceptAlerts ?? true;\n\n if (options.autoDismissAlerts !== undefined) {\n capabilities['appium:autoDismissAlerts'] = options.autoDismissAlerts;\n capabilities['appium:autoAcceptAlerts'] = undefined;\n }\n\n if (options.appWaitActivity) {\n capabilities['appium:appWaitActivity'] = options.appWaitActivity;\n }\n\n // Add any additional custom options\n for (const [key, value] of Object.entries(options)) {\n if (\n !['deviceName', 'platformVersion', 'automationName', 'autoGrantPermissions', 'autoAcceptAlerts', 'autoDismissAlerts', 'appWaitActivity', 'noReset', 'fullReset', 'newCommandTimeout'].includes(\n key,\n )\n ) {\n capabilities[`appium:${key}`] = value;\n }\n }\n\n return capabilities;\n}\n","import type { SessionProvider, ConnectionConfig } from './types';\nimport { buildIOSCapabilities, buildAndroidCapabilities, getAppiumServerConfig } from '../config/appium.config';\n\nexport type LocalAppiumOptions = {\n platform: 'iOS' | 'Android';\n appPath?: string;\n deviceName: string;\n platformVersion?: string;\n automationName?: string;\n appiumConfig?: { host?: string; port?: number; path?: string };\n autoGrantPermissions?: boolean;\n autoAcceptAlerts?: boolean;\n autoDismissAlerts?: boolean;\n appWaitActivity?: string;\n udid?: string;\n noReset?: boolean;\n fullReset?: boolean;\n newCommandTimeout?: number;\n capabilities?: Record<string, unknown>;\n};\n\nexport class LocalAppiumProvider implements SessionProvider {\n name = 'local-appium';\n\n getConnectionConfig(options: Record<string, unknown>): ConnectionConfig {\n const appiumConfig = options.appiumConfig as { host?: string; port?: number; path?: string } | undefined;\n const config = getAppiumServerConfig({\n hostname: appiumConfig?.host,\n port: appiumConfig?.port,\n path: appiumConfig?.path,\n });\n return { protocol: 'http', ...config };\n }\n\n buildCapabilities(options: Record<string, unknown>): Record<string, unknown> {\n const platform = options.platform as string;\n const appPath = options.appPath as string | undefined;\n const deviceName = options.deviceName as string;\n const platformVersion = options.platformVersion as string | undefined;\n const autoGrantPermissions = options.autoGrantPermissions as boolean | undefined;\n const autoAcceptAlerts = options.autoAcceptAlerts as boolean | undefined;\n const autoDismissAlerts = options.autoDismissAlerts as boolean | undefined;\n const udid = options.udid as string | undefined;\n const noReset = options.noReset as boolean | undefined;\n const fullReset = options.fullReset as boolean | undefined;\n const newCommandTimeout = options.newCommandTimeout as number | undefined;\n const appWaitActivity = options.appWaitActivity as string | undefined;\n const userCapabilities = (options.capabilities as Record<string, unknown> | undefined) ?? {};\n\n const capabilities: Record<string, any> = platform === 'iOS'\n ? buildIOSCapabilities(appPath, {\n deviceName,\n platformVersion,\n automationName: (options.automationName as 'XCUITest') || 'XCUITest',\n autoGrantPermissions,\n autoAcceptAlerts,\n autoDismissAlerts,\n udid,\n noReset,\n fullReset,\n newCommandTimeout,\n })\n : buildAndroidCapabilities(appPath, {\n deviceName,\n platformVersion,\n automationName: (options.automationName as 'UiAutomator2' | 'Espresso') || 'UiAutomator2',\n autoGrantPermissions,\n autoAcceptAlerts,\n autoDismissAlerts,\n appWaitActivity,\n noReset,\n fullReset,\n newCommandTimeout,\n });\n\n const mergedCapabilities = {\n ...capabilities,\n ...userCapabilities,\n };\n\n for (const [key, value] of Object.entries(mergedCapabilities)) {\n if (value === undefined) {\n delete mergedCapabilities[key];\n }\n }\n\n return mergedCapabilities;\n }\n\n getSessionType(options: Record<string, unknown>): 'ios' | 'android' {\n const platform = options.platform as string;\n return platform.toLowerCase() as 'ios' | 'android';\n }\n\n shouldAutoDetach(options: Record<string, unknown>): boolean {\n return options.noReset === true || !options.appPath;\n }\n}\n\nexport const localAppiumProvider = new LocalAppiumProvider();\n","import { promisify } from 'node:util';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport { Local as BrowserstackTunnel } from 'browserstack-local';\nimport type { ConnectionConfig, SessionProvider, SessionResult } from '../types';\n\nexport class BrowserStackProvider implements SessionProvider {\n name = 'browserstack';\n\n getConnectionConfig(options: Record<string, unknown>): ConnectionConfig {\n const platform = options.platform as string;\n const hostname = platform === 'browser' ? 'hub.browserstack.com' : 'hub-cloud.browserstack.com';\n return {\n protocol: 'https',\n hostname,\n port: 443,\n path: '/wd/hub',\n user: process.env.BROWSERSTACK_USERNAME,\n key: process.env.BROWSERSTACK_ACCESS_KEY,\n };\n }\n\n buildCapabilities(options: Record<string, unknown>): Record<string, unknown> {\n const platform = options.platform as string;\n const userCapabilities = (options.capabilities as Record<string, unknown> | undefined) ?? {};\n\n const browserstackLocal = options.browserstackLocal as boolean | undefined;\n\n if (platform === 'browser') {\n const bstackOptions: Record<string, unknown> = {\n browserVersion: (options.browserVersion as string | undefined) ?? 'latest',\n };\n if (options.os) bstackOptions.os = options.os;\n if (options.osVersion) bstackOptions.osVersion = options.osVersion;\n if (browserstackLocal) bstackOptions.local = true;\n\n const reporting = options.reporting as { project?: string; build?: string; session?: string } | undefined;\n\n if (reporting?.project) bstackOptions.projectName = reporting.project;\n if (reporting?.build) bstackOptions.buildName = reporting.build;\n if (reporting?.session) bstackOptions.sessionName = reporting.session;\n\n return {\n browserName: (options.browser as string | undefined) ?? 'chrome',\n 'bstack:options': bstackOptions,\n ...userCapabilities,\n };\n }\n\n // Mobile (ios / android)\n const bstackOptions: Record<string, unknown> = {\n platformName: platform,\n deviceName: options.deviceName,\n platformVersion: options.platformVersion,\n deviceType: 'phone',\n appiumVersion: '3.1.0',\n };\n if (browserstackLocal) bstackOptions.local = true;\n const reporting = options.reporting as { project?: string; build?: string; session?: string } | undefined;\n if (reporting?.project) bstackOptions.projectName = reporting.project;\n if (reporting?.build) bstackOptions.buildName = reporting.build;\n if (reporting?.session) bstackOptions.sessionName = reporting.session;\n\n const autoAcceptAlerts = options.autoAcceptAlerts as boolean | undefined;\n const autoDismissAlerts = options.autoDismissAlerts as boolean | undefined;\n\n return {\n platformName: platform,\n 'appium:app': options.app,\n 'appium:autoGrantPermissions': (options.autoGrantPermissions as boolean | undefined) ?? true,\n 'appium:autoAcceptAlerts': autoDismissAlerts ? undefined : (autoAcceptAlerts ?? true),\n 'appium:autoDismissAlerts': autoDismissAlerts,\n 'appium:newCommandTimeout': (options.newCommandTimeout as number | undefined) ?? 300,\n 'bstack:options': bstackOptions,\n ...userCapabilities,\n };\n }\n\n getSessionType(options: Record<string, unknown>): 'browser' | 'ios' | 'android' {\n const platform = options.platform as string;\n if (platform === 'browser') return 'browser';\n return platform as 'ios' | 'android';\n }\n\n shouldAutoDetach(_options: Record<string, unknown>): boolean {\n return false;\n }\n\n async startTunnel(_options: Record<string, unknown>): Promise<unknown> {\n const key = process.env.BROWSERSTACK_ACCESS_KEY ?? '';\n const tunnel = new BrowserstackTunnel();\n const start = promisify(tunnel.start.bind(tunnel));\n try {\n const logFile = join(tmpdir(), 'browserstack-local.log');\n await start({ key, forceLocal: true, logFile });\n } catch (e: unknown) {\n const msg = (e !== null && typeof e === 'object' ? (e as { message?: string }).message : undefined) ?? String(e);\n if (msg.includes('another browserstack local client is running') || msg.includes('server is listening on port')) {\n console.error('[BrowserStack] Tunnel already running — reusing existing tunnel');\n return null;\n }\n throw e;\n }\n return tunnel;\n }\n\n async onSessionClose(\n sessionId: string,\n sessionType: 'browser' | 'ios' | 'android',\n result: SessionResult,\n tunnelHandle?: unknown,\n ): Promise<void> {\n if (tunnelHandle) {\n const tunnel = tunnelHandle as InstanceType<typeof BrowserstackTunnel>;\n const stop = promisify(tunnel.stop.bind(tunnel));\n await stop();\n }\n\n const user = process.env.BROWSERSTACK_USERNAME;\n const key = process.env.BROWSERSTACK_ACCESS_KEY;\n if (!user || !key) return;\n\n const baseUrl = sessionType === 'browser'\n ? 'https://api.browserstack.com/automate/sessions'\n : 'https://api-cloud.browserstack.com/app-automate/sessions';\n\n const auth = Buffer.from(`${user}:${key}`).toString('base64');\n const body: Record<string, string> = { status: result.status, ...(result.reason ? { reason: result.reason } : {}) };\n await fetch(`${baseUrl}/${sessionId}.json`, {\n method: 'PUT',\n headers: { Authorization: `Basic ${auth}`, 'Content-Type': 'application/json' },\n body: JSON.stringify(body),\n });\n }\n}\n\nexport const browserStackProvider = new BrowserStackProvider();\n","import type { SessionProvider } from './types';\nimport { localBrowserProvider } from './local-browser.provider';\nimport { localAppiumProvider } from './local-appium.provider';\nimport { browserStackProvider } from './cloud/browserstack.provider';\n\nexport function getProvider(providerName: string, platform: string): SessionProvider {\n if (providerName === 'browserstack') return browserStackProvider;\n return platform === 'browser' ? localBrowserProvider : localAppiumProvider;\n}\n","import type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport type { ToolDefinition } from '../types/tool';\nimport { z } from 'zod';\nimport { getBrowser } from '../session/state';\n\nexport const switchTabToolDefinition: ToolDefinition = {\n name: 'switch_tab',\n description: 'switches to a browser tab by handle or index',\n inputSchema: {\n handle: z.string().optional().describe('Window handle to switch to'),\n index: z.number().int().min(0).optional().describe('0-based tab index to switch to'),\n },\n};\n\nexport const switchTabTool: ToolCallback = async ({ handle, index }: { handle?: string; index?: number }): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n if (handle) {\n await browser.switchToWindow(handle);\n return { content: [{ type: 'text', text: `Switched to tab: ${handle}` }] };\n } else if (index !== undefined) {\n const handles = await browser.getWindowHandles();\n if (index >= handles.length) {\n return { isError: true, content: [{ type: 'text', text: `Error: index ${index} out of range (${handles.length} tabs)` }] };\n }\n await browser.switchToWindow(handles[index]);\n return { content: [{ type: 'text', text: `Switched to tab ${index}: ${handles[index]}` }] };\n }\n return { isError: true, content: [{ type: 'text', text: 'Error: Must provide either handle or index' }] };\n } catch (e) {\n return { isError: true, content: [{ type: 'text', text: `Error switching tab: ${e}` }] };\n }\n};","import { existsSync, createReadStream } from 'node:fs';\nimport { z } from 'zod';\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport type { ToolDefinition } from '../types/tool';\nimport { coerceBoolean } from '../utils/zod-helpers';\n\nconst BS_API = 'https://api-cloud.browserstack.com';\n\nfunction getAuth(): string | null {\n const user = process.env.BROWSERSTACK_USERNAME;\n const key = process.env.BROWSERSTACK_ACCESS_KEY;\n if (!user || !key) return null;\n return Buffer.from(`${user}:${key}`).toString('base64');\n}\n\nexport interface BrowserStackApp {\n app_name: string;\n app_version: string;\n app_url: string;\n app_id: string;\n custom_id?: string;\n uploaded_at: string;\n}\n\nfunction formatAppList(apps: BrowserStackApp[]): string {\n if (apps.length === 0) return 'No apps found.';\n return apps.map((a) => {\n const id = a.custom_id ? ` [${a.custom_id}]` : '';\n return `${a.app_name} v${a.app_version}${id} — ${a.app_url} (${a.uploaded_at})`;\n }).join('\\n');\n}\n\n// ─── list_apps ───────────────────────────────────────────────────────────────\n\nexport const listAppsToolDefinition: ToolDefinition = {\n name: 'list_apps',\n description: 'List apps uploaded to BrowserStack App Automate. Reads BROWSERSTACK_USERNAME and BROWSERSTACK_ACCESS_KEY from environment.',\n inputSchema: {\n sortBy: z.enum(['app_name', 'uploaded_at']).optional().default('uploaded_at').describe('Sort order for results'),\n organizationWide: coerceBoolean.optional().default(false).describe('List apps uploaded by all users in the organization (uses recent_group_apps endpoint). Defaults to false (own uploads only).'),\n limit: z.number().int().min(1).optional().default(20).describe('Maximum number of apps to return (only applies when organizationWide is true, default 20)'),\n },\n};\n\nexport const listAppsTool: ToolCallback = async ({ sortBy = 'uploaded_at', organizationWide = false, limit = 20 }: { sortBy?: 'app_name' | 'uploaded_at'; organizationWide?: boolean; limit?: number }) => {\n const auth = getAuth();\n if (!auth) {\n return { isError: true as const, content: [{ type: 'text' as const, text: 'Missing credentials: set BROWSERSTACK_USERNAME and BROWSERSTACK_ACCESS_KEY environment variables.' }] };\n }\n\n try {\n let url = `${BS_API}/app-automate/${organizationWide ? 'recent_group_apps' : 'recent_apps'}`;\n if (organizationWide && limit) url += `?limit=${limit}`;\n\n const res = await fetch(url, {\n headers: { Authorization: `Basic ${auth}` },\n });\n\n if (!res.ok) {\n const body = await res.text();\n return { isError: true as const, content: [{ type: 'text' as const, text: `BrowserStack API error ${res.status}: ${body}` }] };\n }\n\n const raw = await res.json();\n let apps: BrowserStackApp[] = Array.isArray(raw) ? raw : [];\n\n apps = sortBy === 'app_name' ? apps.sort((a, b) => a.app_name.localeCompare(b.app_name)) : apps.sort((a, b) => new Date(b.uploaded_at).getTime() - new Date(a.uploaded_at).getTime());\n\n return { content: [{ type: 'text' as const, text: formatAppList(apps) }] };\n } catch (e) {\n return { isError: true as const, content: [{ type: 'text' as const, text: `Error listing apps: ${e}` }] };\n }\n};\n\n// ─── upload_app ──────────────────────────────────────────────────────────────\n\nexport const uploadAppToolDefinition: ToolDefinition = {\n name: 'upload_app',\n description: 'Upload a local .apk or .ipa to BrowserStack App Automate. Returns a bs:// URL for use in start_session.',\n inputSchema: {\n path: z.string().describe('Absolute path to the .apk or .ipa file'),\n customId: z.string().optional().describe('Optional custom ID for the app (used to reference it later)'),\n },\n};\n\nexport const uploadAppTool: ToolCallback = async ({ path, customId }: { path: string; customId?: string }) => {\n const auth = getAuth();\n if (!auth) {\n return { isError: true as const, content: [{ type: 'text' as const, text: 'Missing credentials: set BROWSERSTACK_USERNAME and BROWSERSTACK_ACCESS_KEY environment variables.' }] };\n }\n\n if (!existsSync(path)) {\n return { isError: true as const, content: [{ type: 'text' as const, text: `File not found: ${path}` }] };\n }\n\n try {\n const form = new FormData();\n const stream = createReadStream(path);\n const fileName = path.split('/').pop() ?? 'app';\n form.append('file', new Blob([stream as unknown as BlobPart]), fileName);\n if (customId) form.append('custom_id', customId);\n\n const res = await fetch(`${BS_API}/app-automate/upload`, {\n method: 'POST',\n headers: { Authorization: `Basic ${auth}` },\n body: form,\n });\n\n if (!res.ok) {\n const body = await res.text();\n return { isError: true as const, content: [{ type: 'text' as const, text: `Upload failed ${res.status}: ${body}` }] };\n }\n\n const data = await res.json() as { app_url: string; custom_id?: string };\n const customIdNote = data.custom_id ? `\\nCustom ID: ${data.custom_id}` : '';\n return { content: [{ type: 'text' as const, text: `Upload successful.\\nApp URL: ${data.app_url}${customIdNote}\\n\\nUse this URL as the \"app\" parameter in start_session with provider: \"browserstack\".` }] };\n } catch (e) {\n return { isError: true as const, content: [{ type: 'text' as const, text: `Error uploading app: ${e}` }] };\n }\n};\n"],"mappings":"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","names":["z","z","z","z","defaultTimeout","z","z","state","z","z","getBrowser","z","z","z","z","z","platform","xpath","platform","platform","platform","z","z","z","z","state","state","platform","platform","encode","getState","encode","state","ResourceTemplate","state","z","platform","tmpdir","join","platform","bstackOptions","reporting","platform","state","z","waitForCDP","platform","state","z","existsSync","z","z","existsSync"]}