long_press
Performs a long press on a UI element to activate context menus, drag and drop, or secondary actions. Identify the element by index, coordinates, or text, with adjustable duration.
Instructions
Appui long sur un élément de l'écran. Utile pour les menus contextuels, drag & drop, ou actions secondaires.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| index | No | Index de l'élément depuis get_ui_tree | |
| x | No | Coordonnée X | |
| y | No | Coordonnée Y | |
| text | No | Texte/label de l'élément | |
| duration | No | Durée de l'appui en secondes (défaut: 1, min: 0.1, max: 10) |
Implementation Reference
- src/tools/long-press.ts:9-69 (registration)Registration of the 'long_press' tool on the MCP server via server.tool(), including the handler that resolves coordinates (from index, x+y, or text) and dispatches to iosLongPress or androidLongPress.
export function registerLongPress(server: McpServer): void { server.tool( "long_press", "Appui long sur un élément de l'écran. Utile pour les menus contextuels, drag & drop, ou actions secondaires.", { index: z.number().optional().describe("Index de l'élément depuis get_ui_tree"), x: z.number().optional().describe("Coordonnée X"), y: z.number().optional().describe("Coordonnée Y"), text: z.string().optional().describe("Texte/label de l'élément"), duration: z.number().min(0.1).max(10).optional().default(1).describe("Durée de l'appui en secondes (défaut: 1, min: 0.1, max: 10)"), }, async ({ index, x, y, text, duration }) => { const result = await resolveDevice(); if ("error" in result) return { content: [{ type: "text", text: result.error }], isError: true }; const dev = result.device; if (dev.platform === "ios") { const wda = await ensureWdaRunning(dev); if (!wda.ready) return { content: [{ type: "text", text: wda.message ?? "WDA indisponible." }], isError: true }; } try { let tapX: number, tapY: number; let label = ""; if (index !== undefined) { const cached = getElementByIndex(index, dev.id); if (!cached) return { content: [{ type: "text", text: `Index [${index}] non trouvé.` }], isError: true }; tapX = cached.x + cached.width / 2; tapY = cached.y + cached.height / 2; label = cached.label || cached.name || ""; } else if (x !== undefined && y !== undefined) { tapX = x; tapY = y; } else if (text) { const el = findElementByText(text, dev.id); if (!el) return { content: [{ type: "text", text: `Élément "${text}" non trouvé.` }], isError: true }; tapX = el.x + el.width / 2; tapY = el.y + el.height / 2; label = text; } else { return { content: [{ type: "text", text: "Fournis index, x+y, ou text." }], isError: true }; } if (dev.platform === "ios") { await iosLongPress(tapX, tapY, duration); } else { await androidLongPress(tapX, tapY, duration * 1000); } const successMsg = `Long press ${duration}s sur ${label ? `"${label}"` : `(${Math.round(tapX)}, ${Math.round(tapY)})`}`; logAction("long_press", successMsg, false, dev.platform, dev.id, dev.name); return { content: [{ type: "text", text: successMsg }] }; } catch (err) { const msg = err instanceof Error ? err.message : String(err); logAction("long_press", `Erreur: ${msg}`, true, dev.platform, dev.id, dev.name); return { content: [{ type: "text", text: `Erreur long_press: ${msg}` }], isError: true }; } } ); } - src/tools/long-press.ts:13-19 (schema)Zod schema for long_press inputs: index, x, y, text, and duration (0.1-10s, default 1s).
{ index: z.number().optional().describe("Index de l'élément depuis get_ui_tree"), x: z.number().optional().describe("Coordonnée X"), y: z.number().optional().describe("Coordonnée Y"), text: z.string().optional().describe("Texte/label de l'élément"), duration: z.number().min(0.1).max(10).optional().default(1).describe("Durée de l'appui en secondes (défaut: 1, min: 0.1, max: 10)"), }, - src/platforms/ios/wda.ts:380-382 (handler)iOS long press implementation: calls WDA /wda/touchAndHold with x, y, and duration in seconds.
export async function iosLongPress(x: number, y: number, durationSec: number = 1): Promise<void> { await wdaPost("/wda/touchAndHold", { x, y, duration: durationSec }); } - src/platforms/android/adb.ts:366-373 (handler)Android long press implementation: uses ADB 'input swipe' from (x,y) to (x,y) with duration in milliseconds to simulate a long press.
export async function androidLongPress(x: number, y: number, durationMs: number = 1000): Promise<void> { // Long press = swipe from point to same point with long duration await adb(["shell", "input", "swipe", String(Math.round(x)), String(Math.round(y)), String(Math.round(x)), String(Math.round(y)), String(durationMs), ]); } - src/index.ts:17-17 (registration)Import of registerLongPress from the long-press tool module.
import { registerLongPress } from "./tools/long-press.js"; - src/index.ts:49-49 (registration)Calls registerLongPress(server) to register the tool on the MCP server.
registerLongPress(server);