@nbakka/mcp-appium 4.0.1 → 4.0.2

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.
Files changed (2) hide show
  1. package/lib/server.js +33 -17
  2. package/package.json +1 -1
package/lib/server.js CHANGED
@@ -177,7 +177,7 @@ tool(
177
177
  return `Screen elements (${elements.length} found): ${JSON.stringify(elements, null, 2)}`;
178
178
  });
179
179
 
180
- toool("mobile_press_button", "Press a button on device", {
180
+ tool("mobile_press_button", "Press a button on device", {
181
181
  button: zod_1.z.string().describe("The button to press. Supported buttons: BACK (android only), HOME, VOLUME_UP, VOLUME_DOWN, ENTER, DPAD_CENTER (android tv only), DPAD_UP (android tv only), DPAD_DOWN (android tv only), DPAD_LEFT (android tv only), DPAD_RIGHT (android tv only)"),
182
182
  }, async ({ button }) => {
183
183
  requireRobot();
@@ -230,33 +230,49 @@ tool(
230
230
 
231
231
  tool(
232
232
  "mobile_tap_by_text",
233
- "Tap an element on screen by its displayed text or accessibility label using ADB tap",
233
+ "Tap an element on screen by any attribute: text, accessibilityId (content-desc), or id (resource-id). Searches all attributes automatically.",
234
234
  {
235
- text: zod_1.z.string().describe("The exact text or label of the element to tap"),
235
+ value: zod_1.z.string().describe("The value to search for - can be text, accessibilityId, or id"),
236
236
  },
237
- async ({ text }) => {
238
- if (!text) throw new Error("Input text is required");
237
+ async ({ value }) => {
238
+ if (!value) throw new Error("Input value is required");
239
239
 
240
240
  requireRobot(); // ensure robot instance available
241
- const elements = await robot.getElementsOnScreen();
241
+ const elements = await robot.getSimplifiedElements();
242
242
 
243
- // Find element by exact match on text or label
243
+ // Find element by matching any attribute (text, accessibilityId, or id)
244
244
  const element = elements.find(
245
- el => el.text === text || el.label === text
245
+ el => el.text === value || el.accessibilityId === value || el.id === value
246
246
  );
247
247
 
248
- if (!element) throw new Error(`Element with text or label "${text}" not found`);
249
-
248
+ if (!element) throw new Error(`Element with value "${value}" not found in text, accessibilityId, or id`);
249
+
250
+ // Parse bounds to get coordinates
251
+ // Bounds format: "[x1,y1][x2,y2]"
252
+ if (!element.bounds) throw new Error("Element has no bounds information");
253
+
254
+ const boundsMatch = element.bounds.match(/\[(\d+),(\d+)\]\[(\d+),(\d+)\]/);
255
+ if (!boundsMatch) throw new Error("Invalid bounds format");
256
+
257
+ const x1 = parseInt(boundsMatch[1]);
258
+ const y1 = parseInt(boundsMatch[2]);
259
+ const x2 = parseInt(boundsMatch[3]);
260
+ const y2 = parseInt(boundsMatch[4]);
261
+
250
262
  // Calculate center coordinates
251
- const rect = element.rect;
252
- const x = Math.floor(rect.x + rect.width / 2);
253
- const y = Math.floor(rect.y + rect.height / 2);
263
+ const x = Math.floor((x1 + x2) / 2);
264
+ const y = Math.floor((y1 + y2) / 2);
265
+
266
+ // Execute tap using robot (works for both Android and iOS)
267
+ await robot.tap(x, y);
254
268
 
255
- // Execute adb tap
256
- const { execSync } = require("child_process");
257
- execSync(`adb shell input tap ${x} ${y}`);
269
+ // Determine which attribute matched
270
+ let matchedBy = '';
271
+ if (element.text === value) matchedBy = 'text';
272
+ else if (element.accessibilityId === value) matchedBy = 'accessibilityId';
273
+ else if (element.id === value) matchedBy = 'id';
258
274
 
259
- return `Tapped element with text/label "${text}" at (${x},${y})`;
275
+ return `Tapped element by ${matchedBy} "${value}" at (${x},${y})`;
260
276
  }
261
277
  );
262
278
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nbakka/mcp-appium",
3
- "version": "4.0.1",
3
+ "version": "4.0.2",
4
4
  "description": "Appium MCP",
5
5
  "engines": {
6
6
  "node": ">=18"