@mobilenext/mobile-mcp 0.0.35 → 0.0.37
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 +31 -28
- package/package.json +6 -5
package/lib/server.js
CHANGED
|
@@ -27,10 +27,6 @@ const createMcpServer = () => {
|
|
|
27
27
|
const server = new mcp_js_1.McpServer({
|
|
28
28
|
name: "mobile-mcp",
|
|
29
29
|
version: (0, exports.getAgentVersion)(),
|
|
30
|
-
capabilities: {
|
|
31
|
-
resources: {},
|
|
32
|
-
tools: {},
|
|
33
|
-
},
|
|
34
30
|
});
|
|
35
31
|
// an empty object to satisfy windsurf
|
|
36
32
|
const noParams = zod_1.z.object({});
|
|
@@ -44,8 +40,12 @@ const createMcpServer = () => {
|
|
|
44
40
|
return "unknown";
|
|
45
41
|
}
|
|
46
42
|
};
|
|
47
|
-
const tool = (name, description, paramsSchema, cb) => {
|
|
48
|
-
|
|
43
|
+
const tool = (name, title, description, paramsSchema, cb) => {
|
|
44
|
+
server.registerTool(name, {
|
|
45
|
+
title,
|
|
46
|
+
description,
|
|
47
|
+
inputSchema: paramsSchema,
|
|
48
|
+
}, (async (args, _extra) => {
|
|
49
49
|
try {
|
|
50
50
|
(0, logger_1.trace)(`Invoking ${name} with args: ${JSON.stringify(args)}`);
|
|
51
51
|
const response = await cb(args);
|
|
@@ -71,8 +71,7 @@ const createMcpServer = () => {
|
|
|
71
71
|
};
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
|
-
};
|
|
75
|
-
server.tool(name, description, paramsSchema, args => wrappedCb(args));
|
|
74
|
+
}));
|
|
76
75
|
};
|
|
77
76
|
const posthog = async (event, properties) => {
|
|
78
77
|
try {
|
|
@@ -154,7 +153,7 @@ const createMcpServer = () => {
|
|
|
154
153
|
}
|
|
155
154
|
throw new robot_1.ActionableError(`Device "${device}" not found. Use the mobile_list_available_devices tool to see available devices.`);
|
|
156
155
|
};
|
|
157
|
-
tool("mobile_list_available_devices", "List all available devices. This includes both physical devices and simulators. If there is more than one device returned, you need to let the user select one of them.", {
|
|
156
|
+
tool("mobile_list_available_devices", "List Devices", "List all available devices. This includes both physical devices and simulators. If there is more than one device returned, you need to let the user select one of them.", {
|
|
158
157
|
noParams
|
|
159
158
|
}, async ({}) => {
|
|
160
159
|
const iosManager = new ios_1.IosManager();
|
|
@@ -210,14 +209,14 @@ const createMcpServer = () => {
|
|
|
210
209
|
}
|
|
211
210
|
return resp.join("\n");
|
|
212
211
|
});
|
|
213
|
-
tool("mobile_list_apps", "List all the installed apps on the device", {
|
|
212
|
+
tool("mobile_list_apps", "List Apps", "List all the installed apps on the device", {
|
|
214
213
|
device: zod_1.z.string().describe("The device identifier to use. Use mobile_list_available_devices to find which devices are available to you.")
|
|
215
214
|
}, async ({ device }) => {
|
|
216
215
|
const robot = getRobotFromDevice(device);
|
|
217
216
|
const result = await robot.listApps();
|
|
218
217
|
return `Found these apps on device: ${result.map(app => `${app.appName} (${app.packageName})`).join(", ")}`;
|
|
219
218
|
});
|
|
220
|
-
tool("mobile_launch_app", "Launch an app on mobile device. Use this to open a specific app. You can find the package name of the app by calling list_apps_on_device.", {
|
|
219
|
+
tool("mobile_launch_app", "Launch App", "Launch an app on mobile device. Use this to open a specific app. You can find the package name of the app by calling list_apps_on_device.", {
|
|
221
220
|
device: zod_1.z.string().describe("The device identifier to use. Use mobile_list_available_devices to find which devices are available to you."),
|
|
222
221
|
packageName: zod_1.z.string().describe("The package name of the app to launch"),
|
|
223
222
|
}, async ({ device, packageName }) => {
|
|
@@ -225,7 +224,7 @@ const createMcpServer = () => {
|
|
|
225
224
|
await robot.launchApp(packageName);
|
|
226
225
|
return `Launched app ${packageName}`;
|
|
227
226
|
});
|
|
228
|
-
tool("mobile_terminate_app", "Stop and terminate an app on mobile device", {
|
|
227
|
+
tool("mobile_terminate_app", "Terminate App", "Stop and terminate an app on mobile device", {
|
|
229
228
|
device: zod_1.z.string().describe("The device identifier to use. Use mobile_list_available_devices to find which devices are available to you."),
|
|
230
229
|
packageName: zod_1.z.string().describe("The package name of the app to terminate"),
|
|
231
230
|
}, async ({ device, packageName }) => {
|
|
@@ -233,7 +232,7 @@ const createMcpServer = () => {
|
|
|
233
232
|
await robot.terminateApp(packageName);
|
|
234
233
|
return `Terminated app ${packageName}`;
|
|
235
234
|
});
|
|
236
|
-
tool("mobile_install_app", "Install an app on mobile device", {
|
|
235
|
+
tool("mobile_install_app", "Install App", "Install an app on mobile device", {
|
|
237
236
|
device: zod_1.z.string().describe("The device identifier to use. Use mobile_list_available_devices to find which devices are available to you."),
|
|
238
237
|
path: zod_1.z.string().describe("The path to the app file to install. For iOS simulators, provide a .zip file or a .app directory. For Android provide an .apk file. For iOS real devices provide an .ipa file"),
|
|
239
238
|
}, async ({ device, path }) => {
|
|
@@ -241,7 +240,7 @@ const createMcpServer = () => {
|
|
|
241
240
|
await robot.installApp(path);
|
|
242
241
|
return `Installed app from ${path}`;
|
|
243
242
|
});
|
|
244
|
-
tool("mobile_uninstall_app", "Uninstall an app from mobile device", {
|
|
243
|
+
tool("mobile_uninstall_app", "Uninstall App", "Uninstall an app from mobile device", {
|
|
245
244
|
device: zod_1.z.string().describe("The device identifier to use. Use mobile_list_available_devices to find which devices are available to you."),
|
|
246
245
|
bundle_id: zod_1.z.string().describe("Bundle identifier (iOS) or package name (Android) of the app to be uninstalled"),
|
|
247
246
|
}, async ({ device, bundle_id }) => {
|
|
@@ -249,14 +248,14 @@ const createMcpServer = () => {
|
|
|
249
248
|
await robot.uninstallApp(bundle_id);
|
|
250
249
|
return `Uninstalled app ${bundle_id}`;
|
|
251
250
|
});
|
|
252
|
-
tool("mobile_get_screen_size", "Get the screen size of the mobile device in pixels", {
|
|
251
|
+
tool("mobile_get_screen_size", "Get Screen Size", "Get the screen size of the mobile device in pixels", {
|
|
253
252
|
device: zod_1.z.string().describe("The device identifier to use. Use mobile_list_available_devices to find which devices are available to you.")
|
|
254
253
|
}, async ({ device }) => {
|
|
255
254
|
const robot = getRobotFromDevice(device);
|
|
256
255
|
const screenSize = await robot.getScreenSize();
|
|
257
256
|
return `Screen size is ${screenSize.width}x${screenSize.height} pixels`;
|
|
258
257
|
});
|
|
259
|
-
tool("mobile_click_on_screen_at_coordinates", "Click on the screen at given x,y coordinates. If clicking on an element, use the list_elements_on_screen tool to find the coordinates.", {
|
|
258
|
+
tool("mobile_click_on_screen_at_coordinates", "Click Screen", "Click on the screen at given x,y coordinates. If clicking on an element, use the list_elements_on_screen tool to find the coordinates.", {
|
|
260
259
|
device: zod_1.z.string().describe("The device identifier to use. Use mobile_list_available_devices to find which devices are available to you."),
|
|
261
260
|
x: zod_1.z.number().describe("The x coordinate to click on the screen, in pixels"),
|
|
262
261
|
y: zod_1.z.number().describe("The y coordinate to click on the screen, in pixels"),
|
|
@@ -265,7 +264,7 @@ const createMcpServer = () => {
|
|
|
265
264
|
await robot.tap(x, y);
|
|
266
265
|
return `Clicked on screen at coordinates: ${x}, ${y}`;
|
|
267
266
|
});
|
|
268
|
-
tool("mobile_double_tap_on_screen", "Double-tap on the screen at given x,y coordinates.", {
|
|
267
|
+
tool("mobile_double_tap_on_screen", "Double Tap Screen", "Double-tap on the screen at given x,y coordinates.", {
|
|
269
268
|
device: zod_1.z.string().describe("The device identifier to use. Use mobile_list_available_devices to find which devices are available to you."),
|
|
270
269
|
x: zod_1.z.number().describe("The x coordinate to double-tap, in pixels"),
|
|
271
270
|
y: zod_1.z.number().describe("The y coordinate to double-tap, in pixels"),
|
|
@@ -274,7 +273,7 @@ const createMcpServer = () => {
|
|
|
274
273
|
await robot.doubleTap(x, y);
|
|
275
274
|
return `Double-tapped on screen at coordinates: ${x}, ${y}`;
|
|
276
275
|
});
|
|
277
|
-
tool("mobile_long_press_on_screen_at_coordinates", "Long press on the screen at given x,y coordinates. If long pressing on an element, use the list_elements_on_screen tool to find the coordinates.", {
|
|
276
|
+
tool("mobile_long_press_on_screen_at_coordinates", "Long Press Screen", "Long press on the screen at given x,y coordinates. If long pressing on an element, use the list_elements_on_screen tool to find the coordinates.", {
|
|
278
277
|
device: zod_1.z.string().describe("The device identifier to use. Use mobile_list_available_devices to find which devices are available to you."),
|
|
279
278
|
x: zod_1.z.number().describe("The x coordinate to long press on the screen, in pixels"),
|
|
280
279
|
y: zod_1.z.number().describe("The y coordinate to long press on the screen, in pixels"),
|
|
@@ -283,7 +282,7 @@ const createMcpServer = () => {
|
|
|
283
282
|
await robot.longPress(x, y);
|
|
284
283
|
return `Long pressed on screen at coordinates: ${x}, ${y}`;
|
|
285
284
|
});
|
|
286
|
-
tool("mobile_list_elements_on_screen", "List elements on screen and their coordinates, with display text or accessibility label. Do not cache this result.", {
|
|
285
|
+
tool("mobile_list_elements_on_screen", "List Screen Elements", "List elements on screen and their coordinates, with display text or accessibility label. Do not cache this result.", {
|
|
287
286
|
device: zod_1.z.string().describe("The device identifier to use. Use mobile_list_available_devices to find which devices are available to you.")
|
|
288
287
|
}, async ({ device }) => {
|
|
289
288
|
const robot = getRobotFromDevice(device);
|
|
@@ -310,7 +309,7 @@ const createMcpServer = () => {
|
|
|
310
309
|
});
|
|
311
310
|
return `Found these elements on screen: ${JSON.stringify(result)}`;
|
|
312
311
|
});
|
|
313
|
-
tool("mobile_press_button", "Press a button on device", {
|
|
312
|
+
tool("mobile_press_button", "Press Button", "Press a button on device", {
|
|
314
313
|
device: zod_1.z.string().describe("The device identifier to use. Use mobile_list_available_devices to find which devices are available to you."),
|
|
315
314
|
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)"),
|
|
316
315
|
}, async ({ device, button }) => {
|
|
@@ -318,7 +317,7 @@ const createMcpServer = () => {
|
|
|
318
317
|
await robot.pressButton(button);
|
|
319
318
|
return `Pressed the button: ${button}`;
|
|
320
319
|
});
|
|
321
|
-
tool("mobile_open_url", "Open a URL in browser on device", {
|
|
320
|
+
tool("mobile_open_url", "Open URL", "Open a URL in browser on device", {
|
|
322
321
|
device: zod_1.z.string().describe("The device identifier to use. Use mobile_list_available_devices to find which devices are available to you."),
|
|
323
322
|
url: zod_1.z.string().describe("The URL to open"),
|
|
324
323
|
}, async ({ device, url }) => {
|
|
@@ -326,7 +325,7 @@ const createMcpServer = () => {
|
|
|
326
325
|
await robot.openUrl(url);
|
|
327
326
|
return `Opened URL: ${url}`;
|
|
328
327
|
});
|
|
329
|
-
tool("mobile_swipe_on_screen", "Swipe on the screen", {
|
|
328
|
+
tool("mobile_swipe_on_screen", "Swipe Screen", "Swipe on the screen", {
|
|
330
329
|
device: zod_1.z.string().describe("The device identifier to use. Use mobile_list_available_devices to find which devices are available to you."),
|
|
331
330
|
direction: zod_1.z.enum(["up", "down", "left", "right"]).describe("The direction to swipe"),
|
|
332
331
|
x: zod_1.z.number().optional().describe("The x coordinate to start the swipe from, in pixels. If not provided, uses center of screen"),
|
|
@@ -346,7 +345,7 @@ const createMcpServer = () => {
|
|
|
346
345
|
return `Swiped ${direction} on screen`;
|
|
347
346
|
}
|
|
348
347
|
});
|
|
349
|
-
tool("mobile_type_keys", "Type text into the focused element", {
|
|
348
|
+
tool("mobile_type_keys", "Type Text", "Type text into the focused element", {
|
|
350
349
|
device: zod_1.z.string().describe("The device identifier to use. Use mobile_list_available_devices to find which devices are available to you."),
|
|
351
350
|
text: zod_1.z.string().describe("The text to type"),
|
|
352
351
|
submit: zod_1.z.boolean().describe("Whether to submit the text. If true, the text will be submitted as if the user pressed the enter key."),
|
|
@@ -358,7 +357,7 @@ const createMcpServer = () => {
|
|
|
358
357
|
}
|
|
359
358
|
return `Typed text: ${text}`;
|
|
360
359
|
});
|
|
361
|
-
tool("mobile_save_screenshot", "Save a screenshot of the mobile device to a file", {
|
|
360
|
+
tool("mobile_save_screenshot", "Save Screenshot", "Save a screenshot of the mobile device to a file", {
|
|
362
361
|
device: zod_1.z.string().describe("The device identifier to use. Use mobile_list_available_devices to find which devices are available to you."),
|
|
363
362
|
saveTo: zod_1.z.string().describe("The path to save the screenshot to"),
|
|
364
363
|
}, async ({ device, saveTo }) => {
|
|
@@ -367,8 +366,12 @@ const createMcpServer = () => {
|
|
|
367
366
|
node_fs_1.default.writeFileSync(saveTo, screenshot);
|
|
368
367
|
return `Screenshot saved to: ${saveTo}`;
|
|
369
368
|
});
|
|
370
|
-
server.
|
|
371
|
-
|
|
369
|
+
server.registerTool("mobile_take_screenshot", {
|
|
370
|
+
title: "Take Screenshot",
|
|
371
|
+
description: "Take a screenshot of the mobile device. Use this to understand what's on screen, if you need to press an element that is available through view hierarchy then you must list elements on screen instead. Do not cache this result.",
|
|
372
|
+
inputSchema: {
|
|
373
|
+
device: zod_1.z.string().describe("The device identifier to use. Use mobile_list_available_devices to find which devices are available to you.")
|
|
374
|
+
}
|
|
372
375
|
}, async ({ device }) => {
|
|
373
376
|
try {
|
|
374
377
|
const robot = getRobotFromDevice(device);
|
|
@@ -413,7 +416,7 @@ const createMcpServer = () => {
|
|
|
413
416
|
};
|
|
414
417
|
}
|
|
415
418
|
});
|
|
416
|
-
tool("mobile_set_orientation", "Change the screen orientation of the device", {
|
|
419
|
+
tool("mobile_set_orientation", "Set Orientation", "Change the screen orientation of the device", {
|
|
417
420
|
device: zod_1.z.string().describe("The device identifier to use. Use mobile_list_available_devices to find which devices are available to you."),
|
|
418
421
|
orientation: zod_1.z.enum(["portrait", "landscape"]).describe("The desired orientation"),
|
|
419
422
|
}, async ({ device, orientation }) => {
|
|
@@ -421,7 +424,7 @@ const createMcpServer = () => {
|
|
|
421
424
|
await robot.setOrientation(orientation);
|
|
422
425
|
return `Changed device orientation to ${orientation}`;
|
|
423
426
|
});
|
|
424
|
-
tool("mobile_get_orientation", "Get the current screen orientation of the device", {
|
|
427
|
+
tool("mobile_get_orientation", "Get Orientation", "Get the current screen orientation of the device", {
|
|
425
428
|
device: zod_1.z.string().describe("The device identifier to use. Use mobile_list_available_devices to find which devices are available to you.")
|
|
426
429
|
}, async ({ device }) => {
|
|
427
430
|
const robot = getRobotFromDevice(device);
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mobilenext/mobile-mcp",
|
|
3
3
|
"mcpName": "io.github.mobile-next/mobile-mcp",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.37",
|
|
5
5
|
"description": "Mobile MCP",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -24,14 +24,15 @@
|
|
|
24
24
|
"lib"
|
|
25
25
|
],
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@modelcontextprotocol/sdk": "1.
|
|
27
|
+
"@modelcontextprotocol/sdk": "1.24.2",
|
|
28
28
|
"commander": "14.0.0",
|
|
29
29
|
"express": "5.1.0",
|
|
30
30
|
"fast-xml-parser": "5.2.5",
|
|
31
|
-
"zod
|
|
31
|
+
"zod": "^4.1.13",
|
|
32
|
+
"zod-to-json-schema": "3.25.0"
|
|
32
33
|
},
|
|
33
34
|
"optionalDependencies": {
|
|
34
|
-
"@mobilenext/mobilecli": "0.0.
|
|
35
|
+
"@mobilenext/mobilecli": "0.0.38"
|
|
35
36
|
},
|
|
36
37
|
"devDependencies": {
|
|
37
38
|
"@eslint/eslintrc": "^3.2.0",
|
|
@@ -52,7 +53,7 @@
|
|
|
52
53
|
"mocha": "^11.1.0",
|
|
53
54
|
"nyc": "^17.1.0",
|
|
54
55
|
"ts-node": "^10.9.2",
|
|
55
|
-
"typescript": "
|
|
56
|
+
"typescript": "5.8.2"
|
|
56
57
|
},
|
|
57
58
|
"main": "index.js",
|
|
58
59
|
"bin": {
|