@wdio/mcp 2.3.1 → 2.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/server.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/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","../package.json"],"sourcesContent":["#!/usr/bin/env node\n\nimport { McpServer } 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 pkg from '../package.json' with { type: 'json' };\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 },\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, startBrowserTool);\nregisterTool(startAppToolDefinition, startAppTool);\nregisterTool(closeSessionToolDefinition, closeSessionTool);\nregisterTool(navigateToolDefinition, navigateTool);\n\n// Element Discovery\nregisterTool(getVisibleElementsToolDefinition, getVisibleElementsTool);\nregisterTool(getAccessibilityToolDefinition, getAccessibilityTreeTool);\n\n// Scrolling\nregisterTool(scrollToolDefinition, scrollTool);\n\n// Element Interaction\nregisterTool(clickToolDefinition, clickTool);\nregisterTool(setValueToolDefinition, 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, tapElementTool);\nregisterTool(swipeToolDefinition, swipeTool);\nregisterTool(dragAndDropToolDefinition, 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\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 { 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',\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} = {\n browsers: new Map<string, WebdriverIO.Browser>(),\n currentSession: null,\n sessionMetadata: 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.currentSession = sessionId;\n state.sessionMetadata.set(sessionId, {\n type: 'browser',\n capabilities: wdioBrowser.capabilities,\n isAttached: false,\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 // 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 // Only delete session if not detaching\n if (!args.detach) {\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 = args.detach ? '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 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 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 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 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 { 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().describe('How long (in seconds) Appium will wait for a new command before assuming the client has quit and ending the session. Default: 60. Set to 300 for 5 minutes, etc.'),\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 };\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,\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.currentSession = sessionId;\n state.sessionMetadata.set(sessionId, {\n type: platform.toLowerCase() as 'ios' | 'android',\n capabilities: mergedCapabilities,\n isAttached: shouldAutoDetach,\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 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 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', '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', '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 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(/\\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 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 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 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 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 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 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 content: [{ type: 'text', text: 'Error: Must provide either selector or x,y coordinates' }],\n };\n } catch (e) {\n return {\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 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 content: [{ type: 'text', text: 'Error: Must provide either targetSelector or x,y coordinates' }],\n };\n } catch (e) {\n return {\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 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 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 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 return {\n content: [\n {\n type: 'text',\n text: `Error: Invalid context index ${context}. Available contexts: ${contexts.length}`,\n },\n ],\n };\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 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 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 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 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 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 content: [{ type: 'text', text: `Error executing script: ${e}` }],\n };\n }\n};\n","{\n \"name\": \"@wdio/mcp\",\n \"author\": \"Vince Graics\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git://github.com/webdriverio/mcp.git\"\n },\n \"version\": \"2.3.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/ --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.12.4\"\n}\n"],"mappings":"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","names":["z","z","z","defaultTimeout","remote","z","z","remote","state","z","state","xpath","z","getState","encode","z","state","z","sizeKB","z","z","z","z","z","state","z","z","z","z","z","z"]}
1
+ {"version":3,"sources":["../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/emulate-device.tool.ts","../package.json","../src/recording/step-recorder.ts","../src/recording/code-generator.ts","../src/recording/resources.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { McpServer } 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 { emulateDeviceTool, emulateDeviceToolDefinition } from './tools/emulate-device.tool';\nimport pkg from '../package.json' with { type: 'json' };\nimport { ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { withRecording } from './recording/step-recorder';\nimport { buildSessionsIndex, buildCurrentSessionSteps, 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, startBrowserTool);\nregisterTool(startAppToolDefinition, startAppTool);\nregisterTool(closeSessionToolDefinition, closeSessionTool);\nregisterTool(attachBrowserToolDefinition, 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: 'Index of all browser and app sessions with step counts' },\n async () => ({\n contents: [{ uri: 'wdio://sessions', mimeType: 'text/plain', text: buildSessionsIndex() }],\n }),\n);\n\nserver.registerResource(\n 'session-current-steps',\n 'wdio://session/current/steps',\n { description: 'Steps for the currently active session with generated WebdriverIO JS' },\n async () => ({\n contents: [{ uri: 'wdio://session/current/steps', mimeType: 'text/plain', text: buildCurrentSessionSteps() }],\n }),\n);\n\nserver.registerResource(\n 'session-steps',\n new ResourceTemplate('wdio://session/{sessionId}/steps', { list: undefined }),\n { description: 'Steps for a specific session by ID with generated WebdriverIO JS' },\n async (uri, { sessionId }) => ({\n contents: [{\n uri: uri.href,\n mimeType: 'text/plain',\n text: buildSessionStepsById(sessionId as string),\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 index: 1,\n tool: 'start_browser',\n params: { browser, headless, windowWidth, windowHeight, ...(navigationUrl && { navigationUrl }), ...(Object.keys(userCapabilities).length > 0 && { capabilities: userCapabilities }) },\n status: 'ok',\n durationMs: 0,\n timestamp: new Date().toISOString(),\n }],\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 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 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 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 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 steps: [{\n index: 1,\n tool: 'start_app_session',\n params: {\n platform, deviceName,\n ...(platformVersion !== undefined && { platformVersion }),\n ...(automationName !== undefined && { automationName }),\n ...(appPath !== undefined && { appPath }),\n ...(udid !== undefined && { udid }),\n ...(noReset !== undefined && { noReset }),\n ...(fullReset !== undefined && { fullReset }),\n ...(autoGrantPermissions !== undefined && { autoGrantPermissions }),\n ...(autoAcceptAlerts !== undefined && { autoAcceptAlerts }),\n ...(autoDismissAlerts !== undefined && { autoDismissAlerts }),\n ...(appWaitActivity !== undefined && { appWaitActivity }),\n ...(newCommandTimeout !== undefined && { newCommandTimeout }),\n ...(appiumHost !== undefined && { appiumHost }),\n ...(appiumPort !== undefined && { appiumPort }),\n ...(appiumPath !== undefined && { appiumPath }),\n ...(Object.keys(userCapabilities).length > 0 && { capabilities: userCapabilities }),\n },\n status: 'ok',\n durationMs: 0,\n timestamp: new Date().toISOString(),\n }],\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 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', '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', '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 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(/\\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 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 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 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 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 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 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 content: [{ type: 'text', text: 'Error: Must provide either selector or x,y coordinates' }],\n };\n } catch (e) {\n return {\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 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 content: [{ type: 'text', text: 'Error: Must provide either targetSelector or x,y coordinates' }],\n };\n } catch (e) {\n return {\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 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 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 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 return {\n content: [\n {\n type: 'text',\n text: `Error: Invalid context index ${context}. Available contexts: ${contexts.length}`,\n },\n ],\n };\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 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 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 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 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 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 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\nStart Chrome first (quit any running Chrome instance before launching):\n\n macOS — with real profile (preserves extensions, cookies, logins):\n pkill -x \"Google Chrome\" && sleep 1\n /Applications/Google Chrome.app/Contents/MacOS/Google Chrome --remote-debugging-port=9222 --user-data-dir=\"$HOME/Library/Application Support/Google/Chrome\" --profile-directory=Default &\n\n macOS — with fresh profile (lightweight, no extensions):\n pkill -x \"Google Chrome\" && sleep 1\n /Applications/Google Chrome.app/Contents/MacOS/Google Chrome --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-debug &\n\n Linux — with real profile:\n google-chrome --remote-debugging-port=9222 --user-data-dir=\"$HOME/.config/google-chrome\" --profile-directory=Default &\n\n Linux — with fresh profile:\n google-chrome --remote-debugging-port=9222 --user-data-dir=/tmp/chrome-debug &\n\nVerify Chrome is ready: curl http://localhost:9222/json/version\n\nThen call attach_browser() to hand control to the AI. All other tools (navigate, click, get_visible_elements, etc.) will work on the attached session. Use close_session() to detach without closing Chrome.`,\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 userDataDir: z.string().default('/tmp/chrome-debug').describe('Chrome user data directory — must match the --user-data-dir used when launching Chrome. Use your real profile path (e.g. \"$HOME/Library/Application Support/Google/Chrome\") to preserve extensions and logins, or /tmp/chrome-debug for a fresh profile (default: /tmp/chrome-debug)'),\n navigationUrl: z.string().optional().describe('URL to navigate to immediately after attaching'),\n },\n};\n\nasync function getActiveTabUrl(host: string, port: number): Promise<string | null> {\n try {\n const res = await fetch(`http://${host}:${port}/json`);\n const tabs = await res.json() as { type: string; url: string }[];\n const page = tabs.find((t) => t.type === 'page' && t.url && !t.url.startsWith('devtools://'));\n return page?.url ?? null;\n } catch {\n return null;\n }\n}\n\nexport const attachBrowserTool: ToolCallback = async ({\n port = 9222,\n host = 'localhost',\n userDataDir = '/tmp/chrome-debug',\n navigationUrl,\n}: {\n port?: number;\n host?: string;\n userDataDir?: string;\n navigationUrl?: string;\n}): Promise<CallToolResult> => {\n try {\n const state = (getBrowser as any).__state;\n\n // Capture the active tab URL before WebDriver blanks it\n const activeUrl = navigationUrl ?? await getActiveTabUrl(host, port);\n\n const browser = await remote({\n capabilities: {\n browserName: 'chrome',\n 'goog:chromeOptions': {\n debuggerAddress: `${host}:${port}`,\n args: [`--user-data-dir=${userDataDir}`],\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\n if (activeUrl) {\n await browser.url(activeUrl);\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 content: [{ type: 'text', text: `Error attaching to browser: ${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';\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 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 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 { 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 { content: [{ type: 'text', text: `Error: ${e}` }] };\n }\n } catch (e) {\n return {\n content: [{ type: 'text', text: `Error: ${e}` }],\n };\n }\n};\n","{\n \"name\": \"@wdio/mcp\",\n \"author\": \"Vince Graics\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git://github.com/webdriverio/mcp.git\"\n },\n \"version\": \"2.4.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/ --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.12.4\"\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.content.some(\n (c: any) => c.type === 'text' && typeof (c as any).text === 'string' && (c as any).text.startsWith('Error'),\n );\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): 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 browserName = p.browser === 'edge' ? 'msedge' : String(p.browser ?? 'chrome');\n const headless = p.headless !== false;\n const width = (p.windowWidth as number | undefined) ?? 1920;\n const height = (p.windowHeight as number | undefined) ?? 1080;\n const args: string[] = [`--window-size=${width},${height}`];\n if (headless && browserName !== 'safari') {\n args.push('--headless=new', '--disable-gpu', '--disable-dev-shm-usage');\n }\n const caps: Record<string, unknown> = { browserName };\n if (browserName === 'chrome') caps['goog:chromeOptions'] = { args };\n else if (browserName === 'msedge') caps['ms:edgeOptions'] = { args };\n else if (browserName === 'firefox' && headless) caps['moz:firefoxOptions'] = { args: ['-headless'] };\n const extra = p.capabilities as Record<string, unknown> | undefined;\n const merged = extra ? { ...caps, ...extra } : caps;\n const nav = p.navigationUrl ? `\\nawait browser.url('${escapeStr(p.navigationUrl)}');` : '';\n return `const browser = await remote({\\n capabilities: ${indentJson(merged)}\\n});${nav}`;\n }\n case 'start_app_session': {\n const caps: Record<string, unknown> = {\n platformName: p.platform,\n 'appium:deviceName': p.deviceName,\n ...(p.platformVersion !== undefined && { 'appium:platformVersion': p.platformVersion }),\n ...(p.automationName !== undefined && { 'appium:automationName': p.automationName }),\n ...(p.appPath !== undefined && { 'appium:app': p.appPath }),\n ...(p.udid !== undefined && { 'appium:udid': p.udid }),\n ...(p.noReset !== undefined && { 'appium:noReset': p.noReset }),\n ...(p.fullReset !== undefined && { 'appium:fullReset': p.fullReset }),\n ...(p.autoGrantPermissions !== undefined && { 'appium:autoGrantPermissions': p.autoGrantPermissions }),\n ...(p.autoAcceptAlerts !== undefined && { 'appium:autoAcceptAlerts': p.autoAcceptAlerts }),\n ...(p.autoDismissAlerts !== undefined && { 'appium:autoDismissAlerts': p.autoDismissAlerts }),\n ...(p.appWaitActivity !== undefined && { 'appium:appWaitActivity': p.appWaitActivity }),\n ...(p.newCommandTimeout !== undefined && { 'appium:newCommandTimeout': p.newCommandTimeout }),\n ...((p.capabilities as Record<string, unknown> | undefined) ?? {}),\n };\n const config: Record<string, unknown> = {\n protocol: 'http',\n hostname: p.appiumHost ?? 'localhost',\n port: p.appiumPort ?? 4723,\n path: p.appiumPath ?? '/',\n capabilities: caps,\n };\n return `const browser = await remote(${indentJson(config)});`;\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(generateStep).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 function buildSessionsIndex(): string {\n const histories = getSessionHistory();\n if (histories.size === 0) return 'No sessions recorded.';\n\n const currentId = getCurrentSessionId();\n const lines = [`Sessions (${histories.size} total):\\n`];\n for (const [id, h] of histories) {\n const ended = h.endedAt ?? '-';\n const current = id === currentId ? ' [current]' : '';\n lines.push(`- ${id} ${h.type} started: ${h.startedAt} ended: ${ended} ${h.steps.length} steps${current}`);\n }\n return lines.join('\\n');\n}\n\nexport function buildCurrentSessionSteps(): string {\n const currentId = getCurrentSessionId();\n if (!currentId) return 'No active session.';\n return buildSessionStepsById(currentId);\n}\n\nexport function buildSessionStepsById(sessionId: string): string {\n const history = getSessionHistory().get(sessionId);\n if (!history) return `Session not found: ${sessionId}`;\n return formatSessionSteps(history);\n}\n\nfunction formatSessionSteps(history: SessionHistory): string {\n const header = `Session: ${history.sessionId} (${history.type}) — ${history.steps.length} steps\\n`;\n\n const stepLines = history.steps.map((step) => {\n if (step.tool === '__session_transition__') {\n return `--- session transitioned to ${step.params.newSessionId ?? 'unknown'} at ${step.timestamp} ---`;\n }\n const statusLabel = step.status === 'ok' ? '[ok] ' : '[error]';\n const params = Object.entries(step.params)\n .map(([k, v]) => `${k}=\"${v}\"`)\n .join(' ');\n const errorSuffix = step.error ? ` — ${step.error}` : '';\n return `${step.index}. ${statusLabel} ${step.tool.padEnd(24)} ${params}${errorSuffix} ${step.durationMs}ms`;\n });\n\n const stepsText = stepLines.length > 0 ? stepLines.join('\\n') : '(no steps yet)';\n const jsCode = generateCode(history);\n return `${header}\\nSteps:\\n${stepsText}\\n\\n--- Generated WebdriverIO JS ---\\n${jsCode}`;\n}\n"],"mappings":"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","names":["z","z","z","defaultTimeout","remote","z","z","remote","state","z","state","xpath","z","getState","encode","z","state","z","sizeKB","z","z","z","z","z","state","z","z","z","z","z","z","remote","z","z","state","remote","z","z","state","getState","state"]}