@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.
- package/lib/server.js +33 -17
- 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
|
-
|
|
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
|
|
233
|
+
"Tap an element on screen by any attribute: text, accessibilityId (content-desc), or id (resource-id). Searches all attributes automatically.",
|
|
234
234
|
{
|
|
235
|
-
|
|
235
|
+
value: zod_1.z.string().describe("The value to search for - can be text, accessibilityId, or id"),
|
|
236
236
|
},
|
|
237
|
-
async ({
|
|
238
|
-
if (!
|
|
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.
|
|
241
|
+
const elements = await robot.getSimplifiedElements();
|
|
242
242
|
|
|
243
|
-
// Find element by
|
|
243
|
+
// Find element by matching any attribute (text, accessibilityId, or id)
|
|
244
244
|
const element = elements.find(
|
|
245
|
-
el => el.text ===
|
|
245
|
+
el => el.text === value || el.accessibilityId === value || el.id === value
|
|
246
246
|
);
|
|
247
247
|
|
|
248
|
-
if (!element) throw new Error(`Element with
|
|
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
|
|
252
|
-
const
|
|
253
|
-
|
|
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
|
-
//
|
|
256
|
-
|
|
257
|
-
|
|
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
|
|
275
|
+
return `Tapped element by ${matchedBy} "${value}" at (${x},${y})`;
|
|
260
276
|
}
|
|
261
277
|
);
|
|
262
278
|
|