@wdio/mcp 1.4.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/LICENSE +21 -0
- package/README.md +434 -0
- package/lib/server.d.ts +1 -0
- package/lib/server.js +2130 -0
- package/lib/server.js.map +1 -0
- package/package.json +55 -0
|
@@ -0,0 +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/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"],"sourcesContent":["#!/usr/bin/env node\n\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';\nimport {\n closeSessionTool,\n closeSessionToolArguments,\n startBrowserTool,\n startBrowserToolArguments\n} from './tools/browser.tool';\nimport { navigateTool, navigateToolArguments } from './tools/navigate.tool';\nimport { clickTool, clickToolArguments, clickToolViaText } from './tools/click.tool';\nimport { setValueTool, setValueToolArguments } from './tools/set-value.tool';\nimport { findElementTool, findElementToolArguments } from './tools/find-element.tool';\nimport { getElementTextTool, getElementTextToolArguments } from './tools/get-element-text.tool';\nimport { isDisplayedTool, isDisplayedToolArguments } from './tools/is-displayed.tool';\nimport { scrollDownTool, scrollDownToolArguments } from './tools/scroll-down.tool';\nimport { scrollUpTool, scrollUpToolArguments } from './tools/scroll-up.tool';\nimport { getVisibleElementsTool, getVisibleElementsToolArguments } from './tools/get-visible-elements.tool';\nimport { takeScreenshotTool, takeScreenshotToolArguments } from './tools/take-screenshot.tool';\nimport {\n deleteCookiesTool,\n deleteCookiesToolArguments,\n getCookiesTool,\n getCookiesToolArguments,\n setCookieTool,\n setCookieToolArguments,\n} from './tools/cookies.tool';\nimport { getAccessibilityTreeTool } from './tools/get-accessibility-tree.tool';\nimport { startAppTool, startAppToolArguments } from './tools/app-session.tool';\nimport {\n dragAndDropTool,\n dragAndDropToolArguments,\n longPressTool,\n longPressToolArguments,\n swipeTool,\n swipeToolArguments,\n tapElementTool,\n tapElementToolArguments,\n} from './tools/gestures.tool';\nimport {\n activateAppTool,\n activateAppToolArguments,\n getAppStateTool,\n getAppStateToolArguments,\n terminateAppTool,\n terminateAppToolArguments,\n} from './tools/app-actions.tool';\nimport {\n getContextsTool,\n getCurrentContextTool,\n switchContextTool,\n switchContextToolArguments\n} from './tools/context.tool';\nimport {\n getDeviceInfoTool,\n getGeolocationTool,\n getOrientationTool,\n hideKeyboardTool,\n isDeviceLockedTool,\n isKeyboardShownTool,\n lockDeviceTool,\n openNotificationsTool,\n pressKeyCodeTool,\n pressKeyCodeToolArguments,\n rotateDeviceTool,\n rotateDeviceToolArguments,\n sendKeysTool,\n sendKeysToolArguments,\n setGeolocationTool,\n setGeolocationToolArguments,\n shakeDeviceTool,\n unlockDeviceTool,\n} from './tools/device.tool';\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 name: 'MCP WebdriverIO',\n version: '1.4.0',\n}, {\n capabilities: {\n resources: {},\n tools: {},\n },\n});\n\n// Browser and App Session Management\nserver.tool('start_browser', 'starts a browser session and sets it to the current state', startBrowserToolArguments, startBrowserTool);\nserver.tool('start_app_session', 'starts a mobile app session (iOS/Android) via Appium', startAppToolArguments, startAppTool);\nserver.tool('close_session', 'closes or detaches from the current browser or app session', closeSessionToolArguments, closeSessionTool);\nserver.tool('navigate', 'navigates to a URL', navigateToolArguments, navigateTool);\n\nserver.tool('get_visible_elements', 'get a list of visible (in viewport & displayed) elements on the page, must prefer this to take_screenshot for interactions', getVisibleElementsToolArguments, getVisibleElementsTool);\nserver.tool('get_accessibility', 'gets accessibility tree snapshot with semantic information about page elements (roles, names, states)', {}, getAccessibilityTreeTool);\n\nserver.tool('scroll_down', 'scrolls the page down by specified pixels', scrollDownToolArguments, scrollDownTool);\nserver.tool('scroll_up', 'scrolls the page up by specified pixels', scrollUpToolArguments, scrollUpTool);\n\nserver.tool('find_element', 'finds an element', findElementToolArguments, findElementTool);\nserver.tool('click_element', 'clicks an element', clickToolArguments, clickTool);\nserver.tool('click_via_text', 'clicks an element', clickToolArguments, clickToolViaText);\nserver.tool('set_value', 'set value to an element, aka typing', setValueToolArguments, setValueTool);\n\nserver.tool('get_element_text', 'gets the text content of an element', getElementTextToolArguments, getElementTextTool);\nserver.tool('is_displayed', 'checks if an element is displayed', isDisplayedToolArguments, isDisplayedTool);\n\nserver.tool('take_screenshot', 'captures a screenshot of the current page', takeScreenshotToolArguments, takeScreenshotTool);\n\nserver.tool('get_cookies', 'gets all cookies or a specific cookie by name', getCookiesToolArguments, getCookiesTool);\nserver.tool('set_cookie', 'sets a cookie with specified name, value, and optional attributes', setCookieToolArguments, setCookieTool);\nserver.tool('delete_cookies', 'deletes all cookies or a specific cookie by name', deleteCookiesToolArguments, deleteCookiesTool);\n\n// Mobile Gesture Tools\nserver.tool('tap_element', 'taps an element by selector or coordinates (mobile)', tapElementToolArguments, tapElementTool);\nserver.tool('swipe', 'performs a swipe gesture in specified direction (mobile)', swipeToolArguments, swipeTool);\nserver.tool('long_press', 'performs a long press on element or coordinates (mobile)', longPressToolArguments, longPressTool);\nserver.tool('drag_and_drop', 'drags from one location to another (mobile)', dragAndDropToolArguments, dragAndDropTool);\n\n// App Lifecycle Management\nserver.tool('get_app_state', 'gets the state of an app (not installed, not running, background, foreground)', getAppStateToolArguments, getAppStateTool);\nserver.tool('activate_app', 'activates/brings an app to foreground', activateAppToolArguments, activateAppTool);\nserver.tool('terminate_app', 'terminates a running app', terminateAppToolArguments, terminateAppTool);\n\n// Context Switching (Native/WebView)\nserver.tool('get_contexts', 'lists available contexts (NATIVE_APP, WEBVIEW)', {}, getContextsTool);\nserver.tool('get_current_context', 'shows the currently active context', {}, getCurrentContextTool);\nserver.tool('switch_context', 'switches between native and webview contexts', switchContextToolArguments, switchContextTool);\n\n// Device Interaction\nserver.tool('get_device_info', 'gets device information (platform, version, screen size)', {}, getDeviceInfoTool);\nserver.tool('rotate_device', 'rotates device to portrait or landscape orientation', rotateDeviceToolArguments, rotateDeviceTool);\nserver.tool('get_orientation', 'gets current device orientation', {}, getOrientationTool);\nserver.tool('lock_device', 'locks the device screen', {}, lockDeviceTool);\nserver.tool('unlock_device', 'unlocks the device screen', {}, unlockDeviceTool);\nserver.tool('is_device_locked', 'checks if device is locked', {}, isDeviceLockedTool);\nserver.tool('shake_device', 'shakes the device (iOS only)', {}, shakeDeviceTool);\nserver.tool('send_keys', 'sends keys to the app (Android only)', sendKeysToolArguments, sendKeysTool);\nserver.tool('press_key_code', 'presses an Android key code (Android only)', pressKeyCodeToolArguments, pressKeyCodeTool);\nserver.tool('hide_keyboard', 'hides the on-screen keyboard', {}, hideKeyboardTool);\nserver.tool('is_keyboard_shown', 'checks if keyboard is visible', {}, isKeyboardShownTool);\nserver.tool('open_notifications', 'opens the notifications panel (Android only)', {}, openNotificationsTool);\nserver.tool('get_geolocation', 'gets current device geolocation', {}, getGeolocationTool);\nserver.tool('set_geolocation', 'sets device geolocation (latitude, longitude, altitude)', setGeolocationToolArguments, 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 { z } from 'zod';\n\nexport const startBrowserToolArguments = {\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\nexport const closeSessionToolArguments = {\n detach: z.boolean().optional().describe('If true, disconnect from session without terminating it (preserves app state). Default: false'),\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';\n\nexport const navigateToolArguments: { url: z.ZodString } = {\n url: z.string().nonempty('URL must be provided'),\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';\n\nconst defaultTimeout: number = 3000;\n\nexport const clickToolArguments = {\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\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';\n\nconst defaultTimeout: number = 3000;\n\nexport const setValueToolArguments = {\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\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';\n\nconst defaultTimeout: number = 3000;\n\nexport const findElementToolArguments = {\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\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';\n\nconst defaultTimeout: number = 3000;\n\nexport const getElementTextToolArguments = {\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\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';\n\nconst defaultTimeout: number = 3000;\n\nexport const isDisplayedToolArguments = {\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\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';\n\nexport const scrollDownToolArguments = {\n pixels: z.number().optional().default(500),\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';\n\nexport const scrollUpToolArguments = {\n pixels: z.number().optional().default(500),\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};","const elementsScript = () => (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 /**\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) {\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 = 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 interactable and visible elements on the page\n * @returns {ElementInfo[]} - Array of element information objects\n */\n function getInteractableElements() {\n\n // Get all potentially interactable elements\n const allElements = [];\n interactableSelectors.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) && !(element).disabled)\n .map(element => {\n // Get element information\n const rect = element.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 return {\n tagName: element.tagName.toLowerCase(),\n type: element.getAttribute('type') || undefined,\n id: element.id || undefined,\n className: element.className || undefined,\n textContent: element.textContent?.trim() || undefined,\n value: (element).value || undefined,\n placeholder: (element).placeholder || undefined,\n href: element.getAttribute('href') || undefined,\n ariaLabel: element.getAttribute('aria-label') || undefined,\n role: element.getAttribute('role') || undefined,\n cssSelector: getCssSelector(element),\n isInViewport: isInViewport,\n };\n });\n\n return [\n ...elementInfos,\n ];\n }\n\n return getInteractableElements();\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 } from '../locators';\nimport { generateAllElementLocators, getDefaultFilters } from '../locators';\n\n/**\n * Element info returned by getMobileVisibleElements\n */\nexport interface MobileElementInfo {\n selector: string;\n alternativeSelectors?: string[];\n locators: Record<string, string>;\n tagName?: string;\n text?: string;\n resourceId?: string;\n contentDesc?: string;\n accessibilityId?: string;\n label?: string;\n value?: string;\n className?: string;\n isInViewport: boolean;\n isEnabled: boolean;\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 filterOptions?: FilterOptions;\n}\n\n/**\n * Convert ElementWithLocators to MobileElementInfo\n */\nfunction toMobileElementInfo(element: ElementWithLocators): MobileElementInfo {\n const locatorValues = Object.values(element.locators);\n\n return {\n selector: locatorValues[0] || '',\n alternativeSelectors: locatorValues.length > 1 ? locatorValues.slice(1, 3) : undefined,\n locators: element.locators,\n isInViewport: element.isInViewport,\n isEnabled: element.enabled,\n bounds: element.bounds,\n tagName: element.tagName || undefined,\n text: element.text || undefined,\n resourceId: element.resourceId || undefined,\n contentDesc: element.contentDesc || undefined,\n accessibilityId: element.accessibilityId || undefined,\n label: element.label || undefined,\n value: element.value || undefined,\n className: element.className || undefined,\n };\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, 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(toMobileElementInfo);\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 { encode } from '@toon-format/toon';\nimport { z } from 'zod';\n\n/**\n * Arguments for get_visible_elements tool\n */\nexport const getVisibleElementsToolArguments = {\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};\n\n/**\n * Get visible interactive 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}) => {\n try {\n const browser = getBrowser();\n const { inViewportOnly = true, includeContainers = false } = args || {};\n\n // Handle mobile apps differently from web browsers\n if (browser.isAndroid || browser.isIOS) {\n const platform = browser.isAndroid ? 'android' : 'ios';\n let elements = await getMobileVisibleElements(browser, platform, {\n includeContainers,\n });\n\n // Filter by viewport if requested (default: true)\n if (inViewportOnly) {\n elements = elements.filter((el) => el.isInViewport);\n }\n\n return {\n content: [{ type: 'text', text: encode(elements) }],\n };\n }\n\n // Web browser - use existing implementation\n // Note: Web implementation already filters to visible/interactable elements\n const elements = await browser.execute(getInteractableElements);\n\n // Filter by viewport for web if needed\n if (inViewportOnly) {\n const filteredElements = elements.filter((el: any) => el.isInViewport !== false);\n return {\n content: [{ type: 'text', text: encode(filteredElements) }],\n };\n }\n\n return {\n content: [{ type: 'text', text: encode(elements) }],\n };\n } catch (e) {\n return {\n content: [{ type: 'text', text: `Error getting visible elements: ${e}` }],\n };\n }\n};\n","import { getBrowser } from './browser.tool';\nimport { z } from 'zod';\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp';\n\nexport const takeScreenshotToolArguments = {\n outputPath: z.string().optional().describe('Optional path where to save the screenshot. If not provided, returns base64 data.'),\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';\n\n// Get all cookies or a specific cookie by name\nexport const getCookiesToolArguments = {\n name: z.string().optional().describe('Optional cookie name to retrieve a specific cookie. If not provided, returns all cookies'),\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 setCookieToolArguments = {\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\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 deleteCookiesToolArguments = {\n name: z.string().optional().describe('Optional cookie name to delete a specific cookie. If not provided, deletes all cookies'),\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 { encode } from '@toon-format/toon';\n\n/**\n * Flatten a hierarchical accessibility tree into a flat list\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 result.push({\n role: node.role,\n name: node.name,\n value: node.value,\n description: node.description,\n keyshortcuts: node.keyshortcuts,\n roledescription: node.roledescription,\n valuetext: node.valuetext,\n disabled: node.disabled,\n expanded: node.expanded,\n focused: node.focused,\n modal: node.modal,\n multiline: node.multiline,\n multiselectable: node.multiselectable,\n readonly: node.readonly,\n required: node.required,\n selected: node.selected,\n checked: node.checked,\n pressed: node.pressed,\n level: node.level,\n valuemin: node.valuemin,\n valuemax: node.valuemax,\n autocomplete: node.autocomplete,\n haspopup: node.haspopup,\n invalid: node.invalid,\n orientation: node.orientation,\n });\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 (): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\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 const flattenedNodes = flattenAccessibilityTree(snapshot);\n\n return {\n content: [{\n type: 'text',\n text: encode(flattenedNodes),\n }],\n };\n } catch (e) {\n return {\n content: [{ type: 'text', text: `Error getting accessibility tree: ${e}` }],\n };\n }\n};\n","import { remote } from 'webdriverio';\nimport type { ToolCallback } from '@modelcontextprotocol/sdk/server/mcp';\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types';\nimport { z } from 'zod';\nimport { buildAndroidCapabilities, buildIOSCapabilities, getAppiumServerConfig, } from '../config/appium.config';\nimport { getBrowser } from './browser.tool';\n\nexport const startAppToolArguments = {\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// 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 { z } from 'zod';\nimport { getBrowser } from './browser.tool';\n\n// Tap Element Tool\nexport const tapElementToolArguments = {\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\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 swipeToolArguments = {\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\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 longPressToolArguments = {\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\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 dragAndDropToolArguments = {\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\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 { z } from 'zod';\nimport { getBrowser } from './browser.tool';\n\n// Get App State Tool\nexport const getAppStateToolArguments = {\n bundleId: z.string().describe('App bundle ID (e.g., com.example.app)'),\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 activateAppToolArguments = {\n bundleId: z.string().describe('App bundle ID to activate (e.g., com.example.app)'),\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 terminateAppToolArguments = {\n bundleId: z.string().describe('App bundle ID to terminate (e.g., com.example.app)'),\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 { z } from 'zod';\nimport { getBrowser } from './browser.tool';\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\n// Switch Context Tool\nexport const switchContextToolArguments = {\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\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 { z } from 'zod';\nimport { getBrowser } from './browser.tool';\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 rotateDeviceToolArguments = {\n orientation: z.enum(['PORTRAIT', 'LANDSCAPE']).describe('Device orientation'),\n};\n\nexport const rotateDeviceTool: ToolCallback = async (args: {\n orientation: 'PORTRAIT' | 'LANDSCAPE';\n}): Promise<CallToolResult> => {\n try {\n const browser = getBrowser();\n const { orientation } = args;\n\n await browser.setOrientation(orientation);\n\n return {\n content: [{ type: 'text', text: `Device rotated to: ${orientation}` }],\n };\n } catch (e) {\n return {\n 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 sendKeysToolArguments = {\n keys: z.array(z.string()).describe('Array of keys to send (e.g., [\"h\", \"e\", \"l\", \"l\", \"o\"])'),\n};\n\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 pressKeyCodeToolArguments = {\n keyCode: z.number().describe('Android key code (e.g., 4 for BACK, 3 for HOME)'),\n};\n\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 setGeolocationToolArguments = {\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\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"],"mappings":"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","names":["z","z","z","defaultTimeout","z","defaultTimeout","z","defaultTimeout","z","defaultTimeout","z","z","z","elements","z","z","encode","remote","z","z","remote","state","z","z","z","z","state","z","z","z","z"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wdio/mcp",
|
|
3
|
+
"author": "Vince Graics",
|
|
4
|
+
"repository": {
|
|
5
|
+
"type": "git",
|
|
6
|
+
"url": "git://github.com/webdriverio/mcp.git"
|
|
7
|
+
},
|
|
8
|
+
"version": "1.4.0",
|
|
9
|
+
"description": "MCP server with WebdriverIO for browser and mobile app automation (iOS/Android via Appium)",
|
|
10
|
+
"main": "./lib/server.js",
|
|
11
|
+
"module": "./lib/server.js",
|
|
12
|
+
"types": "./lib/server.d.ts",
|
|
13
|
+
"bin": {
|
|
14
|
+
"wdio-mcp": "lib/server.js"
|
|
15
|
+
},
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"publishConfig": {
|
|
18
|
+
"access": "public"
|
|
19
|
+
},
|
|
20
|
+
"type": "module",
|
|
21
|
+
"files": [
|
|
22
|
+
"lib",
|
|
23
|
+
"README.md"
|
|
24
|
+
],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"prebundle": "rimraf lib --glob ./*.tgz",
|
|
27
|
+
"bundle": "tsup && shx chmod +x lib/server.js",
|
|
28
|
+
"postbundle": "npm pack",
|
|
29
|
+
"lint": "eslint src/ --fix && tsc --noEmit",
|
|
30
|
+
"start": "node lib/server.js",
|
|
31
|
+
"dev": "tsx src/server.ts",
|
|
32
|
+
"prepare": "husky"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@modelcontextprotocol/sdk": "1.25",
|
|
36
|
+
"@toon-format/toon": "^1.0.0",
|
|
37
|
+
"@wdio/protocols": "^9.16.2",
|
|
38
|
+
"@xmldom/xmldom": "^0.8.11",
|
|
39
|
+
"webdriverio": "9.22",
|
|
40
|
+
"zod": "^4.3.5"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/node": "^20.11.0",
|
|
44
|
+
"@wdio/eslint": "^0.1.3",
|
|
45
|
+
"@wdio/types": "^9.20.0",
|
|
46
|
+
"eslint": "^9.39.2",
|
|
47
|
+
"husky": "^9.1.7",
|
|
48
|
+
"rimraf": "^6.1.2",
|
|
49
|
+
"shx": "^0.4.0",
|
|
50
|
+
"tsup": "^8.5.1",
|
|
51
|
+
"tsx": "^4.21.0",
|
|
52
|
+
"typescript": "5.9"
|
|
53
|
+
},
|
|
54
|
+
"packageManager": "pnpm@10.12.4"
|
|
55
|
+
}
|