@mobilenext/mobile-mcp 0.0.36 → 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.
Files changed (2) hide show
  1. package/lib/server.js +31 -28
  2. package/package.json +5 -4
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
- const wrappedCb = async (args) => {
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.tool("mobile_take_screenshot", "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.", {
371
- device: zod_1.z.string().describe("The device identifier to use. Use mobile_list_available_devices to find which devices are available to you.")
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.36",
4
+ "version": "0.0.37",
5
5
  "description": "Mobile MCP",
6
6
  "repository": {
7
7
  "type": "git",
@@ -24,11 +24,12 @@
24
24
  "lib"
25
25
  ],
26
26
  "dependencies": {
27
- "@modelcontextprotocol/sdk": "1.13.2",
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-to-json-schema": "3.24.6"
31
+ "zod": "^4.1.13",
32
+ "zod-to-json-schema": "3.25.0"
32
33
  },
33
34
  "optionalDependencies": {
34
35
  "@mobilenext/mobilecli": "0.0.38"
@@ -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": "^5.8.2"
56
+ "typescript": "5.8.2"
56
57
  },
57
58
  "main": "index.js",
58
59
  "bin": {