@wdio/mcp 1.6.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -26
- package/lib/server.js +407 -775
- package/lib/server.js.map +1 -1
- package/package.json +2 -1
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/find-element.tool.ts","../src/tools/get-element-text.tool.ts","../src/tools/is-displayed.tool.ts","../src/tools/scroll-down.tool.ts","../src/tools/scroll-up.tool.ts","../src/scripts/get-interactable-elements.ts","../src/locators/source-parsing.ts","../src/locators/element-filter.ts","../src/locators/locator-generation.ts","../src/locators/generate-all-locators.ts","../src/utils/mobile-elements.ts","../src/tools/get-visible-elements.tool.ts","../src/utils/strip-undefined.ts","../src/tools/take-screenshot.tool.ts","../src/tools/cookies.tool.ts","../src/tools/get-accessibility-tree.tool.ts","../src/tools/app-session.tool.ts","../src/config/appium.config.ts","../src/tools/gestures.tool.ts","../src/tools/app-actions.tool.ts","../src/tools/context.tool.ts","../src/tools/device.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, clickToolViaText, clickViaTextToolDefinition } from './tools/click.tool';\nimport { setValueTool, setValueToolDefinition } from './tools/set-value.tool';\nimport { findElementTool, findElementToolDefinition } from './tools/find-element.tool';\nimport { getElementTextTool, getElementTextToolDefinition } from './tools/get-element-text.tool';\nimport { isDisplayedTool, isDisplayedToolDefinition } from './tools/is-displayed.tool';\nimport { scrollDownTool, scrollDownToolDefinition } from './tools/scroll-down.tool';\nimport { scrollUpTool, scrollUpToolDefinition } from './tools/scroll-up.tool';\nimport { getVisibleElementsTool, getVisibleElementsToolDefinition } from './tools/get-visible-elements.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 { getAccessibilityToolDefinition, getAccessibilityTreeTool } from './tools/get-accessibility-tree.tool';\nimport { startAppTool, startAppToolDefinition } from './tools/app-session.tool';\nimport {\n dragAndDropTool,\n dragAndDropToolDefinition,\n longPressTool,\n longPressToolDefinition,\n swipeTool,\n swipeToolDefinition,\n tapElementTool,\n tapElementToolDefinition,\n} from './tools/gestures.tool';\nimport {\n activateAppTool,\n activateAppToolDefinition,\n getAppStateTool,\n getAppStateToolDefinition,\n terminateAppTool,\n terminateAppToolDefinition,\n} 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 getDeviceInfoTool,\n getDeviceInfoToolDefinition,\n getGeolocationTool,\n getGeolocationToolDefinition,\n getOrientationTool,\n getOrientationToolDefinition,\n hideKeyboardTool,\n hideKeyboardToolDefinition,\n isDeviceLockedTool,\n isDeviceLockedToolDefinition,\n isKeyboardShownTool,\n isKeyboardShownToolDefinition,\n lockDeviceTool,\n lockDeviceToolDefinition,\n openNotificationsTool,\n openNotificationsToolDefinition,\n pressKeyCodeTool,\n pressKeyCodeToolDefinition,\n rotateDeviceTool,\n rotateDeviceToolDefinition,\n sendKeysTool,\n sendKeysToolDefinition,\n setGeolocationTool,\n setGeolocationToolDefinition,\n shakeDeviceTool,\n shakeDeviceToolDefinition,\n unlockDeviceTool,\n unlockDeviceToolDefinition,\n} from './tools/device.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 browser control (headed/headless) and 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(scrollDownToolDefinition, scrollDownTool);\nregisterTool(scrollUpToolDefinition, scrollUpTool);\n\n// Element Interaction\nregisterTool(findElementToolDefinition, findElementTool);\nregisterTool(clickToolDefinition, clickTool);\nregisterTool(clickViaTextToolDefinition, clickToolViaText);\nregisterTool(setValueToolDefinition, setValueTool);\n\n// Element Inspection\nregisterTool(getElementTextToolDefinition, getElementTextTool);\nregisterTool(isDisplayedToolDefinition, isDisplayedTool);\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(longPressToolDefinition, longPressTool);\nregisterTool(dragAndDropToolDefinition, dragAndDropTool);\n\n// App Lifecycle Management\nregisterTool(getAppStateToolDefinition, getAppStateTool);\nregisterTool(activateAppToolDefinition, activateAppTool);\nregisterTool(terminateAppToolDefinition, terminateAppTool);\n\n// Context Switching (Native/WebView)\nregisterTool(getContextsToolDefinition, getContextsTool);\nregisterTool(getCurrentContextToolDefinition, getCurrentContextTool);\nregisterTool(switchContextToolDefinition, switchContextTool);\n\n// Device Interaction\nregisterTool(getDeviceInfoToolDefinition, getDeviceInfoTool);\nregisterTool(rotateDeviceToolDefinition, rotateDeviceTool);\nregisterTool(getOrientationToolDefinition, getOrientationTool);\nregisterTool(lockDeviceToolDefinition, lockDeviceTool);\nregisterTool(unlockDeviceToolDefinition, unlockDeviceTool);\nregisterTool(isDeviceLockedToolDefinition, isDeviceLockedTool);\nregisterTool(shakeDeviceToolDefinition, shakeDeviceTool);\nregisterTool(sendKeysToolDefinition, sendKeysTool);\nregisterTool(pressKeyCodeToolDefinition, pressKeyCodeTool);\nregisterTool(hideKeyboardToolDefinition, hideKeyboardTool);\nregisterTool(isKeyboardShownToolDefinition, isKeyboardShownTool);\nregisterTool(openNotificationsToolDefinition, openNotificationsTool);\nregisterTool(getGeolocationToolDefinition, getGeolocationTool);\nregisterTool(setGeolocationToolDefinition, setGeolocationTool);\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\nexport const startBrowserToolDefinition: ToolDefinition = {\n name: 'start_browser',\n description: 'starts a browser session and sets it to the current state',\n inputSchema: {\n headless: z.boolean().optional(),\n windowWidth: z.number().min(400).max(3840).optional(),\n windowHeight: z.number().min(400).max(2160).optional(),\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 ({ headless = false, windowWidth = 1280, windowHeight = 1080}: {\n headless?: boolean;\n windowWidth?: number;\n windowHeight?: number;\n}): Promise<CallToolResult> => {\n const chromeArgs = [\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 (headless) {\n chromeArgs.push('--headless=new');\n chromeArgs.push('--disable-gpu');\n chromeArgs.push('--disable-dev-shm-usage');\n }\n\n const browser = await remote({\n capabilities: {\n browserName: 'chrome',\n 'goog:chromeOptions': {\n args: chromeArgs,\n },\n acceptInsecureCerts: true,\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: false,\n });\n\n const modeText = headless ? 'headless' : 'headed';\n return {\n content: [{\n type: 'text',\n text: `Browser started in ${modeText} mode with sessionId: ${sessionId} (${windowWidth}x${windowHeight})`,\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};","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\nexport const clickViaTextToolDefinition: ToolDefinition = {\n name: 'click_via_text',\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\nexport const clickToolViaText: ToolCallback = async ({ text, scrollToView, timeout = defaultTimeout}: {\n text: string;\n scrollToView?: boolean;\n timeout?: number\n}): Promise<CallToolResult> => clickAction(`//a[contains(text(), '${text}')]`, 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 { 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 findElementToolDefinition: ToolDefinition = {\n name: 'find_element',\n description: 'finds 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\\']\")'),\n timeout: z.number().optional().describe('Maximum time to wait for element in milliseconds'),\n },\n};\n\nexport const findElementTool: ToolCallback = async ({ selector, timeout = defaultTimeout}: {\n selector: string;\n timeout?: number\n}) => {\n try {\n const browser = getBrowser();\n await browser.waitUntil(browser.$(selector).isExisting, { timeout });\n return {\n content: [{ type: 'text', text: 'Element found' }],\n };\n } catch (e) {\n return {\n content: [{ type: 'text', text: `Error finding element: ${e}` }],\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\nconst defaultTimeout: number = 3000;\n\nexport const getElementTextToolDefinition: ToolDefinition = {\n name: 'get_element_text',\n description: 'gets the text content of 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\\']\")'),\n timeout: z.number().optional().describe('Maximum time to wait for element in milliseconds'),\n },\n};\n\nexport const getElementTextTool: ToolCallback = async ({ selector, timeout = defaultTimeout}: {\n selector: string;\n timeout?: number\n}) => {\n try {\n const browser = getBrowser();\n await browser.waitUntil(browser.$(selector).isExisting, { timeout });\n const text = await browser.$(selector).getText();\n return {\n content: [{ type: 'text', text: `Text from element \"${selector}\": ${text}` }],\n };\n } catch (e) {\n return {\n content: [{ type: 'text', text: `Error getting element text: ${e}` }],\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\nconst defaultTimeout: number = 3000;\n\nexport const isDisplayedToolDefinition: ToolDefinition = {\n name: 'is_displayed',\n description: 'checks if an element is displayed',\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 timeout: z.number().optional().describe('Maximum time to wait for element in milliseconds'),\n },\n};\n\nexport const isDisplayedTool: ToolCallback = async ({ selector, timeout = defaultTimeout}: {\n selector: string;\n timeout?: number\n}) => {\n try {\n const browser = getBrowser();\n await browser.waitUntil(browser.$(selector).isExisting, { timeout });\n const displayed = await browser.$(selector).isDisplayed();\n return {\n content: [{\n type: 'text',\n text: `Element with selector \"${selector}\" is ${displayed ? 'displayed' : 'not displayed'}`\n }],\n };\n } catch (e) {\n return {\n content: [{ type: 'text', text: `Error checking if element is displayed: ${e}` }],\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 scrollDownToolDefinition: ToolDefinition = {\n name: 'scroll_down',\n description: 'scrolls the page down by specified pixels',\n inputSchema: {\n pixels: z.number().optional().default(500),\n },\n};\n\nexport const scrollDownTool: ToolCallback = async ({ pixels = 500}: { pixels?: number }) => {\n try {\n const browser = getBrowser();\n await browser.execute((scrollPixels) => {\n window.scrollBy(0, scrollPixels);\n }, pixels);\n return {\n content: [{ type: 'text', text: `Scrolled down ${pixels} pixels` }],\n };\n } catch (e) {\n return {\n content: [{ type: 'text', text: `Error scrolling down: ${e}` }],\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 scrollUpToolDefinition: ToolDefinition = {\n name: 'scroll_up',\n description: 'scrolls the page up by specified pixels',\n inputSchema: {\n pixels: z.number().optional().default(500),\n },\n};\n\nexport const scrollUpTool: ToolCallback = async ({ pixels = 500}: { pixels?: number }) => {\n try {\n const browser = getBrowser();\n await browser.execute((scrollPixels) => {\n window.scrollBy(0, -scrollPixels);\n }, pixels);\n return {\n content: [{ type: 'text', text: `Scrolled up ${pixels} pixels` }],\n };\n } catch (e) {\n return {\n content: [{ type: 'text', text: `Error scrolling up: ${e}` }],\n };\n }\n};","/**\n * Browser script to get visible elements on the page\n * Supports interactable elements, visual elements, or both\n *\n * @param elementType - Type of elements to return: 'interactable', 'visual', or 'all'\n */\nconst elementsScript = (elementType: 'interactable' | 'visual' | 'all' = 'interactable') => (function () {\n const interactableSelectors = [\n 'a[href]', // Links with href\n 'button', // Buttons\n 'input:not([type=\"hidden\"])', // Input fields (except hidden)\n 'select', // Select dropdowns\n 'textarea', // Text areas\n '[role=\"button\"]', // Elements with button role\n '[role=\"link\"]', // Elements with link role\n '[role=\"checkbox\"]', // Elements with checkbox role\n '[role=\"radio\"]', // Elements with radio role\n '[role=\"tab\"]', // Elements with tab role\n '[role=\"menuitem\"]', // Elements with menuitem role\n '[role=\"combobox\"]', // Elements with combobox role\n '[role=\"option\"]', // Elements with option role\n '[role=\"switch\"]', // Elements with switch role\n '[role=\"slider\"]', // Elements with slider role\n '[role=\"textbox\"]', // Elements with textbox role\n '[role=\"searchbox\"]', // Elements with searchbox role\n '[contenteditable=\"true\"]', // Editable content\n '[tabindex]:not([tabindex=\"-1\"])', // Elements with tabindex\n ];\n\n const visualSelectors = [\n 'img', // Images\n 'picture', // Picture elements\n 'svg', // SVG graphics\n 'video', // Video elements\n 'canvas', // Canvas elements\n '[style*=\"background-image\"]', // Elements with background images\n ];\n\n /**\n * Check if an element is visible\n * @param {HTMLElement} element - The element to check\n * @returns {boolean} - Whether the element is visible\n */\n function isVisible(element: HTMLElement) {\n // Use checkVisibility if available (modern browsers)\n if (typeof element.checkVisibility === 'function') {\n return element.checkVisibility({\n opacityProperty: true,\n visibilityProperty: true,\n contentVisibilityAuto: true,\n });\n }\n\n // Fallback for browsers that don't support checkVisibility\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 /**\n * Get a CSS selector for an element\n * @param {HTMLElement} element - The element to get a selector for\n * @returns {string} - The CSS selector\n */\n function getCssSelector(element: HTMLElement) {\n if (element.id) {\n return `#${CSS.escape(element.id)}`;\n }\n\n // Try to build a selector with classes if available\n if (element.className && typeof element.className === 'string') {\n const classes = element.className.trim().split(/\\s+/).filter(Boolean);\n if (classes.length > 0) {\n // Use up to 2 classes to avoid overly complex selectors\n const classSelector = classes.slice(0, 2).map(c => `.${CSS.escape(c)}`).join('');\n const tagWithClass = `${element.tagName.toLowerCase()}${classSelector}`;\n\n // Check if this selector uniquely identifies the element\n if (document.querySelectorAll(tagWithClass).length === 1) {\n return tagWithClass;\n }\n }\n }\n\n // Build a path-based selector\n let current: HTMLElement | null = element;\n const path = [];\n\n while (current && current !== document.documentElement) {\n let selector = current.tagName.toLowerCase();\n\n // Add ID if available\n if (current.id) {\n selector = `#${CSS.escape(current.id)}`;\n path.unshift(selector);\n break;\n }\n\n // Add position among siblings\n const parent = current.parentElement;\n if (parent) {\n const siblings = Array.from(parent.children).filter(child =>\n child.tagName === current!.tagName,\n );\n\n if (siblings.length > 1) {\n const index = siblings.indexOf(current) + 1;\n selector += `:nth-child(${index})`;\n }\n }\n\n path.unshift(selector);\n current = current.parentElement;\n\n // Limit path length to avoid overly complex selectors\n if (path.length >= 4) {\n break;\n }\n }\n\n return path.join(' > ');\n }\n\n /**\n * Get all visible elements on the page based on elementType\n * @returns {Record<string, unknown>[]} - Array of element information objects\n */\n function getElements(): Record<string, unknown>[] {\n // Select which selectors to use based on elementType\n const selectors: string[] = [];\n if (elementType === 'interactable' || elementType === 'all') {\n selectors.push(...interactableSelectors);\n }\n if (elementType === 'visual' || elementType === 'all') {\n selectors.push(...visualSelectors);\n }\n\n // Get all potentially matching elements\n const allElements: Element[] = [];\n selectors.forEach(selector => {\n const elements = document.querySelectorAll(selector);\n elements.forEach(element => {\n if (!allElements.includes(element)) {\n allElements.push(element);\n }\n });\n });\n\n // Filter for visible elements and collect information\n const elementInfos = allElements\n .filter(element => isVisible(element as HTMLElement) && !(element as HTMLInputElement).disabled)\n .map(element => {\n const el = element as HTMLElement;\n const inputEl = element as HTMLInputElement;\n\n // Get element information\n const rect = el.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 // Build object with only defined values (no null clutter in TOON output)\n const info: Record<string, unknown> = {\n tagName: el.tagName.toLowerCase(),\n cssSelector: getCssSelector(el),\n isInViewport: isInViewport,\n };\n\n // Only add properties that have actual values\n const type = el.getAttribute('type');\n if (type) info.type = type;\n\n const id = el.id;\n if (id) info.id = id;\n\n const className = el.className;\n if (className && typeof className === 'string') info.className = className;\n\n const textContent = el.textContent?.trim();\n if (textContent) info.textContent = textContent;\n\n const value = inputEl.value;\n if (value) info.value = value;\n\n const placeholder = inputEl.placeholder;\n if (placeholder) info.placeholder = placeholder;\n\n const href = el.getAttribute('href');\n if (href) info.href = href;\n\n const ariaLabel = el.getAttribute('aria-label');\n if (ariaLabel) info.ariaLabel = ariaLabel;\n\n const role = el.getAttribute('role');\n if (role) info.role = role;\n\n // Visual element specific properties\n const src = el.getAttribute('src');\n if (src) info.src = src;\n\n const alt = el.getAttribute('alt');\n if (alt) info.alt = alt;\n\n // Check for background-image (only if it's a visual element type query)\n if (elementType === 'visual' || elementType === 'all') {\n const bgImage = window.getComputedStyle(el).backgroundImage;\n if (bgImage && bgImage !== 'none') info.backgroundImage = bgImage;\n }\n\n return info;\n });\n\n return elementInfos;\n }\n\n return getElements();\n})();\n\nexport default elementsScript;","/**\n * XML page source parsing utilities\n * Converts Appium page source XML to traversable JSON tree\n *\n * Based on: https://github.com/appium/appium-mcp/blob/main/src/locators/source-parsing.ts\n */\n\nimport { DOMParser } from '@xmldom/xmldom';\n\nexport interface ElementAttributes {\n // Android attributes\n 'resource-id'?: string;\n 'content-desc'?: string;\n text?: string;\n class?: string;\n package?: string;\n clickable?: string;\n 'long-clickable'?: string;\n focusable?: string;\n checkable?: string;\n scrollable?: string;\n enabled?: string;\n displayed?: string;\n bounds?: string; // Format: \"[x1,y1][x2,y2]\"\n\n // iOS attributes\n type?: string;\n name?: string;\n label?: string;\n value?: string;\n accessible?: string;\n visible?: string;\n x?: string;\n y?: string;\n width?: string;\n height?: string;\n\n // Generic\n [key: string]: string | undefined;\n}\n\nexport interface JSONElement {\n children: JSONElement[];\n tagName: string;\n attributes: ElementAttributes;\n path: string; // Dot-separated index path for tree traversal\n}\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 // ELEMENT_NODE\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 // Extract attributes if this is an element node\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 // Replace newlines in attribute values\n attributes[attr.name] = attr.value.replace(/(\\n)/gm, '\\\\n');\n }\n }\n }\n\n // Build path: dot-separated index chain (e.g., \"0.2.1\")\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 * Convert XML page source to JSON tree structure\n * @param sourceXML - The XML string from getPageSource()\n * @returns JSONElement tree or null if parsing fails\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 // Handle parsing errors\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 // Get the first element child\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 Android bounds string \"[x1,y1][x2,y2]\" to coordinates\n * @param bounds - Bounds string in format \"[x1,y1][x2,y2]\"\n * @returns Object with x, y, width, height\n */\nexport function parseAndroidBounds(bounds: string): {\n x: number;\n y: number;\n width: number;\n height: number;\n} {\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 * @param attributes - Element attributes\n * @returns Object with x, y, width, height\n */\nexport function parseIOSBounds(attributes: ElementAttributes): {\n x: number;\n y: number;\n width: number;\n height: number;\n} {\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 * @param root - Root JSONElement\n * @returns Array of all elements in tree\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 * Used to determine if a selector would be unique\n */\nexport function countAttributeOccurrences(\n sourceXML: string,\n attribute: string,\n value: string,\n): number {\n // Escape special regex characters in value\n const escapedValue = value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n // Match attribute=\"value\" pattern\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\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 platforms\n *\n * Based on: https://github.com/appium/appium-mcp/blob/main/src/locators/element-filter.ts\n */\n\nimport type { JSONElement } from './source-parsing';\n\nexport interface FilterOptions {\n includeTagNames?: string[]; // Only include these tags (whitelist)\n excludeTagNames?: string[]; // Exclude these tags (blacklist)\n requireAttributes?: string[]; // Must have at least one of these attributes\n minAttributeCount?: number; // Minimum number of non-empty attributes\n fetchableOnly?: boolean; // Only interactable elements\n clickableOnly?: boolean; // Only elements with clickable=\"true\"\n visibleOnly?: boolean; // Only visible/displayed elements\n}\n\n/**\n * Android interactive element types\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\n/**\n * iOS interactive element types\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\n/**\n * Android layout containers - typically not interactive targets\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\n/**\n * iOS layout containers - typically not interactive targets\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/**\n * Check if element tag matches any in the list (handles partial matches)\n */\nfunction matchesTagList(tagName: string, tagList: string[]): boolean {\n // Exact match\n if (tagList.includes(tagName)) {\n return true;\n }\n\n // Partial match for tags with package prefixes\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 include list provided, element must match it\n if (includeTagNames.length > 0 && !matchesTagList(element.tagName, includeTagNames)) {\n return false;\n }\n\n // If element matches exclude list, filter it out\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 // Check required attributes\n if (requireAttributes.length > 0) {\n const hasRequiredAttr = requireAttributes.some((attr) => element.attributes?.[attr]);\n if (!hasRequiredAttr) return false;\n }\n\n // Check minimum attribute count\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\n const interactableTags = isAndroid ? ANDROID_INTERACTABLE_TAGS : IOS_INTERACTABLE_TAGS;\n\n // Check if tag is interactable\n if (matchesTagList(element.tagName, interactableTags)) {\n return true;\n }\n\n // Check clickable/focusable attributes (Android)\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 // Check accessible attribute (iOS)\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 * Elements with content should be kept even if they're containers\n */\nexport function hasMeaningfulContent(\n element: JSONElement,\n platform: 'android' | 'ios',\n): boolean {\n const attrs = element.attributes;\n\n // Check for text content\n if (attrs.text && attrs.text.trim() !== '' && attrs.text !== 'null') {\n return true;\n }\n\n if (platform === 'android') {\n // Android: content-desc is accessibility info\n if (attrs['content-desc'] && attrs['content-desc'].trim() !== '' && attrs['content-desc'] !== 'null') {\n return true;\n }\n } else {\n // iOS: label or name is accessibility info\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'], // Always exclude root hierarchy node\n requireAttributes = [],\n minAttributeCount = 0,\n fetchableOnly = false,\n clickableOnly = false,\n visibleOnly = true,\n } = filters;\n\n // Check tag name filters\n if (!matchesTagFilters(element, includeTagNames, excludeTagNames)) {\n return false;\n }\n\n // Check attribute filters\n if (!matchesAttributeFilters(element, requireAttributes, minAttributeCount)) {\n return false;\n }\n\n // Check clickable filter (Android only)\n if (clickableOnly && element.attributes?.clickable !== 'true') {\n return false;\n }\n\n // Check visible/displayed filter\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 // Check fetchable/interactable filter\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 * Generate multiple locator strategies for an element\n *\n * Based on: https://github.com/appium/appium-mcp/blob/main/src/locators/locator-generation.ts\n */\n\nimport type { JSONElement } from './source-parsing';\nimport { isAttributeUnique } from './source-parsing';\n\nexport type LocatorStrategy =\n | 'accessibility-id'\n | 'id'\n | 'class-name'\n | 'xpath'\n | 'predicate-string'\n | 'class-chain'\n | 'uiautomator'\n | 'text';\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 * Get simple locators based on single attributes\n * These are preferred because they're most stable and readable\n */\nfunction getSimpleSuggestedLocators(\n element: JSONElement,\n sourceXML: string,\n isNative: boolean,\n automationName: string,\n): [LocatorStrategy, string][] {\n const results: [LocatorStrategy, string][] = [];\n const isAndroid = automationName.toLowerCase().includes('uiautomator');\n const attrs = element.attributes;\n\n if (isAndroid) {\n // Android simple locators\n\n // 1. Resource ID (most stable)\n const resourceId = attrs['resource-id'];\n if (isValidValue(resourceId) && isAttributeUnique(sourceXML, 'resource-id', resourceId)) {\n results.push(['id', `android=new UiSelector().resourceId(\"${resourceId}\")`]);\n }\n\n // 2. Content Description (accessibility)\n const contentDesc = attrs['content-desc'];\n if (isValidValue(contentDesc) && isAttributeUnique(sourceXML, 'content-desc', contentDesc)) {\n results.push(['accessibility-id', `~${contentDesc}`]);\n }\n\n // 3. Text (visible text)\n const text = attrs.text;\n if (isValidValue(text) && text.length < 100 && isAttributeUnique(sourceXML, 'text', text)) {\n results.push(['text', `android=new UiSelector().text(\"${escapeText(text)}\")`]);\n }\n } else {\n // iOS simple locators\n\n // 1. Accessibility ID (name attribute)\n const name = attrs.name;\n if (isValidValue(name) && isAttributeUnique(sourceXML, 'name', name)) {\n results.push(['accessibility-id', `~${name}`]);\n }\n\n // 2. Label (visible text, often same as name)\n const label = attrs.label;\n if (isValidValue(label) && label !== name && isAttributeUnique(sourceXML, 'label', label)) {\n results.push(['predicate-string', `-ios predicate string:label == \"${escapeText(label)}\"`]);\n }\n\n // 3. Value\n const value = attrs.value;\n if (isValidValue(value) && isAttributeUnique(sourceXML, 'value', value)) {\n results.push(['predicate-string', `-ios predicate string:value == \"${escapeText(value)}\"`]);\n }\n }\n\n return results;\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 // Build selector with available attributes\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 // Use AND for multiple conditions\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 // Simple class chain with type\n if (!tagName.startsWith('XCUI')) return null;\n\n let selector = `**/${tagName}`;\n\n // Add label predicate if available\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 // Android XPath attributes\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 // iOS XPath attributes\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 // Build XPath\n if (conditions.length === 0) {\n // Fallback: just the tag\n return `//${tagName}`;\n }\n\n // Combine conditions with 'and'\n return `//${tagName}[${conditions.join(' and ')}]`;\n}\n\n/**\n * Get complex locators (combinations, XPath, etc.)\n */\nfunction getComplexSuggestedLocators(\n element: JSONElement,\n sourceXML: string,\n isNative: boolean,\n automationName: string,\n): [LocatorStrategy, string][] {\n const results: [LocatorStrategy, string][] = [];\n const isAndroid = automationName.toLowerCase().includes('uiautomator');\n\n if (isAndroid) {\n // Android complex locators\n\n // UiAutomator with multiple attributes\n const uiAutomator = buildUiAutomatorSelector(element);\n if (uiAutomator) {\n results.push(['uiautomator', uiAutomator]);\n }\n\n // XPath\n const xpath = buildXPath(element, sourceXML, true);\n if (xpath) {\n results.push(['xpath', xpath]);\n }\n\n // Class name (least specific)\n if (isValidValue(element.attributes.class)) {\n results.push([\n 'class-name',\n `android=new UiSelector().className(\"${element.attributes.class}\")`,\n ]);\n }\n } else {\n // iOS complex locators\n\n // Predicate string with multiple conditions\n const predicate = buildPredicateString(element);\n if (predicate) {\n results.push(['predicate-string', predicate]);\n }\n\n // Class chain\n const classChain = buildClassChain(element);\n if (classChain) {\n results.push(['class-chain', classChain]);\n }\n\n // XPath\n const xpath = buildXPath(element, sourceXML, false);\n if (xpath) {\n results.push(['xpath', xpath]);\n }\n\n // Class name (least specific)\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 * Returns array of [strategy, value] tuples ordered by priority\n *\n * Priority order:\n * Android: id > accessibility-id > text > xpath > uiautomator > class-name\n * iOS: accessibility-id > predicate-string > class-chain > xpath > class-name\n */\nexport function getSuggestedLocators(\n element: JSONElement,\n sourceXML: string,\n isNative: boolean,\n automationName: string,\n): [LocatorStrategy, string][] {\n // Get simple (single attribute) locators first\n const simpleLocators = getSimpleSuggestedLocators(element, sourceXML, isNative, automationName);\n\n // Get complex (combination) locators\n const complexLocators = getComplexSuggestedLocators(element, sourceXML, isNative, automationName);\n\n // Combine, removing duplicates (keep first occurrence)\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 isNative: boolean,\n automationName: string,\n): string | null {\n const locators = getSuggestedLocators(element, sourceXML, isNative, 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 // Use first locator for each strategy\n if (!result[strategy]) {\n result[strategy] = value;\n }\n }\n return result;\n}\n","/**\n * Main orchestrator for generating locators from page source\n *\n * Based on: https://github.com/appium/appium-mcp/blob/main/src/locators/generate-all-locators.ts\n */\n\nimport type { LocatorStrategy } from './locator-generation';\nimport { getSuggestedLocators, locatorsToObject } from './locator-generation';\nimport type { JSONElement } from './source-parsing';\nimport { parseAndroidBounds, parseIOSBounds, xmlToJSON } from './source-parsing';\nimport type { FilterOptions } from './element-filter';\nimport { hasMeaningfulContent, isLayoutContainer, shouldIncludeElement } from './element-filter';\n\nexport interface ElementWithLocators {\n tagName: string;\n locators: Record<string, string>;\n text: string;\n contentDesc: string;\n resourceId: string;\n accessibilityId: string;\n label: string;\n value: string;\n className: string;\n clickable: boolean;\n enabled: boolean;\n displayed: boolean;\n bounds: { x: number; y: number; width: number; height: number };\n isInViewport: boolean;\n}\n\n/**\n * Processing context - carries all shared state through the processing pipeline\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}\n\n/**\n * Options for generating element locators\n */\nexport interface GenerateLocatorsOptions {\n platform: 'android' | 'ios';\n viewportSize?: { width: number; height: number };\n filters?: FilterOptions;\n isNative?: boolean;\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(element: JSONElement, locators: [LocatorStrategy, string][], ctx: ProcessingContext): 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 (passes filters or has meaningful content)\n */\nfunction shouldProcess(element: JSONElement, ctx: ProcessingContext): boolean {\n if (shouldIncludeElement(element, ctx.filters, ctx.isNative, ctx.automationName)) {\n return true;\n }\n // Keep layout containers that have meaningful content\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 locators = getSuggestedLocators(element, ctx.sourceXML, ctx.isNative, ctx.automationName);\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 if (!sourceJSON) {\n console.error('[generateAllElementLocators] Failed to parse page source XML');\n return [];\n }\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 };\n\n traverseTree(sourceJSON, ctx);\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 * Only includes fields that have actual values (no nulls/undefined)\n */\nexport interface MobileElementInfo {\n selector: string;\n tagName: string;\n isInViewport: boolean;\n // Optional fields - only present when they have meaningful values\n text?: string;\n resourceId?: string;\n accessibilityId?: string;\n isEnabled?: boolean;\n alternativeSelectors?: string[];\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 * Only includes fields with actual values (mirrors browser script behavior)\n */\nfunction toMobileElementInfo(element: ElementWithLocators, includeBounds: boolean): MobileElementInfo {\n const selectedLocators = selectBestLocators(element.locators);\n\n // Start with required fields\n const info: MobileElementInfo = {\n selector: selectedLocators[0] || '',\n tagName: element.tagName,\n isInViewport: element.isInViewport,\n };\n\n // Only add optional fields if they have meaningful values\n if (element.text) {\n info.text = element.text;\n }\n\n if (element.resourceId) {\n info.resourceId = element.resourceId;\n }\n\n // Use contentDesc for accessibilityId on Android, or name on iOS\n const accessId = element.accessibilityId || element.contentDesc;\n if (accessId) {\n info.accessibilityId = accessId;\n }\n\n // Only include isEnabled if it's false (true is the common case)\n if (!element.enabled) {\n info.isEnabled = false;\n }\n\n // Only add alternative selectors if we have more than one\n if (selectedLocators.length > 1) {\n info.alternativeSelectors = selectedLocators.slice(1);\n }\n\n // Only include bounds if explicitly requested\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 getInteractableElements from '../scripts/get-interactable-elements';\nimport { getMobileVisibleElements } from '../utils/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';\nimport { stripUndefinedFromArray } from '../utils/strip-undefined';\n\n/**\n * Tool definition for get_visible_elements\n */\nexport const getVisibleElementsToolDefinition: ToolDefinition = {\n name: 'get_visible_elements',\n description: 'get a list of visible (in viewport & displayed) interactable elements on the page (buttons, links, inputs). Use elementType=\"visual\" for images/SVGs. Must prefer this to take_screenshot for interactions',\n inputSchema: {\n inViewportOnly: z\n .boolean()\n .optional()\n .describe(\n 'Only return elements within the visible viewport. Default: true. Set to false to get ALL elements on the page.',\n ),\n includeContainers: z\n .boolean()\n .optional()\n .describe(\n 'Include layout containers (ViewGroup, FrameLayout, ScrollView, etc). Default: false. Set to true to see all elements including layouts.',\n ),\n includeBounds: z\n .boolean()\n .optional()\n .describe(\n 'Include element bounds/coordinates (x, y, width, height). Default: false. Set to true for coordinate-based interactions or layout debugging.',\n ),\n elementType: z\n .enum(['interactable', 'visual', 'all'])\n .optional()\n .describe(\n 'Type of elements to return: \"interactable\" (default) for buttons/links/inputs, \"visual\" for images/SVGs, \"all\" for both.',\n ),\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 elementType?: 'interactable' | 'visual' | 'all';\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 elementType = 'interactable',\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 const raw = await browser.execute(getInteractableElements, elementType);\n elements = stripUndefinedFromArray(raw);\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 = {\n total,\n showing: elements.length,\n hasMore: offset + elements.length < total,\n elements,\n };\n\n return {\n content: [{ type: 'text', text: encode(result) }],\n };\n } catch (e) {\n return {\n content: [{ type: 'text', text: `Error getting visible elements: ${e}` }],\n };\n }\n};","/**\n * Utility to strip undefined, null, and empty string values from objects\n *\n * Used to clean up element data before encoding to avoid null clutter in TOON output.\n * TOON format is columnar - it creates a unified schema from ALL objects.\n * If ANY object has a field, ALL rows get that column with null for missing values.\n * By stripping undefined/null/empty values BEFORE encoding, we ensure TOON only\n * creates columns for fields that actually have values.\n */\n\n/**\n * Strip undefined, null, and empty string values from an object\n * @param obj - The object to clean\n * @returns A new object with only defined, non-null, non-empty values\n */\nexport function stripUndefined<T extends Record<string, unknown>>(obj: T): Partial<T> {\n return Object.fromEntries(\n Object.entries(obj).filter(([_, v]) => v !== undefined && v !== null && v !== ''),\n ) as Partial<T>;\n}\n\n/**\n * Strip undefined values from an array of objects\n * @param arr - The array of objects to clean\n * @returns A new array with cleaned objects\n */\nexport function stripUndefinedFromArray<T extends Record<string, unknown>>(arr: T[]): Partial<T>[] {\n return arr.map(stripUndefined);\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 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\nexport const takeScreenshotTool: ToolCallback = async ({ outputPath}: { outputPath?: string }) => {\n try {\n const browser = getBrowser();\n const screenshot = await browser.takeScreenshot();\n\n if (outputPath) {\n const fs = await import('node:fs');\n await fs.promises.writeFile(outputPath, screenshot, 'base64');\n return {\n content: [{ type: 'text', text: `Screenshot saved to ${outputPath}` }],\n };\n }\n return {\n content: [\n { type: 'text', text: 'Screenshot captured as base64:' },\n { type: 'image', data: screenshot.toString(), mimeType: 'image/png' },\n ],\n };\n\n } catch (e) {\n return {\n content: [{ type: 'text', text: `Error taking screenshot: ${e.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, SameSiteOptions } 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 expires: 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 expires,\n httpOnly,\n secure,\n sameSite,\n}: {\n name: string;\n value: string;\n domain?: string;\n path?: string;\n expires?: number;\n httpOnly?: boolean;\n secure?: boolean;\n sameSite?: SameSiteOptions;\n}): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n\n // Build cookie object\n const cookie: Cookie = {\n name,\n value,\n path,\n domain,\n expiry: expires,\n httpOnly,\n secure,\n sameSite,\n };\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 { getBrowser } from './browser.tool';\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\n/**\n * Tool definition for get_accessibility\n */\nexport const getAccessibilityToolDefinition: ToolDefinition = {\n name: 'get_accessibility',\n description: 'gets accessibility tree snapshot with semantic information about page elements (roles, names, states). Browser-only - use when get_visible_elements does not return expected 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., [\"button\", \"link\", \"textbox\"]). Default: all roles.'),\n namedOnly: z.boolean().optional()\n .describe('Only return nodes with a name/label. Default: true. Filters out anonymous containers.'),\n },\n};\n\n/**\n * Flatten a hierarchical accessibility tree into a flat list\n * Only includes properties that have actual values (no null clutter)\n * @param node - The accessibility node\n * @param result - Accumulator array\n */\nfunction flattenAccessibilityTree(node: any, result: any[] = []): any[] {\n if (!node) return result;\n\n // Add current node (excluding root WebArea unless it has meaningful content)\n if (node.role !== 'WebArea' || node.name) {\n const entry: Record<string, any> = {};\n\n // Only add properties that have actual values\n if (node.role) entry.role = node.role;\n if (node.name) entry.name = node.name;\n if (node.value !== undefined && node.value !== '') entry.value = node.value;\n if (node.description) entry.description = node.description;\n if (node.keyshortcuts) entry.keyshortcuts = node.keyshortcuts;\n if (node.roledescription) entry.roledescription = node.roledescription;\n if (node.valuetext) entry.valuetext = node.valuetext;\n if (node.disabled) entry.disabled = node.disabled;\n if (node.expanded !== undefined) entry.expanded = node.expanded;\n if (node.focused) entry.focused = node.focused;\n if (node.modal) entry.modal = node.modal;\n if (node.multiline) entry.multiline = node.multiline;\n if (node.multiselectable) entry.multiselectable = node.multiselectable;\n if (node.readonly) entry.readonly = node.readonly;\n if (node.required) entry.required = node.required;\n if (node.selected) entry.selected = node.selected;\n if (node.checked !== undefined) entry.checked = node.checked;\n if (node.pressed !== undefined) entry.pressed = node.pressed;\n if (node.level !== undefined) entry.level = node.level;\n if (node.valuemin !== undefined) entry.valuemin = node.valuemin;\n if (node.valuemax !== undefined) entry.valuemax = node.valuemax;\n if (node.autocomplete) entry.autocomplete = node.autocomplete;\n if (node.haspopup) entry.haspopup = node.haspopup;\n if (node.invalid) entry.invalid = node.invalid;\n if (node.orientation) entry.orientation = node.orientation;\n\n result.push(entry);\n }\n\n // Recursively process children\n if (node.children && Array.isArray(node.children)) {\n for (const child of node.children) {\n flattenAccessibilityTree(child, result);\n }\n }\n\n return result;\n}\n\nexport const getAccessibilityTreeTool: ToolCallback = async (args: {\n limit?: number;\n offset?: number;\n roles?: string[];\n namedOnly?: boolean;\n}): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n\n // Check if this is a mobile session - accessibility tree is browser-only\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, namedOnly = true } = args || {};\n\n // Get Puppeteer instance for native accessibility API\n const puppeteer = await browser.getPuppeteer();\n const pages = await puppeteer.pages();\n\n if (pages.length === 0) {\n return {\n content: [{ type: 'text', text: 'No active pages found' }],\n };\n }\n\n const page = pages[0];\n\n // Get accessibility snapshot with interestingOnly filter\n const snapshot = await page.accessibility.snapshot({\n interestingOnly: true, // Filter to only interesting/semantic nodes\n });\n\n if (!snapshot) {\n return {\n content: [{ type: 'text', text: 'No accessibility tree available' }],\n };\n }\n\n // Flatten the hierarchical tree into a flat list\n let nodes = flattenAccessibilityTree(snapshot);\n\n // Filter to named nodes only (removes anonymous containers, StaticText duplicates)\n if (namedOnly) {\n nodes = nodes.filter(n => n.name && n.name.trim() !== '');\n }\n\n // Filter to specific roles if provided\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 // Apply pagination\n if (offset > 0) {\n nodes = nodes.slice(offset);\n }\n if (limit > 0) {\n nodes = nodes.slice(0, limit);\n }\n\n const result = {\n total,\n showing: nodes.length,\n hasMore: offset + nodes.length < total,\n nodes,\n };\n\n return {\n content: [{ type: 'text', text: encode(result) }],\n };\n } catch (e) {\n return {\n content: [{ type: 'text', text: `Error getting accessibility tree: ${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 },\n};\n\n// Access shared state from browser.tool.ts\nconst 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}): 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 } = 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 })\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 });\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,\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,\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","/**\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\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\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 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'].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 // 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'].includes(\n key,\n )\n ) {\n capabilities[`appium:${key}`] = value;\n }\n }\n\n return capabilities;\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 Element Tool\nexport const tapElementToolDefinition: ToolDefinition = {\n name: 'tap_element',\n description: 'taps an element by selector or 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 tap (if no selector provided)'),\n y: z.number().optional().describe('Y coordinate for 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 // Tap on element by 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 // Tap at coordinates\n await browser.touchAction({\n action: 'tap',\n x,\n y,\n });\n return {\n content: [{ type: 'text', text: `Tapped at coordinates: (${x}, ${y})` }],\n };\n }\n return {\n content: [{ type: 'text', text: 'Error: Must provide either selector or x,y coordinates' }],\n };\n\n } catch (e) {\n return {\n content: [{ type: 'text', text: `Error tapping element: ${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 startX: z.number().optional().describe('Start X coordinate (optional, uses screen center)'),\n startY: z.number().optional().describe('Start Y coordinate (optional, uses screen center)'),\n distance: z\n .number()\n .optional()\n .describe('Swipe distance in pixels (optional, uses percentage of screen)'),\n },\n};\n\nexport const swipeTool: ToolCallback = async (args: {\n direction: 'up' | 'down' | 'left' | 'right';\n duration?: number;\n startX?: number;\n startY?: number;\n distance?: number;\n}): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n const { direction, duration = 500, startX, startY, distance } = args;\n\n // Get screen size\n const windowSize = await browser.getWindowSize();\n const screenWidth = windowSize.width;\n const screenHeight = windowSize.height;\n\n // Calculate start and end coordinates\n const centerX = startX ?? screenWidth / 2;\n const centerY = startY ?? screenHeight / 2;\n\n const swipeDistance = distance ?? Math.min(screenWidth, screenHeight) * 0.5;\n\n let endX = centerX;\n let endY = centerY;\n\n switch (direction) {\n case 'up':\n endY = centerY - swipeDistance;\n break;\n case 'down':\n endY = centerY + swipeDistance;\n break;\n case 'left':\n endX = centerX - swipeDistance;\n break;\n case 'right':\n endX = centerX + swipeDistance;\n break;\n }\n\n // Perform swipe\n await browser.touchPerform([\n { action: 'press', options: { x: centerX, y: centerY } },\n { action: 'wait', options: { ms: duration } },\n { action: 'moveTo', options: { x: endX, y: endY } },\n { action: 'release', options: {} },\n ]);\n\n return {\n content: [\n {\n type: 'text',\n text: `Swiped ${direction} from (${Math.round(centerX)}, ${Math.round(centerY)}) to (${Math.round(endX)}, ${Math.round(endY)}) over ${duration}ms`,\n },\n ],\n };\n } catch (e) {\n return {\n content: [{ type: 'text', text: `Error swiping: ${e}` }],\n };\n }\n};\n\n// Long Press Tool\nexport const longPressToolDefinition: ToolDefinition = {\n name: 'long_press',\n description: 'performs a long press on element or 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 long press (if no selector provided)'),\n y: z.number().optional().describe('Y coordinate for long press (if no selector provided)'),\n duration: z.number().min(500).max(10000).optional().describe('Long press duration in milliseconds (default: 1000)'),\n },\n};\n\nexport const longPressTool: ToolCallback = async (args: {\n selector?: string;\n x?: number;\n y?: number;\n duration?: number;\n}): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n const { selector, x, y, duration = 1000 } = args;\n\n if (selector) {\n // Long press on element by selector\n const element = await browser.$(selector);\n await element.touchAction([\n { action: 'longPress' },\n { action: 'wait', ms: duration },\n { action: 'release' },\n ]);\n return {\n content: [{ type: 'text', text: `Long pressed element: ${selector} for ${duration}ms` }],\n };\n } else if (x !== undefined && y !== undefined) {\n // Long press at coordinates\n await browser.touchPerform([\n { action: 'press', options: { x, y } },\n { action: 'wait', options: { ms: duration } },\n { action: 'release', options: {} },\n ]);\n return {\n content: [{ type: 'text', text: `Long pressed at coordinates: (${x}, ${y}) for ${duration}ms` }],\n };\n }\n return {\n content: [{ type: 'text', text: 'Error: Must provide either selector or x,y coordinates' }],\n };\n\n } catch (e) {\n return {\n content: [{ type: 'text', text: `Error long pressing: ${e}` }],\n };\n }\n};\n\n// Drag and Drop Tool\nexport const dragAndDropToolDefinition: ToolDefinition = {\n name: 'drag_and_drop',\n description: 'drags from one location to another (mobile)',\n inputSchema: {\n fromSelector: z.string().optional().describe('Source element selector'),\n fromX: z.number().optional().describe('Source X coordinate'),\n fromY: z.number().optional().describe('Source Y coordinate'),\n toSelector: z.string().optional().describe('Target element selector'),\n toX: z.number().optional().describe('Target X coordinate'),\n toY: z.number().optional().describe('Target Y coordinate'),\n duration: z.number().min(100).max(5000).optional().describe('Drag duration in milliseconds (default: 500)'),\n },\n};\n\nexport const dragAndDropTool: ToolCallback = async (args: {\n fromSelector?: string;\n fromX?: number;\n fromY?: number;\n toSelector?: string;\n toX?: number;\n toY?: number;\n duration?: number;\n}): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n const { fromSelector, fromX, fromY, toSelector, toX, toY, duration = 500 } = args;\n\n let startX: number;\n let startY: number;\n let endX: number;\n let endY: number;\n\n // Get source coordinates\n if (fromSelector) {\n const element = await browser.$(fromSelector);\n const location = await element.getLocation();\n const size = await element.getSize();\n startX = location.x + size.width / 2;\n startY = location.y + size.height / 2;\n } else if (fromX !== undefined && fromY !== undefined) {\n startX = fromX;\n startY = fromY;\n } else {\n return {\n content: [{ type: 'text', text: 'Error: Must provide either fromSelector or fromX,fromY coordinates' }],\n };\n }\n\n // Get target coordinates\n if (toSelector) {\n const element = await browser.$(toSelector);\n const location = await element.getLocation();\n const size = await element.getSize();\n endX = location.x + size.width / 2;\n endY = location.y + size.height / 2;\n } else if (toX !== undefined && toY !== undefined) {\n endX = toX;\n endY = toY;\n } else {\n return {\n content: [{ type: 'text', text: 'Error: Must provide either toSelector or toX,toY coordinates' }],\n };\n }\n\n // Perform drag and drop\n await browser.touchPerform([\n { action: 'press', options: { x: startX, y: startY } },\n { action: 'wait', options: { ms: duration } },\n { action: 'moveTo', options: { x: endX, y: endY } },\n { action: 'release', options: {} },\n ]);\n\n return {\n content: [\n {\n type: 'text',\n text: `Dragged from (${Math.round(startX)}, ${Math.round(startY)}) to (${Math.round(endX)}, ${Math.round(endY)}) over ${duration}ms`,\n },\n ],\n };\n } catch (e) {\n return {\n content: [{ type: 'text', text: `Error dragging and dropping: ${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// 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// Activate App Tool\nexport const activateAppToolDefinition: ToolDefinition = {\n name: 'activate_app',\n description: 'activates/brings an app to foreground',\n inputSchema: {\n bundleId: z.string().describe('App bundle ID to activate (e.g., com.example.app)'),\n },\n};\n\nexport const activateAppTool: 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 await browser.execute('mobile: activateApp', appIdentifier);\n\n return {\n content: [{ type: 'text', text: `Activated app: ${bundleId}` }],\n };\n } catch (e) {\n return {\n content: [{ type: 'text', text: `Error activating app: ${e}` }],\n };\n }\n};\n\n// Terminate App Tool\nexport const terminateAppToolDefinition: ToolDefinition = {\n name: 'terminate_app',\n description: 'terminates a running app',\n inputSchema: {\n bundleId: z.string().describe('App bundle ID to terminate (e.g., com.example.app)'),\n },\n};\n\nexport const terminateAppTool: 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 await browser.execute('mobile: terminateApp', appIdentifier);\n\n return {\n content: [{ type: 'text', text: `Terminated app: ${bundleId}` }],\n };\n } catch (e) {\n return {\n content: [{ type: 'text', text: `Error terminating app: ${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 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 getDeviceInfoToolDefinition: ToolDefinition = {\n name: 'get_device_info',\n description: 'gets device information (platform, version, screen size)',\n inputSchema: {},\n};\n\nexport const getOrientationToolDefinition: ToolDefinition = {\n name: 'get_orientation',\n description: 'gets current device orientation',\n inputSchema: {},\n};\n\nexport const lockDeviceToolDefinition: ToolDefinition = {\n name: 'lock_device',\n description: 'locks the device screen',\n inputSchema: {},\n};\n\nexport const unlockDeviceToolDefinition: ToolDefinition = {\n name: 'unlock_device',\n description: 'unlocks the device screen',\n inputSchema: {},\n};\n\nexport const isDeviceLockedToolDefinition: ToolDefinition = {\n name: 'is_device_locked',\n description: 'checks if device is locked',\n inputSchema: {},\n};\n\nexport const shakeDeviceToolDefinition: ToolDefinition = {\n name: 'shake_device',\n description: 'shakes the device (iOS only)',\n inputSchema: {},\n};\n\nexport const hideKeyboardToolDefinition: ToolDefinition = {\n name: 'hide_keyboard',\n description: 'hides the on-screen keyboard',\n inputSchema: {},\n};\n\nexport const isKeyboardShownToolDefinition: ToolDefinition = {\n name: 'is_keyboard_shown',\n description: 'checks if keyboard is visible',\n inputSchema: {},\n};\n\nexport const openNotificationsToolDefinition: ToolDefinition = {\n name: 'open_notifications',\n description: 'opens the notifications panel (Android only)',\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 sendKeysToolDefinition: ToolDefinition = {\n name: 'send_keys',\n description: 'sends keys to the app (Android only)',\n inputSchema: {\n keys: z.array(z.string()).describe('Array of keys to send (e.g., [\"h\", \"e\", \"l\", \"l\", \"o\"])'),\n },\n};\n\nexport const pressKeyCodeToolDefinition: ToolDefinition = {\n name: 'press_key_code',\n description: 'presses an Android key code (Android only)',\n inputSchema: {\n keyCode: z.number().describe('Android key code (e.g., 4 for BACK, 3 for HOME)'),\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// Get Device Info Tool\nexport const getDeviceInfoTool: ToolCallback = async (): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n\n // Get various device information\n const capabilities = browser.capabilities;\n const windowSize = await browser.getWindowSize();\n\n const info = {\n platformName: capabilities.platformName,\n platformVersion: capabilities['appium:platformVersion'],\n deviceName: capabilities['appium:deviceName'],\n automationName: capabilities['appium:automationName'],\n screenSize: `${windowSize.width}x${windowSize.height}`,\n };\n\n return {\n content: [\n {\n type: 'text',\n text: `Device Info:\\n${Object.entries(info)\n .map(([key, value]) => ` ${key}: ${value}`)\n .join('\\n')}`,\n },\n ],\n };\n } catch (e) {\n return {\n content: [{ type: 'text', text: `Error getting device info: ${e}` }],\n };\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// Get Orientation Tool\nexport const getOrientationTool: ToolCallback = async (): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n\n const orientation = await browser.getOrientation();\n\n return {\n content: [{ type: 'text', text: `Current orientation: ${orientation}` }],\n };\n } catch (e) {\n return {\n content: [{ type: 'text', text: `Error getting orientation: ${e}` }],\n };\n }\n};\n\n// Lock Device Tool\nexport const lockDeviceTool: ToolCallback = async (): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n\n await browser.lock();\n\n return {\n content: [{ type: 'text', text: 'Device locked' }],\n };\n } catch (e) {\n return {\n content: [{ type: 'text', text: `Error locking device: ${e}` }],\n };\n }\n};\n\n// Unlock Device Tool\nexport const unlockDeviceTool: ToolCallback = async (): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n\n await browser.unlock();\n\n return {\n content: [{ type: 'text', text: 'Device unlocked' }],\n };\n } catch (e) {\n return {\n content: [{ type: 'text', text: `Error unlocking device: ${e}` }],\n };\n }\n};\n\n// Is Device Locked Tool\nexport const isDeviceLockedTool: ToolCallback = async (): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n\n const isLocked = await browser.isLocked();\n\n return {\n content: [{ type: 'text', text: `Device is ${isLocked ? 'locked' : 'unlocked'}` }],\n };\n } catch (e) {\n return {\n content: [{ type: 'text', text: `Error checking lock status: ${e}` }],\n };\n }\n};\n\n// Shake Device Tool (iOS only)\nexport const shakeDeviceTool: ToolCallback = async (): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n\n await browser.shake();\n\n return {\n content: [{ type: 'text', text: 'Device shaken' }],\n };\n } catch (e) {\n return {\n content: [{ type: 'text', text: `Error shaking device: ${e}` }],\n };\n }\n};\n\n// Send Keys Tool (Android only)\nexport const sendKeysTool: ToolCallback = async (args: {\n keys: string[];\n}): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n const { keys } = args;\n\n await browser.sendKeys(keys);\n\n return {\n content: [{ type: 'text', text: `Sent keys: ${keys.join('')}` }],\n };\n } catch (e) {\n return {\n content: [{ type: 'text', text: `Error sending keys: ${e}` }],\n };\n }\n};\n\n// Press Key Code Tool (Android only)\nexport const pressKeyCodeTool: ToolCallback = async (args: {\n keyCode: number;\n}): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n const { keyCode } = args;\n\n await browser.pressKeyCode(keyCode);\n\n return {\n content: [{ type: 'text', text: `Pressed key code: ${keyCode}` }],\n };\n } catch (e) {\n return {\n content: [{ type: 'text', text: `Error pressing key code: ${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// Is Keyboard Shown Tool\nexport const isKeyboardShownTool: ToolCallback = async (): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n\n const isShown = await browser.isKeyboardShown();\n\n return {\n content: [{ type: 'text', text: `Keyboard is ${isShown ? 'shown' : 'hidden'}` }],\n };\n } catch (e) {\n return {\n content: [{ type: 'text', text: `Error checking keyboard status: ${e}` }],\n };\n }\n};\n\n// Open Notifications Tool (Android only)\nexport const openNotificationsTool: ToolCallback = async (): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n\n await browser.openNotifications();\n\n return {\n content: [{ type: 'text', text: 'Opened notifications panel' }],\n };\n } catch (e) {\n return {\n content: [{ type: 'text', text: `Error opening notifications: ${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","{\n \"name\": \"@wdio/mcp\",\n \"author\": \"Vince Graics\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"git://github.com/webdriverio/mcp.git\"\n },\n \"version\": \"1.5.1\",\n \"description\": \"MCP server with WebdriverIO for browser and mobile app automation (iOS/Android via Appium)\",\n \"main\": \"./lib/server.js\",\n \"module\": \"./lib/server.js\",\n \"types\": \"./lib/server.d.ts\",\n \"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 \"start\": \"node lib/server.js\",\n \"dev\": \"tsx --watch src/server.ts\",\n \"prepare\": \"husky\"\n },\n \"dependencies\": {\n \"@modelcontextprotocol/sdk\": \"1.25\",\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 \"webdriverio\": \"9.23\",\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 \"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 },\n \"packageManager\": \"pnpm@10.12.4\"\n}\n"],"mappings":"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","names":["z","z","z","defaultTimeout","z","defaultTimeout","z","defaultTimeout","z","defaultTimeout","z","z","z","z","z","z","encode","z","remote","z","z","remote","state","z","z","z","z","state","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/source-parsing.ts","../src/locators/element-filter.ts","../src/locators/locator-generation.ts","../src/locators/generate-all-locators.ts","../src/scripts/get-visible-mobile-elements.ts","../src/tools/get-visible-elements.tool.ts","../src/utils/strip-undefined.ts","../src/tools/take-screenshot.tool.ts","../src/tools/cookies.tool.ts","../src/tools/get-accessibility-tree.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 { 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 { getAccessibilityToolDefinition, getAccessibilityTreeTool } from './tools/get-accessibility-tree.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 {\n getAppStateTool,\n getAppStateToolDefinition,\n} 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 browser control (headed/headless) and 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\nexport const startBrowserToolDefinition: ToolDefinition = {\n name: 'start_browser',\n description: 'starts a browser session and sets it to the current state',\n inputSchema: {\n headless: z.boolean().optional(),\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 },\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 headless = false,\n windowWidth = 1920,\n windowHeight = 1080,\n navigationUrl\n}: {\n headless?: boolean;\n windowWidth?: number;\n windowHeight?: number;\n navigationUrl?: string;\n}): Promise<CallToolResult> => {\n const chromeArgs = [\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 (headless) {\n chromeArgs.push('--headless=new');\n chromeArgs.push('--disable-gpu');\n chromeArgs.push('--disable-dev-shm-usage');\n }\n\n const browser = await remote({\n capabilities: {\n browserName: 'chrome',\n 'goog:chromeOptions': {\n args: chromeArgs,\n },\n acceptInsecureCerts: true,\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: false,\n });\n\n // Navigate to URL if provided\n if (navigationUrl) {\n await browser.url(navigationUrl);\n }\n\n const modeText = headless ? 'headless' : 'headed';\n const urlText = navigationUrl ? ` and navigated to ${navigationUrl}` : '';\n return {\n content: [{\n type: 'text',\n text: `Browser started in ${modeText} mode with sessionId: ${sessionId} (${windowWidth}x${windowHeight})${urlText}`,\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};","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 },\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}): 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 } = 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 // 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,\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,\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","/**\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 script to get visible elements on the page\n * Supports interactable elements, visual elements, or both\n *\n * @param elementType - Type of elements to return: 'interactable', 'visual', or 'all'\n */\nconst elementsScript = (elementType: 'interactable' | 'visual' | 'all' = 'interactable') => (function () {\n const interactableSelectors = [\n 'a[href]', // Links with href\n 'button', // Buttons\n 'input:not([type=\"hidden\"])', // Input fields (except hidden)\n 'select', // Select dropdowns\n 'textarea', // Text areas\n '[role=\"button\"]', // Elements with button role\n '[role=\"link\"]', // Elements with link role\n '[role=\"checkbox\"]', // Elements with checkbox role\n '[role=\"radio\"]', // Elements with radio role\n '[role=\"tab\"]', // Elements with tab role\n '[role=\"menuitem\"]', // Elements with menuitem role\n '[role=\"combobox\"]', // Elements with combobox role\n '[role=\"option\"]', // Elements with option role\n '[role=\"switch\"]', // Elements with switch role\n '[role=\"slider\"]', // Elements with slider role\n '[role=\"textbox\"]', // Elements with textbox role\n '[role=\"searchbox\"]', // Elements with searchbox role\n '[contenteditable=\"true\"]', // Editable content\n '[tabindex]:not([tabindex=\"-1\"])', // Elements with tabindex\n ];\n\n const visualSelectors = [\n 'img', // Images\n 'picture', // Picture elements\n 'svg', // SVG graphics\n 'video', // Video elements\n 'canvas', // Canvas elements\n '[style*=\"background-image\"]', // Elements with background images\n ];\n\n /**\n * Check if an element is visible\n * @param {HTMLElement} element - The element to check\n * @returns {boolean} - Whether the element is visible\n */\n function isVisible(element: HTMLElement) {\n // Use checkVisibility if available (modern browsers)\n if (typeof element.checkVisibility === 'function') {\n return element.checkVisibility({\n opacityProperty: true,\n visibilityProperty: true,\n contentVisibilityAuto: true,\n });\n }\n\n // Fallback for browsers that don't support checkVisibility\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 /**\n * Get a CSS selector for an element\n * @param {HTMLElement} element - The element to get a selector for\n * @returns {string} - The CSS selector\n */\n function getCssSelector(element: HTMLElement) {\n if (element.id) {\n return `#${CSS.escape(element.id)}`;\n }\n\n // Try to build a selector with classes if available\n if (element.className && typeof element.className === 'string') {\n const classes = element.className.trim().split(/\\s+/).filter(Boolean);\n if (classes.length > 0) {\n // Use up to 2 classes to avoid overly complex selectors\n const classSelector = classes.slice(0, 2).map(c => `.${CSS.escape(c)}`).join('');\n const tagWithClass = `${element.tagName.toLowerCase()}${classSelector}`;\n\n // Check if this selector uniquely identifies the element\n if (document.querySelectorAll(tagWithClass).length === 1) {\n return tagWithClass;\n }\n }\n }\n\n // Build a path-based selector\n let current: HTMLElement | null = element;\n const path = [];\n\n while (current && current !== document.documentElement) {\n let selector = current.tagName.toLowerCase();\n\n // Add ID if available\n if (current.id) {\n selector = `#${CSS.escape(current.id)}`;\n path.unshift(selector);\n break;\n }\n\n // Add position among siblings\n const parent = current.parentElement;\n if (parent) {\n const siblings = Array.from(parent.children).filter(child =>\n child.tagName === current!.tagName,\n );\n\n if (siblings.length > 1) {\n const index = siblings.indexOf(current) + 1;\n selector += `:nth-child(${index})`;\n }\n }\n\n path.unshift(selector);\n current = current.parentElement;\n\n // Limit path length to avoid overly complex selectors\n if (path.length >= 4) {\n break;\n }\n }\n\n return path.join(' > ');\n }\n\n /**\n * Get all visible elements on the page based on elementType\n * @returns {Record<string, unknown>[]} - Array of element information objects\n */\n function getElements(): Record<string, unknown>[] {\n // Select which selectors to use based on elementType\n const selectors: string[] = [];\n if (elementType === 'interactable' || elementType === 'all') {\n selectors.push(...interactableSelectors);\n }\n if (elementType === 'visual' || elementType === 'all') {\n selectors.push(...visualSelectors);\n }\n\n // Get all potentially matching elements\n const allElements: Element[] = [];\n selectors.forEach(selector => {\n const elements = document.querySelectorAll(selector);\n elements.forEach(element => {\n if (!allElements.includes(element)) {\n allElements.push(element);\n }\n });\n });\n\n // Filter for visible elements and collect information\n const elementInfos = allElements\n .filter(element => isVisible(element as HTMLElement) && !(element as HTMLInputElement).disabled)\n .map(element => {\n const el = element as HTMLElement;\n const inputEl = element as HTMLInputElement;\n\n // Get element information\n const rect = el.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 // Build object with only defined values (no null clutter in TOON output)\n const info: Record<string, unknown> = {\n tagName: el.tagName.toLowerCase(),\n cssSelector: getCssSelector(el),\n isInViewport: isInViewport,\n };\n\n // Only add properties that have actual values\n const type = el.getAttribute('type');\n if (type) info.type = type;\n\n const id = el.id;\n if (id) info.id = id;\n\n const className = el.className;\n if (className && typeof className === 'string') info.className = className;\n\n const textContent = el.textContent?.trim();\n if (textContent) info.textContent = textContent;\n\n const value = inputEl.value;\n if (value) info.value = value;\n\n const placeholder = inputEl.placeholder;\n if (placeholder) info.placeholder = placeholder;\n\n const href = el.getAttribute('href');\n if (href) info.href = href;\n\n const ariaLabel = el.getAttribute('aria-label');\n if (ariaLabel) info.ariaLabel = ariaLabel;\n\n const role = el.getAttribute('role');\n if (role) info.role = role;\n\n // Visual element specific properties\n const src = el.getAttribute('src');\n if (src) info.src = src;\n\n const alt = el.getAttribute('alt');\n if (alt) info.alt = alt;\n\n // Check for background-image (only if it's a visual element type query)\n if (elementType === 'visual' || elementType === 'all') {\n const bgImage = window.getComputedStyle(el).backgroundImage;\n if (bgImage && bgImage !== 'none') info.backgroundImage = bgImage;\n }\n\n return info;\n });\n\n return elementInfos;\n }\n\n return getElements();\n})();\n\nexport default elementsScript;","/**\n * XML page source parsing utilities\n * Converts Appium page source XML to traversable JSON tree\n *\n * Based on: https://github.com/appium/appium-mcp/blob/main/src/locators/source-parsing.ts\n */\n\nimport { DOMParser } from '@xmldom/xmldom';\n\nexport interface ElementAttributes {\n // Android attributes\n 'resource-id'?: string;\n 'content-desc'?: string;\n text?: string;\n class?: string;\n package?: string;\n clickable?: string;\n 'long-clickable'?: string;\n focusable?: string;\n checkable?: string;\n scrollable?: string;\n enabled?: string;\n displayed?: string;\n bounds?: string; // Format: \"[x1,y1][x2,y2]\"\n\n // iOS attributes\n type?: string;\n name?: string;\n label?: string;\n value?: string;\n accessible?: string;\n visible?: string;\n x?: string;\n y?: string;\n width?: string;\n height?: string;\n\n // Generic\n [key: string]: string | undefined;\n}\n\nexport interface JSONElement {\n children: JSONElement[];\n tagName: string;\n attributes: ElementAttributes;\n path: string; // Dot-separated index path for tree traversal\n}\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 // ELEMENT_NODE\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 // Extract attributes if this is an element node\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 // Replace newlines in attribute values\n attributes[attr.name] = attr.value.replace(/(\\n)/gm, '\\\\n');\n }\n }\n }\n\n // Build path: dot-separated index chain (e.g., \"0.2.1\")\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 * Convert XML page source to JSON tree structure\n * @param sourceXML - The XML string from getPageSource()\n * @returns JSONElement tree or null if parsing fails\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 // Handle parsing errors\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 // Get the first element child\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 Android bounds string \"[x1,y1][x2,y2]\" to coordinates\n * @param bounds - Bounds string in format \"[x1,y1][x2,y2]\"\n * @returns Object with x, y, width, height\n */\nexport function parseAndroidBounds(bounds: string): {\n x: number;\n y: number;\n width: number;\n height: number;\n} {\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 * @param attributes - Element attributes\n * @returns Object with x, y, width, height\n */\nexport function parseIOSBounds(attributes: ElementAttributes): {\n x: number;\n y: number;\n width: number;\n height: number;\n} {\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 * @param root - Root JSONElement\n * @returns Array of all elements in tree\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 * Used to determine if a selector would be unique\n */\nexport function countAttributeOccurrences(\n sourceXML: string,\n attribute: string,\n value: string,\n): number {\n // Escape special regex characters in value\n const escapedValue = value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n\n // Match attribute=\"value\" pattern\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\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 platforms\n *\n * Based on: https://github.com/appium/appium-mcp/blob/main/src/locators/element-filter.ts\n */\n\nimport type { JSONElement } from './source-parsing';\n\nexport interface FilterOptions {\n includeTagNames?: string[]; // Only include these tags (whitelist)\n excludeTagNames?: string[]; // Exclude these tags (blacklist)\n requireAttributes?: string[]; // Must have at least one of these attributes\n minAttributeCount?: number; // Minimum number of non-empty attributes\n fetchableOnly?: boolean; // Only interactable elements\n clickableOnly?: boolean; // Only elements with clickable=\"true\"\n visibleOnly?: boolean; // Only visible/displayed elements\n}\n\n/**\n * Android interactive element types\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\n/**\n * iOS interactive element types\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\n/**\n * Android layout containers - typically not interactive targets\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\n/**\n * iOS layout containers - typically not interactive targets\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/**\n * Check if element tag matches any in the list (handles partial matches)\n */\nfunction matchesTagList(tagName: string, tagList: string[]): boolean {\n // Exact match\n if (tagList.includes(tagName)) {\n return true;\n }\n\n // Partial match for tags with package prefixes\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 include list provided, element must match it\n if (includeTagNames.length > 0 && !matchesTagList(element.tagName, includeTagNames)) {\n return false;\n }\n\n // If element matches exclude list, filter it out\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 // Check required attributes\n if (requireAttributes.length > 0) {\n const hasRequiredAttr = requireAttributes.some((attr) => element.attributes?.[attr]);\n if (!hasRequiredAttr) return false;\n }\n\n // Check minimum attribute count\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\n const interactableTags = isAndroid ? ANDROID_INTERACTABLE_TAGS : IOS_INTERACTABLE_TAGS;\n\n // Check if tag is interactable\n if (matchesTagList(element.tagName, interactableTags)) {\n return true;\n }\n\n // Check clickable/focusable attributes (Android)\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 // Check accessible attribute (iOS)\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 * Elements with content should be kept even if they're containers\n */\nexport function hasMeaningfulContent(\n element: JSONElement,\n platform: 'android' | 'ios',\n): boolean {\n const attrs = element.attributes;\n\n // Check for text content\n if (attrs.text && attrs.text.trim() !== '' && attrs.text !== 'null') {\n return true;\n }\n\n if (platform === 'android') {\n // Android: content-desc is accessibility info\n if (attrs['content-desc'] && attrs['content-desc'].trim() !== '' && attrs['content-desc'] !== 'null') {\n return true;\n }\n } else {\n // iOS: label or name is accessibility info\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'], // Always exclude root hierarchy node\n requireAttributes = [],\n minAttributeCount = 0,\n fetchableOnly = false,\n clickableOnly = false,\n visibleOnly = true,\n } = filters;\n\n // Check tag name filters\n if (!matchesTagFilters(element, includeTagNames, excludeTagNames)) {\n return false;\n }\n\n // Check attribute filters\n if (!matchesAttributeFilters(element, requireAttributes, minAttributeCount)) {\n return false;\n }\n\n // Check clickable filter (Android only)\n if (clickableOnly && element.attributes?.clickable !== 'true') {\n return false;\n }\n\n // Check visible/displayed filter\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 // Check fetchable/interactable filter\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 * Generate multiple locator strategies for an element\n *\n * Based on: https://github.com/appium/appium-mcp/blob/main/src/locators/locator-generation.ts\n */\n\nimport type { JSONElement } from './source-parsing';\nimport { isAttributeUnique } from './source-parsing';\n\nexport type LocatorStrategy =\n | 'accessibility-id'\n | 'id'\n | 'class-name'\n | 'xpath'\n | 'predicate-string'\n | 'class-chain'\n | 'uiautomator'\n | 'text';\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 * Get simple locators based on single attributes\n * These are preferred because they're most stable and readable\n */\nfunction getSimpleSuggestedLocators(\n element: JSONElement,\n sourceXML: string,\n isNative: boolean,\n automationName: string,\n): [LocatorStrategy, string][] {\n const results: [LocatorStrategy, string][] = [];\n const isAndroid = automationName.toLowerCase().includes('uiautomator');\n const attrs = element.attributes;\n\n if (isAndroid) {\n // Android simple locators\n\n // 1. Resource ID (most stable)\n const resourceId = attrs['resource-id'];\n if (isValidValue(resourceId) && isAttributeUnique(sourceXML, 'resource-id', resourceId)) {\n results.push(['id', `android=new UiSelector().resourceId(\"${resourceId}\")`]);\n }\n\n // 2. Content Description (accessibility)\n const contentDesc = attrs['content-desc'];\n if (isValidValue(contentDesc) && isAttributeUnique(sourceXML, 'content-desc', contentDesc)) {\n results.push(['accessibility-id', `~${contentDesc}`]);\n }\n\n // 3. Text (visible text)\n const text = attrs.text;\n if (isValidValue(text) && text.length < 100 && isAttributeUnique(sourceXML, 'text', text)) {\n results.push(['text', `android=new UiSelector().text(\"${escapeText(text)}\")`]);\n }\n } else {\n // iOS simple locators\n\n // 1. Accessibility ID (name attribute)\n const name = attrs.name;\n if (isValidValue(name) && isAttributeUnique(sourceXML, 'name', name)) {\n results.push(['accessibility-id', `~${name}`]);\n }\n\n // 2. Label (visible text, often same as name)\n const label = attrs.label;\n if (isValidValue(label) && label !== name && isAttributeUnique(sourceXML, 'label', label)) {\n results.push(['predicate-string', `-ios predicate string:label == \"${escapeText(label)}\"`]);\n }\n\n // 3. Value\n const value = attrs.value;\n if (isValidValue(value) && isAttributeUnique(sourceXML, 'value', value)) {\n results.push(['predicate-string', `-ios predicate string:value == \"${escapeText(value)}\"`]);\n }\n }\n\n return results;\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 // Build selector with available attributes\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 // Use AND for multiple conditions\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 // Simple class chain with type\n if (!tagName.startsWith('XCUI')) return null;\n\n let selector = `**/${tagName}`;\n\n // Add label predicate if available\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 // Android XPath attributes\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 // iOS XPath attributes\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 // Build XPath\n if (conditions.length === 0) {\n // Fallback: just the tag\n return `//${tagName}`;\n }\n\n // Combine conditions with 'and'\n return `//${tagName}[${conditions.join(' and ')}]`;\n}\n\n/**\n * Get complex locators (combinations, XPath, etc.)\n */\nfunction getComplexSuggestedLocators(\n element: JSONElement,\n sourceXML: string,\n isNative: boolean,\n automationName: string,\n): [LocatorStrategy, string][] {\n const results: [LocatorStrategy, string][] = [];\n const isAndroid = automationName.toLowerCase().includes('uiautomator');\n\n if (isAndroid) {\n // Android complex locators\n\n // UiAutomator with multiple attributes\n const uiAutomator = buildUiAutomatorSelector(element);\n if (uiAutomator) {\n results.push(['uiautomator', uiAutomator]);\n }\n\n // XPath\n const xpath = buildXPath(element, sourceXML, true);\n if (xpath) {\n results.push(['xpath', xpath]);\n }\n\n // Class name (least specific)\n if (isValidValue(element.attributes.class)) {\n results.push([\n 'class-name',\n `android=new UiSelector().className(\"${element.attributes.class}\")`,\n ]);\n }\n } else {\n // iOS complex locators\n\n // Predicate string with multiple conditions\n const predicate = buildPredicateString(element);\n if (predicate) {\n results.push(['predicate-string', predicate]);\n }\n\n // Class chain\n const classChain = buildClassChain(element);\n if (classChain) {\n results.push(['class-chain', classChain]);\n }\n\n // XPath\n const xpath = buildXPath(element, sourceXML, false);\n if (xpath) {\n results.push(['xpath', xpath]);\n }\n\n // Class name (least specific)\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 * Returns array of [strategy, value] tuples ordered by priority\n *\n * Priority order:\n * Android: id > accessibility-id > text > xpath > uiautomator > class-name\n * iOS: accessibility-id > predicate-string > class-chain > xpath > class-name\n */\nexport function getSuggestedLocators(\n element: JSONElement,\n sourceXML: string,\n isNative: boolean,\n automationName: string,\n): [LocatorStrategy, string][] {\n // Get simple (single attribute) locators first\n const simpleLocators = getSimpleSuggestedLocators(element, sourceXML, isNative, automationName);\n\n // Get complex (combination) locators\n const complexLocators = getComplexSuggestedLocators(element, sourceXML, isNative, automationName);\n\n // Combine, removing duplicates (keep first occurrence)\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 isNative: boolean,\n automationName: string,\n): string | null {\n const locators = getSuggestedLocators(element, sourceXML, isNative, 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 // Use first locator for each strategy\n if (!result[strategy]) {\n result[strategy] = value;\n }\n }\n return result;\n}\n","/**\n * Main orchestrator for generating locators from page source\n *\n * Based on: https://github.com/appium/appium-mcp/blob/main/src/locators/generate-all-locators.ts\n */\n\nimport type { LocatorStrategy } from './locator-generation';\nimport { getSuggestedLocators, locatorsToObject } from './locator-generation';\nimport type { JSONElement } from './source-parsing';\nimport { parseAndroidBounds, parseIOSBounds, xmlToJSON } from './source-parsing';\nimport type { FilterOptions } from './element-filter';\nimport { hasMeaningfulContent, isLayoutContainer, shouldIncludeElement } from './element-filter';\n\nexport interface ElementWithLocators {\n tagName: string;\n locators: Record<string, string>;\n text: string;\n contentDesc: string;\n resourceId: string;\n accessibilityId: string;\n label: string;\n value: string;\n className: string;\n clickable: boolean;\n enabled: boolean;\n displayed: boolean;\n bounds: { x: number; y: number; width: number; height: number };\n isInViewport: boolean;\n}\n\n/**\n * Processing context - carries all shared state through the processing pipeline\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}\n\n/**\n * Options for generating element locators\n */\nexport interface GenerateLocatorsOptions {\n platform: 'android' | 'ios';\n viewportSize?: { width: number; height: number };\n filters?: FilterOptions;\n isNative?: boolean;\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(element: JSONElement, locators: [LocatorStrategy, string][], ctx: ProcessingContext): 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 (passes filters or has meaningful content)\n */\nfunction shouldProcess(element: JSONElement, ctx: ProcessingContext): boolean {\n if (shouldIncludeElement(element, ctx.filters, ctx.isNative, ctx.automationName)) {\n return true;\n }\n // Keep layout containers that have meaningful content\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 locators = getSuggestedLocators(element, ctx.sourceXML, ctx.isNative, ctx.automationName);\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 if (!sourceJSON) {\n console.error('[generateAllElementLocators] Failed to parse page source XML');\n return [];\n }\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 };\n\n traverseTree(sourceJSON, ctx);\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 * Only includes fields that have actual values (no nulls/undefined)\n */\nexport interface MobileElementInfo {\n selector: string;\n tagName: string;\n isInViewport: boolean;\n // Optional fields - only present when they have meaningful values\n text?: string;\n resourceId?: string;\n accessibilityId?: string;\n isEnabled?: boolean;\n alternativeSelectors?: string[];\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 * Only includes fields with actual values (mirrors browser script behavior)\n */\nfunction toMobileElementInfo(element: ElementWithLocators, includeBounds: boolean): MobileElementInfo {\n const selectedLocators = selectBestLocators(element.locators);\n\n // Start with required fields\n const info: MobileElementInfo = {\n selector: selectedLocators[0] || '',\n tagName: element.tagName,\n isInViewport: element.isInViewport,\n };\n\n // Only add optional fields if they have meaningful values\n if (element.text) {\n info.text = element.text;\n }\n\n if (element.resourceId) {\n info.resourceId = element.resourceId;\n }\n\n // Use contentDesc for accessibilityId on Android, or name on iOS\n const accessId = element.accessibilityId || element.contentDesc;\n if (accessId) {\n info.accessibilityId = accessId;\n }\n\n // Only include isEnabled if it's false (true is the common case)\n if (!element.enabled) {\n info.isEnabled = false;\n }\n\n // Only add alternative selectors if we have more than one\n if (selectedLocators.length > 1) {\n info.alternativeSelectors = selectedLocators.slice(1);\n }\n\n // Only include bounds if explicitly requested\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 getInteractableElements 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';\nimport { stripUndefinedFromArray } from '../utils/strip-undefined';\n\n/**\n * Tool definition for get_visible_elements\n */\nexport const getVisibleElementsToolDefinition: ToolDefinition = {\n name: 'get_visible_elements',\n description: 'get a list of visible (in viewport & displayed) interactable elements on the page (buttons, links, inputs). Use elementType=\"visual\" for images/SVGs. Must prefer this to take_screenshot for interactions',\n inputSchema: {\n inViewportOnly: z\n .boolean()\n .optional()\n .describe(\n 'Only return elements within the visible viewport. Default: true. Set to false to get ALL elements on the page.',\n ),\n includeContainers: z\n .boolean()\n .optional()\n .describe(\n 'Include layout containers (ViewGroup, FrameLayout, ScrollView, etc). Default: false. Set to true to see all elements including layouts.',\n ),\n includeBounds: z\n .boolean()\n .optional()\n .describe(\n 'Include element bounds/coordinates (x, y, width, height). Default: false. Set to true for coordinate-based interactions or layout debugging.',\n ),\n elementType: z\n .enum(['interactable', 'visual', 'all'])\n .optional()\n .describe(\n 'Type of elements to return: \"interactable\" (default) for buttons/links/inputs, \"visual\" for images/SVGs, \"all\" for both.',\n ),\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 elementType?: 'interactable' | 'visual' | 'all';\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 elementType = 'interactable',\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 const raw = await browser.execute(getInteractableElements, elementType);\n elements = stripUndefinedFromArray(raw);\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 = {\n total,\n showing: elements.length,\n hasMore: offset + elements.length < total,\n elements,\n };\n\n return {\n content: [{ type: 'text', text: encode(result) }],\n };\n } catch (e) {\n return {\n content: [{ type: 'text', text: `Error getting visible elements: ${e}` }],\n };\n }\n};","/**\n * Utility to strip undefined, null, and empty string values from objects\n *\n * Used to clean up element data before encoding to avoid null clutter in TOON output.\n * TOON format is columnar - it creates a unified schema from ALL objects.\n * If ANY object has a field, ALL rows get that column with null for missing values.\n * By stripping undefined/null/empty values BEFORE encoding, we ensure TOON only\n * creates columns for fields that actually have values.\n */\n\n/**\n * Strip undefined, null, and empty string values from an object\n * @param obj - The object to clean\n * @returns A new object with only defined, non-null, non-empty values\n */\nexport function stripUndefined<T extends Record<string, unknown>>(obj: T): Partial<T> {\n return Object.fromEntries(\n Object.entries(obj).filter(([_, v]) => v !== undefined && v !== null && v !== ''),\n ) as Partial<T>;\n}\n\n/**\n * Strip undefined values from an array of objects\n * @param arr - The array of objects to clean\n * @returns A new array with cleaned objects\n */\nexport function stripUndefinedFromArray<T extends Record<string, unknown>>(arr: T[]): Partial<T>[] {\n return arr.map(stripUndefined);\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 { getBrowser } from './browser.tool';\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\n/**\n * Tool definition for get_accessibility\n */\nexport const getAccessibilityToolDefinition: ToolDefinition = {\n name: 'get_accessibility',\n description: 'gets accessibility tree snapshot with semantic information about page elements (roles, names, states). Browser-only - use when get_visible_elements does not return expected 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., [\"button\", \"link\", \"textbox\"]). Default: all roles.'),\n namedOnly: z.boolean().optional()\n .describe('Only return nodes with a name/label. Default: true. Filters out anonymous containers.'),\n },\n};\n\n/**\n * Flatten a hierarchical accessibility tree into a flat list\n * Only includes properties that have actual values (no null clutter)\n * @param node - The accessibility node\n * @param result - Accumulator array\n */\nfunction flattenAccessibilityTree(node: any, result: any[] = []): any[] {\n if (!node) return result;\n\n // Add current node (excluding root WebArea unless it has meaningful content)\n if (node.role !== 'WebArea' || node.name) {\n const entry: Record<string, any> = {};\n\n // Only add properties that have actual values\n if (node.role) entry.role = node.role;\n if (node.name) entry.name = node.name;\n if (node.value !== undefined && node.value !== '') entry.value = node.value;\n if (node.description) entry.description = node.description;\n if (node.keyshortcuts) entry.keyshortcuts = node.keyshortcuts;\n if (node.roledescription) entry.roledescription = node.roledescription;\n if (node.valuetext) entry.valuetext = node.valuetext;\n if (node.disabled) entry.disabled = node.disabled;\n if (node.expanded !== undefined) entry.expanded = node.expanded;\n if (node.focused) entry.focused = node.focused;\n if (node.modal) entry.modal = node.modal;\n if (node.multiline) entry.multiline = node.multiline;\n if (node.multiselectable) entry.multiselectable = node.multiselectable;\n if (node.readonly) entry.readonly = node.readonly;\n if (node.required) entry.required = node.required;\n if (node.selected) entry.selected = node.selected;\n if (node.checked !== undefined) entry.checked = node.checked;\n if (node.pressed !== undefined) entry.pressed = node.pressed;\n if (node.level !== undefined) entry.level = node.level;\n if (node.valuemin !== undefined) entry.valuemin = node.valuemin;\n if (node.valuemax !== undefined) entry.valuemax = node.valuemax;\n if (node.autocomplete) entry.autocomplete = node.autocomplete;\n if (node.haspopup) entry.haspopup = node.haspopup;\n if (node.invalid) entry.invalid = node.invalid;\n if (node.orientation) entry.orientation = node.orientation;\n\n result.push(entry);\n }\n\n // Recursively process children\n if (node.children && Array.isArray(node.children)) {\n for (const child of node.children) {\n flattenAccessibilityTree(child, result);\n }\n }\n\n return result;\n}\n\nexport const getAccessibilityTreeTool: ToolCallback = async (args: {\n limit?: number;\n offset?: number;\n roles?: string[];\n namedOnly?: boolean;\n}): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n\n // Check if this is a mobile session - accessibility tree is browser-only\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, namedOnly = true } = args || {};\n\n // Get Puppeteer instance for native accessibility API\n const puppeteer = await browser.getPuppeteer();\n const pages = await puppeteer.pages();\n\n if (pages.length === 0) {\n return {\n content: [{ type: 'text', text: 'No active pages found' }],\n };\n }\n\n const page = pages[0];\n\n // Get accessibility snapshot with interestingOnly filter\n const snapshot = await page.accessibility.snapshot({\n interestingOnly: true, // Filter to only interesting/semantic nodes\n });\n\n if (!snapshot) {\n return {\n content: [{ type: 'text', text: 'No accessibility tree available' }],\n };\n }\n\n // Flatten the hierarchical tree into a flat list\n let nodes = flattenAccessibilityTree(snapshot);\n\n // Filter to named nodes only (removes anonymous containers, StaticText duplicates)\n if (namedOnly) {\n nodes = nodes.filter(n => n.name && n.name.trim() !== '');\n }\n\n // Filter to specific roles if provided\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 // Apply pagination\n if (offset > 0) {\n nodes = nodes.slice(offset);\n }\n if (limit > 0) {\n nodes = nodes.slice(0, limit);\n }\n\n const result = {\n total,\n showing: nodes.length,\n hasMore: offset + nodes.length < total,\n nodes,\n };\n\n return {\n content: [{ type: 'text', text: encode(result) }],\n };\n } catch (e) {\n return {\n content: [{ type: 'text', text: `Error getting accessibility tree: ${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// 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**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\": \"1.6.1\",\n \"description\": \"MCP server with WebdriverIO for browser and mobile app automation (iOS/Android via Appium)\",\n \"main\": \"./lib/server.js\",\n \"module\": \"./lib/server.js\",\n \"types\": \"./lib/server.d.ts\",\n \"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 \"start\": \"node lib/server.js\",\n \"dev\": \"tsx --watch src/server.ts\",\n \"prepare\": \"husky\"\n },\n \"dependencies\": {\n \"@modelcontextprotocol/sdk\": \"1.25\",\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.23\",\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 \"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 },\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","z","z","z","sizeKB","z","encode","z","z","z","z","z","state","z","z","z","z","z","z"]}
|