Skip to main content
Glama

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

TableJSON Schema
NameRequiredDescriptionDefault
indexNoIndex de l'élément depuis get_ui_tree
xNoCoordonnée X
yNoCoordonnée Y
textNoTexte/label de l'élément
durationNoDurée de l'appui en secondes (défaut: 1, min: 0.1, max: 10)

Implementation Reference

  • 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 };
          }
        }
      );
    }
  • 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)"),
    },
  • 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 });
    }
  • 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);
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It only states 'long press' without disclosing behavioral traits like duration effect, haptic feedback, or element compatibility, leaving gaps for the agent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, efficiently conveying purpose and use cases with no wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The use cases provide useful context, but without an output schema or annotations, the description lacks details on return values or side effects, making it only moderately complete for a simple action tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3. The description adds minimal extra meaning beyond the schema, which already documents parameters well.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action (long press) and resource (screen element), and provides specific use cases (context menus, drag & drop, secondary actions), distinguishing it from siblings like tap and swipe.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives context for when to use (context menus, drag & drop, secondary actions) but lacks explicit guidance on when not to use or alternatives, though it's still clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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/nthImpulse/phantom-mcp'

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