Skip to main content
Glama

drag

Automate drag-and-drop actions in Firefox using Playwright by specifying coordinates, offsets, and duration. Ideal for browser testing and debugging multi-tab workflows.

Instructions

Perform drag operation

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
durationNo
fromCoordinatesNo
offsetXNo
offsetYNo
selectorNo
stepsNo
tabIdNo
toCoordinatesNo

Implementation Reference

  • The handler function for the 'drag' tool. It supports dragging from an element selector or coordinates to a target selector, coordinates, or offset. Uses Playwright's mouse API for precise control, with optional smooth animation over duration with steps.
    async drag(args) { this.ensureBrowserRunning(); const { selector, fromCoordinates, toSelector, toCoordinates, offsetX, offsetY, duration = 0, steps = 1, tabId } = args; const page = this.getPage(tabId); // Validate inputs if (!selector && !fromCoordinates) { throw new Error('Either selector or fromCoordinates must be provided'); } if (!toSelector && !toCoordinates && offsetX === undefined && offsetY === undefined) { throw new Error('Either toSelector, toCoordinates, or offset values must be provided'); } // Get starting position let startX, startY; if (selector) { const element = await page.$(selector); if (!element) { throw new Error(`Element not found: ${selector}`); } const box = await element.boundingBox(); if (!box) { throw new Error(`Cannot get bounding box for element: ${selector}`); } startX = box.x + box.width / 2; startY = box.y + box.height / 2; } else { startX = fromCoordinates.x; startY = fromCoordinates.y; } // Get ending position let endX, endY; if (toSelector) { const element = await page.$(toSelector); if (!element) { throw new Error(`Target element not found: ${toSelector}`); } const box = await element.boundingBox(); if (!box) { throw new Error(`Cannot get bounding box for target element: ${toSelector}`); } endX = box.x + box.width / 2; endY = box.y + box.height / 2; } else if (toCoordinates) { endX = toCoordinates.x; endY = toCoordinates.y; } else { // Use offset from start position endX = startX + (offsetX || 0); endY = startY + (offsetY || 0); } // Perform the drag await page.mouse.move(startX, startY); await page.mouse.down(); if (duration > 0 && steps > 1) { // Smooth drag with intermediate steps const stepDelay = duration / steps; for (let i = 1; i <= steps; i++) { const progress = i / steps; const currentX = startX + (endX - startX) * progress; const currentY = startY + (endY - startY) * progress; await page.mouse.move(currentX, currentY); if (i < steps) { await new Promise(resolve => setTimeout(resolve, stepDelay)); } } } else { // Direct drag await page.mouse.move(endX, endY); } await page.mouse.up(); return { content: [{ type: 'text', text: `Dragged from (${Math.round(startX)}, ${Math.round(startY)}) to (${Math.round(endX)}, ${Math.round(endY)}) in tab '${tabId || this.activeTabId}'${duration > 0 ? ` over ${duration}ms` : ''}` }] }; }
  • Input schema for the 'drag' tool defining parameters like selector, from/to coordinates, offsets, duration, steps, and tabId.
    inputSchema: { type: 'object', properties: { selector: { type: 'string' }, fromCoordinates: { type: 'object', properties: { x: { type: 'number' }, y: { type: 'number' } } }, toCoordinates: { type: 'object', properties: { x: { type: 'number' }, y: { type: 'number' } } }, offsetX: { type: 'number' }, offsetY: { type: 'number' }, duration: { type: 'number', default: 0 }, steps: { type: 'number', default: 1 }, tabId: { type: 'string' } } }
  • Registration of the 'drag' tool in the tools list returned by the ListToolsRequest handler.
    { name: 'drag', description: 'Perform drag operation', inputSchema: { type: 'object', properties: { selector: { type: 'string' }, fromCoordinates: { type: 'object', properties: { x: { type: 'number' }, y: { type: 'number' } } }, toCoordinates: { type: 'object', properties: { x: { type: 'number' }, y: { type: 'number' } } }, offsetX: { type: 'number' }, offsetY: { type: 'number' }, duration: { type: 'number', default: 0 }, steps: { type: 'number', default: 1 }, tabId: { type: 'string' } } } },
  • Dispatch registration in the CallToolRequest switch statement that routes calls to the drag handler.
    case 'drag': return await this.drag(args);

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/JediLuke/firefox-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server