drag_and_drop
Drag a source element to a target element or to specified x,y offsets on mobile devices. Requires source selector; optionally specify target selector or coordinates.
Instructions
Drags an element to another element or to relative x/y offsets. x and y are offsets from the source element, not absolute screen coordinates (unlike tap_element). Provide targetSelector OR both x and y. Mobile-only.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| sourceSelector | Yes | Source element selector to drag | |
| targetSelector | No | Target element selector to drop onto | |
| x | No | Target X offset (if no targetSelector) | |
| y | No | Target Y offset (if no targetSelector) | |
| duration | No | Drag duration in milliseconds |
Implementation Reference
- src/tools/gestures.tool.ts:143-179 (handler)The main handler function (dragAndDropAction) that executes the drag and drop logic. It uses WebDriverIO's browser.$ to locate elements, and calls element.dragAndDrop() with either a target element or x/y offsets.
export const dragAndDropAction = async (args: { sourceSelector: string; targetSelector?: string; x?: number; y?: number; duration?: number; }): Promise<CallToolResult> => { try { const browser = getBrowser(); const { sourceSelector, targetSelector, x, y, duration } = args; const sourceElement = await browser.$(sourceSelector); if (targetSelector) { const targetElement = await browser.$(targetSelector); await sourceElement.dragAndDrop(targetElement, { duration }); return { content: [{ type: 'text', text: `Dragged ${sourceSelector} to ${targetSelector}` }], }; } else if (x !== undefined && y !== undefined) { await sourceElement.dragAndDrop({ x, y }, { duration }); return { content: [{ type: 'text', text: `Dragged ${sourceSelector} by (${x}, ${y})` }], }; } return { isError: true, content: [{ type: 'text', text: 'Error: Must provide either targetSelector or x,y coordinates' }], }; } catch (e) { return { isError: true, content: [{ type: 'text', text: `Error dragging: ${e}` }], }; } }; - src/tools/gestures.tool.ts:181-187 (handler)The ToolCallback wrapper (dragAndDropTool) that delegates to dragAndDropAction.
export const dragAndDropTool: ToolCallback = async (args: { sourceSelector: string; targetSelector?: string; x?: number; y?: number; duration?: number; }): Promise<CallToolResult> => dragAndDropAction(args); - src/tools/gestures.tool.ts:130-141 (schema)Input schema and tool definition for drag_and_drop, defining required sourceSelector, optional targetSelector/x/y/duration with Zod validation.
export const dragAndDropToolDefinition: ToolDefinition = { name: 'drag_and_drop', description: 'Drags an element to another element or to relative x/y offsets. x and y are offsets from the source element, not absolute screen coordinates (unlike tap_element). Provide targetSelector OR both x and y. Mobile-only.', annotations: { title: 'Drag and Drop', destructiveHint: false }, inputSchema: { sourceSelector: z.string().describe('Source element selector to drag'), targetSelector: z.string().optional().describe('Target element selector to drop onto'), x: z.number().optional().describe('Target X offset (if no targetSelector)'), y: z.number().optional().describe('Target Y offset (if no targetSelector)'), duration: z.number().min(100).max(5000).optional().describe('Drag duration in milliseconds'), }, }; - src/server.ts:142-142 (registration)Registration of the drag_and_drop tool on the MCP server, wrapping it with recording functionality.
registerTool(dragAndDropToolDefinition, withRecording('drag_and_drop', dragAndDropTool)); - Code generator for drag_and_drop that outputs WebDriverIO-style dragAndDrop calls when replaying recorded sessions.
case 'drag_and_drop': if (p.targetSelector !== undefined) { return `await browser.$('${escapeStr(p.sourceSelector)}').dragAndDrop(browser.$('${escapeStr(p.targetSelector)}'));`; } return `await browser.$('${escapeStr(p.sourceSelector)}').dragAndDrop({ x: ${p.x}, y: ${p.y} });`;