@wdio/mcp 2.5.3 → 3.1.0
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/README.md +270 -17
- package/lib/server.js +2032 -1579
- package/lib/server.js.map +1 -1
- package/package.json +17 -18
package/lib/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../package.json","../src/server.ts","../src/tools/browser.tool.ts","../src/tools/navigate.tool.ts","../src/tools/click.tool.ts","../src/tools/set-value.tool.ts","../src/tools/app-session.tool.ts","../src/config/appium.config.ts","../src/tools/scroll.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/tools/get-visible-elements.tool.ts","../src/scripts/get-browser-accessibility-tree.ts","../src/tools/get-accessibility-tree.tool.ts","../src/tools/take-screenshot.tool.ts","../src/tools/cookies.tool.ts","../src/tools/gestures.tool.ts","../src/tools/app-actions.tool.ts","../src/tools/context.tool.ts","../src/tools/device.tool.ts","../src/tools/execute-script.tool.ts","../src/tools/attach-browser.tool.ts","../src/tools/launch-chrome.tool.ts","../src/tools/emulate-device.tool.ts","../src/recording/step-recorder.ts","../src/recording/code-generator.ts","../src/recording/resources.ts"],"sourcesContent":["{\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\": \"2.5.2\",\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/ --fix && tsc --noEmit\",\n \"lint:tests\": \"eslint tests/ --fix && tsc -p tsconfig.test.json --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\",\n \"@toon-format/toon\": \"^2.1.0\",\n \"@wdio/protocols\": \"^9.16.2\",\n \"@xmldom/xmldom\": \"^0.8.11\",\n \"puppeteer-core\": \"^24.35.0\",\n \"sharp\": \"^0.34.5\",\n \"webdriverio\": \"9.24\",\n \"xpath\": \"^0.0.34\",\n \"zod\": \"^4.3.5\"\n },\n \"devDependencies\": {\n \"@release-it/conventional-changelog\": \"^10.0.4\",\n \"@types/node\": \"^20.11.0\",\n \"@wdio/eslint\": \"^0.1.3\",\n \"@wdio/types\": \"^9.20.0\",\n \"eslint\": \"^9.39.2\",\n \"happy-dom\": \"^20.7.0\",\n \"husky\": \"^9.1.7\",\n \"release-it\": \"^19.2.3\",\n \"rimraf\": \"^6.1.2\",\n \"shx\": \"^0.4.0\",\n \"tsup\": \"^8.5.1\",\n \"tsx\": \"^4.21.0\",\n \"typescript\": \"5.9\",\n \"vitest\": \"^4.0.18\"\n },\n \"packageManager\": \"pnpm@10.32.1\"\n}\n","#!/usr/bin/env node\nimport pkg from '../package.json' with { type: 'json' };\nimport { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport type { ToolDefinition } from './types/tool';\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp';\nimport {\n closeSessionTool,\n closeSessionToolDefinition,\n startBrowserTool,\n startBrowserToolDefinition\n} from './tools/browser.tool';\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 { getVisibleElementsTool, getVisibleElementsToolDefinition } from './tools/get-visible-elements.tool';\nimport { getAccessibilityToolDefinition, getAccessibilityTreeTool } from './tools/get-accessibility-tree.tool';\nimport { takeScreenshotTool, takeScreenshotToolDefinition } from './tools/take-screenshot.tool';\nimport {\n deleteCookiesTool,\n deleteCookiesToolDefinition,\n getCookiesTool,\n getCookiesToolDefinition,\n setCookieTool,\n setCookieToolDefinition,\n} from './tools/cookies.tool';\nimport { startAppTool, startAppToolDefinition } from './tools/app-session.tool';\nimport {\n dragAndDropTool,\n dragAndDropToolDefinition,\n swipeTool,\n swipeToolDefinition,\n tapElementTool,\n tapElementToolDefinition,\n} from './tools/gestures.tool';\nimport { getAppStateTool, getAppStateToolDefinition } from './tools/app-actions.tool';\nimport {\n getContextsTool,\n getContextsToolDefinition,\n getCurrentContextTool,\n getCurrentContextToolDefinition,\n switchContextTool,\n switchContextToolDefinition\n} from './tools/context.tool';\nimport {\n getGeolocationTool,\n getGeolocationToolDefinition,\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 { attachBrowserTool, attachBrowserToolDefinition } from './tools/attach-browser.tool';\nimport { launchChromeTool, launchChromeToolDefinition } from './tools/launch-chrome.tool';\nimport { emulateDeviceTool, emulateDeviceToolDefinition } from './tools/emulate-device.tool';\nimport { withRecording } from './recording/step-recorder';\nimport { buildCurrentSessionSteps, buildSessionsIndex, buildSessionStepsById } from './recording/resources';\n\n// IMPORTANT: Redirect all console output to stderr to avoid messing with MCP protocol (Chrome writes to console)\nconst _originalConsoleLog = console.log;\nconst _originalConsoleInfo = console.info;\nconst _originalConsoleWarn = console.warn;\nconst _originalConsoleDebug = console.debug;\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\n// Helper function to register tools using the new registerTool pattern\nconst registerTool = (definition: ToolDefinition, callback: ToolCallback) =>\n server.registerTool(definition.name, {\n description: definition.description,\n inputSchema: definition.inputSchema,\n }, callback);\n\n// Browser and App Session Management\nregisterTool(startBrowserToolDefinition, withRecording('start_browser', startBrowserTool));\nregisterTool(startAppToolDefinition, withRecording('start_app_session', startAppTool));\nregisterTool(closeSessionToolDefinition, closeSessionTool);\nregisterTool(launchChromeToolDefinition, withRecording('launch_chrome', launchChromeTool));\nregisterTool(attachBrowserToolDefinition, withRecording('attach_browser', attachBrowserTool));\nregisterTool(emulateDeviceToolDefinition, emulateDeviceTool);\nregisterTool(navigateToolDefinition, withRecording('navigate', navigateTool));\n\n// Element Discovery\nregisterTool(getVisibleElementsToolDefinition, getVisibleElementsTool);\nregisterTool(getAccessibilityToolDefinition, getAccessibilityTreeTool);\n\n// Scrolling\nregisterTool(scrollToolDefinition, withRecording('scroll', scrollTool));\n\n// Element Interaction\nregisterTool(clickToolDefinition, withRecording('click_element', clickTool));\nregisterTool(setValueToolDefinition, withRecording('set_value', setValueTool));\n\n// Screenshots\nregisterTool(takeScreenshotToolDefinition, takeScreenshotTool);\n\n// Cookies\nregisterTool(getCookiesToolDefinition, getCookiesTool);\nregisterTool(setCookieToolDefinition, setCookieTool);\nregisterTool(deleteCookiesToolDefinition, deleteCookiesTool);\n\n// Mobile Gesture Tools\nregisterTool(tapElementToolDefinition, withRecording('tap_element', tapElementTool));\nregisterTool(swipeToolDefinition, withRecording('swipe', swipeTool));\nregisterTool(dragAndDropToolDefinition, withRecording('drag_and_drop', dragAndDropTool));\n\n// App Lifecycle Management\nregisterTool(getAppStateToolDefinition, getAppStateTool);\n\n// Context Switching (Native/WebView)\nregisterTool(getContextsToolDefinition, getContextsTool);\nregisterTool(getCurrentContextToolDefinition, getCurrentContextTool);\nregisterTool(switchContextToolDefinition, switchContextTool);\n\n// Device Interaction\nregisterTool(rotateDeviceToolDefinition, rotateDeviceTool);\nregisterTool(hideKeyboardToolDefinition, hideKeyboardTool);\nregisterTool(getGeolocationToolDefinition, getGeolocationTool);\nregisterTool(setGeolocationToolDefinition, setGeolocationTool);\n\n// Script Execution (Browser JS / Appium Mobile Commands)\nregisterTool(executeScriptToolDefinition, executeScriptTool);\n\n// Session Recording Resources\nserver.registerResource(\n 'sessions',\n 'wdio://sessions',\n { description: 'JSON index of all browser and app sessions with metadata and step counts' },\n async () => ({\n contents: [{ uri: 'wdio://sessions', mimeType: 'application/json', text: buildSessionsIndex() }],\n }),\n);\n\nserver.registerResource(\n 'session-current-steps',\n 'wdio://session/current/steps',\n { description: 'JSON step log for the currently active session' },\n 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\nserver.registerResource(\n 'session-current-code',\n 'wdio://session/current/code',\n { description: 'Generated WebdriverIO JS code for the currently active session' },\n 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\nserver.registerResource(\n 'session-steps',\n new ResourceTemplate('wdio://session/{sessionId}/steps', { list: undefined }),\n { description: 'JSON step log for a specific session by ID' },\n 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\nserver.registerResource(\n 'session-code',\n new ResourceTemplate('wdio://session/{sessionId}/code', { list: undefined }),\n { description: 'Generated WebdriverIO JS code for a specific session by ID' },\n 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);\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});\n","import { remote } from 'webdriverio';\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types';\nimport type { ToolDefinition } from '../types/tool';\nimport type { SessionHistory } from '../types/recording';\nimport { z } from 'zod';\n\nconst supportedBrowsers = ['chrome', 'firefox', 'edge', 'safari'] as const;\nconst browserSchema = z.enum(supportedBrowsers).default('chrome');\ntype SupportedBrowser = z.infer<typeof browserSchema>;\n\nexport const startBrowserToolDefinition: ToolDefinition = {\n name: 'start_browser',\n description: 'starts a browser session (Chrome, Firefox, Edge, Safari) and sets it to the current state. Prefer headless: true unless the user explicitly asks to see the browser.',\n inputSchema: {\n browser: browserSchema.describe('Browser to launch: chrome, firefox, edge, safari (default: chrome)'),\n headless: z.boolean().optional().default(true),\n windowWidth: z.number().min(400).max(3840).optional().default(1920),\n windowHeight: z.number().min(400).max(2160).optional().default(1080),\n navigationUrl: z.string().optional().describe('URL to navigate to after starting the browser'),\n capabilities: z.record(z.string(), z.unknown()).optional().describe('Additional W3C capabilities to merge with defaults (e.g. goog:chromeOptions args/extensions/prefs)'),\n },\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: z.boolean().optional().describe('If true, disconnect from session without terminating it (preserves app state). Default: false'),\n },\n};\n\nconst state: {\n browsers: Map<string, WebdriverIO.Browser>;\n currentSession: string | null;\n sessionMetadata: Map<string, { type: 'browser' | 'ios' | 'android'; capabilities: any; isAttached: boolean }>;\n sessionHistory: Map<string, SessionHistory>;\n} = {\n browsers: new Map<string, WebdriverIO.Browser>(),\n currentSession: null,\n sessionMetadata: new Map(),\n sessionHistory: new Map(),\n};\n\nexport const getBrowser = () => {\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// Export state for app-session.tool.ts to access\n(getBrowser as any).__state = state;\n\nexport const startBrowserTool: ToolCallback = async ({\n browser = 'chrome',\n headless = true,\n windowWidth = 1920,\n windowHeight = 1080,\n navigationUrl,\n capabilities: userCapabilities = {}\n}: {\n browser?: SupportedBrowser;\n headless?: boolean;\n windowWidth?: number;\n windowHeight?: number;\n navigationUrl?: string;\n capabilities?: Record<string, unknown>;\n}): Promise<CallToolResult> => {\n const browserDisplayNames: Record<SupportedBrowser, string> = {\n chrome: 'Chrome',\n firefox: 'Firefox',\n edge: 'Edge',\n safari: 'Safari',\n };\n const selectedBrowser = browser;\n const headlessSupported = selectedBrowser !== 'safari';\n const effectiveHeadless = headless && headlessSupported;\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 // Add headless argument if enabled\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 mergeCapabilityOptions = (defaultOptions: unknown, customOptions: 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 const mergedCapabilities: Record<string, unknown> = {\n ...capabilities,\n ...userCapabilities,\n 'goog:chromeOptions': mergeCapabilityOptions(capabilities['goog:chromeOptions'], userCapabilities['goog:chromeOptions']),\n 'ms:edgeOptions': mergeCapabilityOptions(capabilities['ms:edgeOptions'], userCapabilities['ms:edgeOptions']),\n 'moz:firefoxOptions': mergeCapabilityOptions(capabilities['moz:firefoxOptions'], userCapabilities['moz:firefoxOptions']),\n };\n for (const [key, value] of Object.entries(mergedCapabilities)) {\n if (value === undefined) {\n delete mergedCapabilities[key];\n }\n }\n\n const wdioBrowser = await remote({\n capabilities: mergedCapabilities,\n });\n\n const { sessionId } = wdioBrowser;\n state.browsers.set(sessionId, wdioBrowser);\n state.sessionMetadata.set(sessionId, {\n type: 'browser',\n capabilities: wdioBrowser.capabilities,\n isAttached: false,\n });\n\n // If replacing an active session, close its history and append transition sentinel\n if (state.currentSession && state.currentSession !== sessionId) {\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: sessionId },\n status: 'ok',\n durationMs: 0,\n timestamp: new Date().toISOString(),\n });\n outgoing.endedAt = new Date().toISOString();\n }\n }\n\n state.sessionHistory.set(sessionId, {\n sessionId,\n type: 'browser',\n startedAt: new Date().toISOString(),\n capabilities: wdioBrowser.capabilities as Record<string, unknown>,\n steps: [],\n });\n\n state.currentSession = sessionId;\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 // Navigate to URL if provided\n if (navigationUrl) {\n await wdioBrowser.url(navigationUrl);\n }\n\n const modeText = effectiveHeadless ? 'headless' : 'headed';\n const browserText = browserDisplayNames[selectedBrowser];\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 return {\n content: [{\n type: 'text',\n text: `${browserText} browser started in ${modeText} mode with sessionId: ${sessionId} (${windowWidth}x${windowHeight})${urlText}${headlessNote}${sizeNote}`,\n }],\n };\n};\n\nexport const closeSessionTool: ToolCallback = async (args: { detach?: boolean } = {}): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n const sessionId = state.currentSession;\n const metadata = state.sessionMetadata.get(sessionId);\n\n // Retain history but mark session as ended\n const history = state.sessionHistory.get(sessionId);\n if (history) {\n history.endedAt = new Date().toISOString();\n }\n\n // Skip deleteSession for attached sessions (not created by us) or when user explicitly detaches\n const effectiveDetach = args.detach || !!metadata?.isAttached;\n if (!effectiveDetach) {\n await browser.deleteSession();\n }\n\n // Always clean up local state\n state.browsers.delete(sessionId);\n state.sessionMetadata.delete(sessionId);\n state.currentSession = null;\n\n const action = effectiveDetach ? 'detached from' : 'closed';\n const note = args.detach && !metadata?.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 {\n isError: true,\n content: [{ type: 'text', text: `Error closing session: ${e}` }],\n };\n }\n};\n","import { getBrowser } from './browser.tool';\nimport { z } from 'zod';\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp';\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 navigateTool: ToolCallback = async ({ url}: { url: string }) => {\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","import { getBrowser } from './browser.tool';\nimport { z } from 'zod';\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types';\nimport type { ToolDefinition } from '../types/tool';\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: z.boolean().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\nconst 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 { getBrowser } from './browser.tool';\nimport { z } from 'zod';\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp';\nimport type { ToolDefinition } from '../types/tool';\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: z.boolean().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 setValueTool: ToolCallback = async ({ selector, value, scrollToView = true, timeout = defaultTimeout}: {\n selector: string;\n value: string;\n scrollToView?: boolean;\n timeout?: number\n}) => {\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};","import { remote } from 'webdriverio';\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types';\nimport type { ToolDefinition } from '../types/tool';\nimport type { SessionHistory } from '../types/recording';\nimport { z } from 'zod';\nimport { buildAndroidCapabilities, buildIOSCapabilities, getAppiumServerConfig, } from '../config/appium.config';\nimport { getBrowser } from './browser.tool';\n\nexport const startAppToolDefinition: ToolDefinition = {\n name: 'start_app_session',\n description: 'starts a mobile app session (iOS/Android) via Appium',\n inputSchema: {\n platform: z.enum(['iOS', 'Android']).describe('Mobile platform'),\n appPath: z.string().optional().describe('Path to the app file (.app/.apk/.ipa). Required unless noReset=true (connecting to already-running app)'),\n deviceName: z.string().describe('Device/emulator/simulator name'),\n platformVersion: z.string().optional().describe('OS version (e.g., \"17.0\", \"14\")'),\n automationName: z\n .enum(['XCUITest', 'UiAutomator2', 'Espresso'])\n .optional()\n .describe('Automation driver name'),\n appiumHost: z.string().optional().describe('Appium server hostname (overrides APPIUM_URL env var)'),\n appiumPort: z.number().optional().describe('Appium server port (overrides APPIUM_URL_PORT env var)'),\n appiumPath: z.string().optional().describe('Appium server path (overrides APPIUM_PATH env var)'),\n autoGrantPermissions: z.boolean().optional().describe('Auto-grant app permissions (default: true)'),\n autoAcceptAlerts: z.boolean().optional().describe('Auto-accept alerts (default: true)'),\n autoDismissAlerts: z.boolean().optional().describe('Auto-dismiss alerts (default: false, will override \"autoAcceptAlerts\" to undefined if set)'),\n appWaitActivity: z.string().optional().describe('Activity to wait for on launch (Android only)'),\n udid: z.string().optional().describe('Unique Device Identifier for iOS real device testing (e.g., \"00008030-001234567890002E\")'),\n noReset: z.boolean().optional().describe('Do not reset app state before session (preserves app data). Default: false'),\n fullReset: z.boolean().optional().describe('Uninstall app before/after session. Default: true. Set to false with noReset=true to preserve app state completely'),\n newCommandTimeout: z.number().min(0).optional().default(300).describe('How long (in seconds) Appium will wait for a new command before assuming the client has quit and ending the session. Default: 300.'),\n capabilities: z.record(z.string(), z.unknown()).optional().describe('Additional Appium/WebDriver capabilities to merge with defaults (e.g. appium:udid, appium:chromedriverExecutable, appium:autoWebview)'),\n },\n};\n\n// Access shared state from browser.tool.ts\nexport const getState = () => {\n const sharedState = (getBrowser as any).__state;\n if (!sharedState) {\n throw new Error('Browser state not initialized');\n }\n return sharedState as {\n browsers: Map<string, WebdriverIO.Browser>;\n currentSession: string | null;\n sessionMetadata: Map<string, { type: 'browser' | 'ios' | 'android'; capabilities: any; isAttached: boolean }>;\n sessionHistory: Map<string, SessionHistory>;\n };\n};\n\nexport const startAppTool: ToolCallback = async (args: {\n platform: 'iOS' | 'Android';\n appPath?: string;\n deviceName: string;\n platformVersion?: string;\n automationName?: 'XCUITest' | 'UiAutomator2' | 'Espresso';\n appiumHost?: string;\n appiumPort?: number;\n appiumPath?: 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}): Promise<CallToolResult> => {\n try {\n const {\n platform,\n appPath,\n deviceName,\n platformVersion,\n automationName,\n appiumHost,\n appiumPort,\n appiumPath,\n autoGrantPermissions = true,\n autoAcceptAlerts,\n autoDismissAlerts,\n appWaitActivity,\n udid,\n noReset,\n fullReset,\n newCommandTimeout = 300,\n capabilities: userCapabilities = {},\n } = args;\n\n // Validate: either appPath or noReset=true is required\n if (!appPath && 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 // Get Appium server configuration\n const serverConfig = getAppiumServerConfig({\n hostname: appiumHost,\n port: appiumPort,\n path: appiumPath,\n });\n\n // Build platform-specific capabilities\n const capabilities: Record<string, any> = platform === 'iOS'\n ? buildIOSCapabilities(appPath, {\n deviceName,\n platformVersion,\n automationName: (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: (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 for (const [key, value] of Object.entries(mergedCapabilities)) {\n if (value === undefined) {\n delete mergedCapabilities[key];\n }\n }\n\n // Create Appium session\n const browser = await remote({\n protocol: 'http',\n hostname: serverConfig.hostname,\n port: serverConfig.port,\n path: serverConfig.path,\n capabilities: mergedCapabilities,\n });\n\n const { sessionId } = browser;\n\n // Store session and metadata\n // Auto-set isAttached=true when noReset or no appPath to preserve session on close\n const shouldAutoDetach = noReset === true || !appPath;\n const state = getState();\n state.browsers.set(sessionId, browser);\n state.sessionMetadata.set(sessionId, {\n type: platform.toLowerCase() as 'ios' | 'android',\n capabilities: mergedCapabilities,\n isAttached: shouldAutoDetach,\n });\n\n // If replacing an active session, close its history with transition sentinel\n if (state.currentSession && state.currentSession !== sessionId) {\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: sessionId },\n status: 'ok',\n durationMs: 0,\n timestamp: new Date().toISOString(),\n });\n outgoing.endedAt = new Date().toISOString();\n }\n }\n\n state.sessionHistory.set(sessionId, {\n sessionId,\n type: platform.toLowerCase() as 'ios' | 'android',\n startedAt: new Date().toISOString(),\n capabilities: mergedCapabilities as Record<string, unknown>,\n appiumConfig: { hostname: serverConfig.hostname, port: serverConfig.port, path: serverConfig.path },\n steps: [],\n });\n\n state.currentSession = sessionId;\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 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 } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error starting app session: ${e}` }],\n };\n }\n};\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 { getBrowser } from './browser.tool';\nimport { getState } from './app-session.tool';\nimport { z } from 'zod';\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp';\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 scrollTool: ToolCallback = async ({ direction, pixels = 500 }: { direction: 'up' | 'down'; pixels?: number }) => {\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 * 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 { getBrowser } from './browser.tool';\nimport { getInteractableBrowserElements } from '../scripts/get-interactable-browser-elements';\nimport { getMobileVisibleElements } from '../scripts/get-visible-mobile-elements';\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp';\nimport type { ToolDefinition } from '../types/tool';\nimport { encode } from '@toon-format/toon';\nimport { z } from 'zod';\n\n/**\n * Tool definition for get_visible_elements\n */\nexport const getVisibleElementsToolDefinition: ToolDefinition = {\n name: 'get_visible_elements',\n description: 'Get interactable elements on the page (buttons, links, inputs). Use get_accessibility for page structure and non-interactable elements.',\n inputSchema: {\n inViewportOnly: z\n .boolean()\n .optional()\n .describe('Only return elements within the visible viewport. Default: true. Set to false to get ALL elements on the page.'),\n includeContainers: z\n .boolean()\n .optional()\n .describe('Mobile only: include layout containers. Default: false.'),\n includeBounds: z\n .boolean()\n .optional()\n .describe('Include element bounds/coordinates (x, y, width, height). Default: false.'),\n limit: z\n .number()\n .optional()\n .describe('Maximum number of elements to return. Default: 0 (unlimited).'),\n offset: z\n .number()\n .optional()\n .describe('Number of elements to skip (for pagination). Default: 0.'),\n },\n};\n\n/**\n * Get visible elements on the current screen\n * Supports both web browsers and mobile apps (iOS/Android)\n */\nexport const getVisibleElementsTool: ToolCallback = async (args: {\n inViewportOnly?: boolean;\n includeContainers?: boolean;\n includeBounds?: boolean;\n limit?: number;\n offset?: number;\n}) => {\n try {\n const browser = getBrowser();\n const {\n inViewportOnly = true,\n includeContainers = false,\n includeBounds = false,\n limit = 0,\n offset = 0,\n } = args || {};\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 // Apply pagination\n if (offset > 0) {\n elements = elements.slice(offset);\n }\n if (limit > 0) {\n elements = elements.slice(0, limit);\n }\n\n const result: Record<string, unknown> = {\n total,\n showing: elements.length,\n hasMore: offset + elements.length < total,\n elements,\n };\n\n // TOON tabular format with post-processing: replace \"\" with bare commas for efficiency\n const toon = encode(result).replace(/,\"\"/g, ',').replace(/\"\",/g, ',');\n return {\n content: [{ type: 'text', text: toon }],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error getting visible elements: ${e}` }],\n };\n }\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 { getBrowser } from './browser.tool';\nimport { getBrowserAccessibilityTree } from '../scripts/get-browser-accessibility-tree';\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types';\nimport type { ToolDefinition } from '../types/tool';\nimport { encode } from '@toon-format/toon';\nimport { z } from 'zod';\n\nexport const getAccessibilityToolDefinition: ToolDefinition = {\n name: 'get_accessibility',\n description: 'Gets the accessibility tree: page structure with headings, landmarks, and semantic roles. Browser-only. Use to understand page layout and context around interactable elements.',\n inputSchema: {\n limit: z.number().optional()\n .describe('Maximum number of nodes to return. Default: 100. Use 0 for unlimited.'),\n offset: z.number().optional()\n .describe('Number of nodes to skip (for pagination). Default: 0.'),\n roles: z.array(z.string()).optional()\n .describe('Filter to specific roles (e.g., [\"heading\", \"navigation\", \"region\"]). Default: all roles.'),\n },\n};\n\nexport const getAccessibilityTreeTool: ToolCallback = async (args: {\n limit?: number;\n offset?: number;\n roles?: string[];\n}): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n\n if (browser.isAndroid || browser.isIOS) {\n return {\n content: [{\n type: 'text',\n text: 'Error: get_accessibility is browser-only. For mobile apps, use get_visible_elements instead.',\n }],\n };\n }\n\n const { limit = 100, offset = 0, roles } = args || {};\n\n let nodes = await getBrowserAccessibilityTree(browser);\n\n if (nodes.length === 0) {\n return {\n content: [{ type: 'text', text: 'No accessibility tree available' }],\n };\n }\n\n // Filter out nodes with no meaningful name\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 // Drop state columns that are empty for every node in this result set\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)\n .replace(/,\"\"/g, ',')\n .replace(/\"\",/g, ',');\n\n return {\n content: [{ type: 'text', text: toon }],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error getting accessibility tree: ${e}` }],\n };\n }\n};\n","import { getBrowser } from './browser.tool';\nimport { z } from 'zod';\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp';\nimport type { ToolDefinition } from '../types/tool';\nimport sharp from 'sharp';\n\nconst MAX_DIMENSION = 2000;\nconst MAX_FILE_SIZE_BYTES = 1024 * 1024; // 1MB\n\nexport const takeScreenshotToolDefinition: ToolDefinition = {\n name: 'take_screenshot',\n description: 'captures a screenshot of the current page',\n inputSchema: {\n outputPath: z.string().optional().describe('Optional path where to save the screenshot. If not provided, returns base64 data.'),\n },\n};\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 // Resize if any dimension exceeds MAX_DIMENSION\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\n ? { width: MAX_DIMENSION }\n : { height: MAX_DIMENSION };\n image = image.resize(resizeOptions);\n }\n\n // Try PNG with maximum compression first\n let outputBuffer = await image.png({ compressionLevel: 9 }).toBuffer();\n\n // If still over 1MB, convert to JPEG with progressive quality reduction\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\nexport const takeScreenshotTool: ToolCallback = async ({ outputPath }: { outputPath?: string }) => {\n try {\n const browser = getBrowser();\n const screenshot = await browser.takeScreenshot();\n const { data, mimeType } = await processScreenshot(screenshot);\n\n if (outputPath) {\n const fs = await import('node:fs');\n await fs.promises.writeFile(outputPath, data);\n const sizeKB = (data.length / 1024).toFixed(1);\n return {\n content: [{ type: 'text', text: `Screenshot saved to ${outputPath} (${sizeKB}KB, ${mimeType})` }],\n };\n }\n\n const sizeKB = (data.length / 1024).toFixed(1);\n return {\n content: [\n { type: 'text', text: `Screenshot captured (${sizeKB}KB, ${mimeType}):` },\n { type: 'image', data: data.toString('base64'), mimeType },\n ],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error taking screenshot: ${(e as Error).message}` }],\n };\n }\n};","import { getBrowser } from './browser.tool';\nimport { z } from 'zod';\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types';\nimport type { Cookie } from '@wdio/protocols';\nimport type { ToolDefinition } from '../types/tool';\n\n// Tool definitions\nexport const getCookiesToolDefinition: ToolDefinition = {\n name: 'get_cookies',\n description: 'gets all cookies or a specific cookie by name',\n inputSchema: {\n name: z.string().optional().describe('Optional cookie name to retrieve a specific cookie. If not provided, returns all cookies'),\n },\n};\n\nexport const getCookiesTool: ToolCallback = async ({ name}: { name?: string }): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n\n if (name) {\n // Get specific cookie by name\n const cookie = await browser.getCookies([name]);\n if (cookie.length === 0) {\n return {\n content: [{ type: 'text', text: `Cookie \"${name}\" not found` }],\n };\n }\n return {\n content: [{ type: 'text', text: JSON.stringify(cookie[0], null, 2) }],\n };\n }\n // Get all cookies\n const cookies = await browser.getCookies();\n if (cookies.length === 0) {\n return {\n content: [{ type: 'text', text: 'No cookies found' }],\n };\n }\n return {\n content: [{ type: 'text', text: JSON.stringify(cookies, null, 2) }],\n };\n\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error getting cookies: ${e}` }],\n };\n }\n};\n\n// Set a cookie\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: z.boolean().optional().describe('HttpOnly flag'),\n secure: z.boolean().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 browser = getBrowser();\n\n const cookie: Cookie = { name, value, path, domain, expiry, httpOnly, secure, sameSite };\n\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\n// Delete cookies\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 browser = getBrowser();\n\n if (name) {\n // Delete specific cookie by name\n await browser.deleteCookies([name]);\n return {\n content: [{ type: 'text', text: `Cookie \"${name}\" deleted successfully` }],\n };\n }\n // Delete all cookies\n await browser.deleteCookies();\n return {\n content: [{ type: 'text', text: 'All cookies deleted successfully' }],\n };\n\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error deleting cookies: ${e}` }],\n };\n }\n};\n","import type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types';\nimport type { ToolDefinition } from '../types/tool';\nimport { z } from 'zod';\nimport { getBrowser } from './browser.tool';\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 tapElementTool: ToolCallback = 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\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 swipeTool: ToolCallback = 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\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 dragAndDropTool: ToolCallback = 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};","import type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types';\nimport type { ToolDefinition } from '../types/tool';\nimport { z } from 'zod';\nimport { getBrowser } from './browser.tool';\n\n// Get App State Tool\nexport const getAppStateToolDefinition: ToolDefinition = {\n name: 'get_app_state',\n description: 'gets the state of an app (not installed, not running, background, foreground)',\n inputSchema: {\n bundleId: z.string().describe('App bundle ID (e.g., com.example.app)'),\n },\n};\n\nexport const getAppStateTool: ToolCallback = async (args: {\n bundleId: string;\n}): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n const { bundleId } = args;\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 content: [\n {\n type: 'text',\n text: `App state for ${bundleId}: ${stateMap[state] || 'unknown: ' + state}`,\n },\n ],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error getting app state: ${e}` }],\n };\n }\n};\n\n","import type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types';\nimport type { ToolDefinition } from '../types/tool';\nimport { z } from 'zod';\nimport { getBrowser } from './browser.tool';\n\n// Get Contexts Tool Definition\nexport const getContextsToolDefinition: ToolDefinition = {\n name: 'get_contexts',\n description: 'lists available contexts (NATIVE_APP, WEBVIEW)',\n inputSchema: {},\n};\n\n// Get Current Context Tool Definition\nexport const getCurrentContextToolDefinition: ToolDefinition = {\n name: 'get_current_context',\n description: 'shows the currently active context',\n inputSchema: {},\n};\n\n// Switch Context Tool Definition\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 get_contexts)',\n ),\n },\n};\n\n// Get Contexts Tool\nexport const getContextsTool: ToolCallback = async (): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n\n const contexts = await browser.getContexts();\n\n return {\n content: [\n {\n type: 'text',\n text: `Available contexts:\\n${contexts.map((ctx, idx) => `${idx + 1}. ${ctx}`).join('\\n')}`,\n },\n ],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error getting contexts: ${e}` }],\n };\n }\n};\n\n// Get Current Context Tool\nexport const getCurrentContextTool: ToolCallback = async (): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n\n const currentContext = await browser.getContext();\n\n return {\n content: [{ type: 'text', text: `Current context: ${JSON.stringify(currentContext)}` }],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error getting current context: ${e}` }],\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 context is a number, get the context by index\n let targetContext = context;\n if (/^\\d+$/.test(context)) {\n const contexts = await browser.getContexts();\n const index = parseInt(context, 10) - 1; // Convert to 0-based index\n if (index >= 0 && index < contexts.length) {\n targetContext = contexts[index] as string;\n } else {\n throw new Error(`Error: Invalid context index ${context}. Available contexts: ${contexts.length}`);\n }\n }\n\n await browser.switchContext(targetContext);\n\n return {\n content: [{ type: 'text', text: `Switched to context: ${targetContext}` }],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error switching context: ${e}` }],\n };\n }\n};\n","import type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types';\nimport type { ToolDefinition } from '../types/tool';\nimport { z } from 'zod';\nimport { getBrowser } from './browser.tool';\n\n// Tool Definitions for zero-argument tools\nexport const hideKeyboardToolDefinition: ToolDefinition = {\n name: 'hide_keyboard',\n description: 'hides the on-screen keyboard',\n inputSchema: {},\n};\n\nexport const getGeolocationToolDefinition: ToolDefinition = {\n name: 'get_geolocation',\n description: 'gets current device geolocation',\n inputSchema: {},\n};\n\n// Tool Definitions for tools with arguments\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\n// Rotate Device Tool\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\n// Hide Keyboard Tool\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\n// Get Geolocation Tool\nexport const getGeolocationTool: ToolCallback = async (): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n\n const location = await browser.getGeoLocation();\n\n return {\n content: [\n {\n type: 'text',\n text: `Location:\\n Latitude: ${location.latitude}\\n Longitude: ${location.longitude}\\n Altitude: ${location.altitude || 'N/A'}`,\n },\n ],\n };\n } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error getting geolocation: ${e}` }],\n };\n }\n};\n\n// Set Geolocation Tool\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};\n","import type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types';\nimport type { ToolDefinition } from '../types/tool';\nimport { z } from 'zod';\nimport { getBrowser } from './browser.tool';\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 { remote } from 'webdriverio';\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types';\nimport type { ToolDefinition } from '../types/tool';\nimport { z } from 'zod';\nimport { getBrowser } from './browser.tool';\n\nexport const attachBrowserToolDefinition: ToolDefinition = {\n name: 'attach_browser',\n description: `Attach to a Chrome instance already running with --remote-debugging-port.\n\nUse launch_chrome() first to prepare and launch Chrome with remote debugging enabled.`,\n inputSchema: {\n port: z.number().default(9222).describe('Chrome remote debugging port (default: 9222)'),\n host: z.string().default('localhost').describe('Host where Chrome is running (default: localhost)'),\n navigationUrl: z.string().optional().describe('URL to navigate to immediately after attaching'),\n },\n};\n\ntype TabSnapshot = { activeTabUrl: string | undefined; allTabUrls: string[] };\n\n// ChromeDriver injects a BiDi-CDP Mapper page when creating a session. If the previous session\n// was detached without proper cleanup, this target remains and causes \"unexpected alert open\" on\n// the next attach attempt. Close any stale mappers before creating a new session.\n// Returns the active tab URL (first real page tab) and all page tab URLs — Chrome lists the\n// active/focused tab first in /json.\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\n// After CDP session init, Chrome blanks the first tab it takes over. This restores any tabs\n// that became about:blank and then switches focus to the originally active tab.\nasync function restoreAndSwitchToActiveTab(\n browser: WebdriverIO.Browser,\n activeTabUrl: string,\n allTabUrls: string[],\n): 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 // Restore blank tabs that had a known URL before attaching.\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 // Switch to the originally active tab.\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\nexport const attachBrowserTool: ToolCallback = async ({\n port = 9222,\n host = 'localhost',\n navigationUrl,\n}: {\n port?: number;\n host?: string;\n navigationUrl?: string;\n}): Promise<CallToolResult> => {\n try {\n const state = (getBrowser as any).__state;\n\n await waitForCDP(host, port);\n const { activeTabUrl, allTabUrls } = await closeStaleMappers(host, port);\n\n const browser = await remote({\n connectionRetryTimeout: 30000,\n connectionRetryCount: 3,\n capabilities: {\n browserName: 'chrome',\n unhandledPromptBehavior: 'dismiss',\n webSocketUrl: false,\n 'goog:chromeOptions': {\n debuggerAddress: `${host}:${port}`,\n },\n },\n });\n\n const { sessionId } = browser;\n state.browsers.set(sessionId, browser);\n state.currentSession = sessionId;\n state.sessionMetadata.set(sessionId, {\n type: 'browser',\n capabilities: browser.capabilities,\n isAttached: true,\n });\n state.sessionHistory.set(sessionId, {\n sessionId,\n type: 'browser',\n startedAt: new Date().toISOString(),\n capabilities: {\n browserName: 'chrome',\n 'goog:chromeOptions': {\n debuggerAddress: `${host}:${port}`,\n },\n },\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 } catch (e) {\n return {\n isError: true,\n content: [{ type: 'text', text: `Error attaching to browser: ${e}` }],\n };\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';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types';\nimport type { ToolDefinition } from '../types/tool';\nimport { z } from 'zod';\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: z.boolean().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';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types';\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 } from './browser.tool';\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 = (getBrowser as any).__state;\n const sessionId = state.currentSession as string;\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: [{ type: 'text', text: 'Error: emulate_device is only supported for web browser sessions, not iOS/Android.' }],\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';\nimport type { RecordedStep, SessionHistory } from '../types/recording';\nimport { getBrowser } from '../tools/browser.tool';\n\nfunction getState() {\n return (getBrowser as any).__state as {\n currentSession: string | null;\n sessionHistory: Map<string, SessionHistory>;\n };\n}\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","// 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_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 case 'start_app_session': {\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 'attach_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 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 default:\n return `// [unknown tool] ${step.tool}`;\n }\n}\n\nexport function generateCode(history: SessionHistory): string {\n const steps = history.steps.map(step => generateStep(step, history)).join('\\n');\n return `import { remote } from 'webdriverio';\\n\\n${steps}\\n\\nawait browser.deleteSession();`;\n}\n","// src/recording/resources.ts\nimport type { SessionHistory } from '../types/recording';\nimport { generateCode } from './code-generator';\nimport { getSessionHistory } from './step-recorder';\nimport { getBrowser } from '../tools/browser.tool';\n\nfunction getCurrentSessionId(): string | null {\n return (getBrowser as any).__state?.currentSession ?? null;\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"],"mappings":"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","names":["z","z","z","defaultTimeout","remote","z","z","platform","remote","state","z","state","platform","xpath","platform","platform","z","platform","getState","encode","z","state","z","sizeKB","z","z","z","z","z","state","z","z","z","z","z","z","remote","z","z","state","remote","z","waitForCDP","z","z","state","getState","state"]}
|
|
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}\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.0.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 \"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';\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp';\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';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types';\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';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types';\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';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types';\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';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types';\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';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types';\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';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types';\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';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types';\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';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types';\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';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types';\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';\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';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types';\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';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types';\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';\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';\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 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\nexport function generateCode(history: SessionHistory): string {\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 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';\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';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types';\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). IMPORTANT: The BrowserStack Local binary daemon MUST already be running before calling start_session, otherwise all navigation to local/internal URLs will fail with ERR_TUNNEL_CONNECTION_FAILED. Read the wdio://browserstack/local-binary resource for the platform-specific download URL and the exact daemon start command. Do not set this to true without first confirming the daemon is running.'),\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 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 };\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 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 const metadata: SessionMetadata = {\n type: sessionType,\n capabilities: mergedCapabilities,\n isAttached: shouldAutoDetach,\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 };\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 { SessionMetadata } from './state';\nimport { getState } from './state';\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 if (oldBrowser) {\n // Fire and forget — don't block registration on close\n oldBrowser.deleteSession().catch(() => {\n // Ignore errors during force-close of orphaned session\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 // 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 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 type { ConnectionConfig, SessionProvider } 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\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';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types';\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';\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","state","platform","platform","bstackOptions","reporting","platform","z","waitForCDP","platform","state","z","existsSync","z","z","existsSync"]}
|