Skip to main content
Glama
native-run.ts9.15 kB
/** * @fileoverview Native-Run Tools - Lightweight ADB Alternative * * Provides native-run integration as a lightweight alternative to ADB for device * management and app deployment. native-run is part of the Capacitor/Ionic ecosystem * and offers cross-platform support for Android and iOS. * * @module tools/android/native-run * @category Device Management * @see {@link https://github.com/ionic-team/native-run|native-run GitHub} */ import { z } from 'zod'; import { ProcessExecutor } from '../../utils/process.js'; import { Tool } from '@modelcontextprotocol/sdk/types.js'; const processExecutor = new ProcessExecutor(); /** * Zod validation schema for native_run_list_devices tool. * * @type {z.ZodObject} * @property {string} platform - Target platform (android or ios) */ const NativeRunListDevicesSchema = z.object({ platform: z.enum(['android', 'ios']).default('android'), }); /** * Zod validation schema for native_run_install_app tool. * * @type {z.ZodObject} * @property {string} platform - Target platform (android or ios) * @property {string} appPath - Path to app file (APK for Android, .app for iOS) * @property {string} [deviceId] - Target device ID (optional) */ const NativeRunInstallAppSchema = z.object({ platform: z.enum(['android', 'ios']).default('android'), appPath: z.string().min(1), deviceId: z.string().optional(), }); /** * Zod validation schema for native_run_run_app tool. * * @type {z.ZodObject} * @property {string} platform - Target platform (android or ios) * @property {string} appId - App identifier (bundle ID for iOS, package name for Android) * @property {string} [deviceId] - Target device ID (optional) */ const NativeRunRunAppSchema = z.object({ platform: z.enum(['android', 'ios']).default('android'), appId: z.string().min(1), deviceId: z.string().optional(), }); /** * Checks if native-run CLI is available in the system PATH. * * @returns {Promise<boolean>} True if native-run is available, false otherwise */ async function isNativeRunAvailable(): Promise<boolean> { try { await processExecutor.execute('native-run', ['--version']); return true; } catch { return false; } } /** * Creates native-run tools as lightweight alternatives to ADB. * Provides cross-platform device management for Android and iOS. * * @returns {Map<string, Tool>} Map of native-run tool names to tool configurations */ export function createNativeRunTools(): Map<string, Tool> { const tools = new Map<string, Tool>(); // Native-Run - List devices (Android & iOS) tools.set('native_run_list_devices', { name: 'native_run_list_devices', description: 'List connected devices using native-run (Android & iOS support)', inputSchema: { type: 'object', properties: { platform: { type: 'string', enum: ['android', 'ios'], default: 'android' } }, required: [] }, handler: async (args: any) => { const parsed = NativeRunListDevicesSchema.parse(args); if (!(await isNativeRunAvailable())) { throw new Error('native-run is not installed. Install with: npm install -g native-run'); } const result = await processExecutor.execute('native-run', [ parsed.platform, '--list', '--json' ]); if (result.exitCode !== 0) { throw new Error(`Failed to list ${parsed.platform} devices: ${result.stderr}`); } let devices = []; try { const output = JSON.parse(result.stdout); devices = output.devices || []; } catch (parseError) { // If JSON parsing fails, try to parse text output devices = result.stdout .split('\n') .filter((line: string) => line.trim() && !line.includes('Available targets')) .map((line: string, index: number) => ({ id: `device_${index}`, name: line.trim(), platform: parsed.platform, available: true })); } return { success: true, data: { platform: parsed.platform, devices, totalCount: devices.length, tool: 'native-run' }, }; } }); // Native-Run - Install app tools.set('native_run_install_app', { name: 'native_run_install_app', description: 'Install app on device using native-run (works for Android APK & iOS app)', inputSchema: { type: 'object', properties: { platform: { type: 'string', enum: ['android', 'ios'], default: 'android' }, appPath: { type: 'string', minLength: 1 }, deviceId: { type: 'string' } }, required: ['appPath'] }, handler: async (args: any) => { const parsed = NativeRunInstallAppSchema.parse(args); if (!(await isNativeRunAvailable())) { throw new Error('native-run is not installed. Install with: npm install -g native-run'); } const runArgs = [ parsed.platform, '--app', parsed.appPath, '--device' ]; if (parsed.deviceId) { runArgs.push('--target', parsed.deviceId); } const result = await processExecutor.execute('native-run', runArgs); if (result.exitCode !== 0) { throw new Error(`Failed to install app on ${parsed.platform}: ${result.stderr}`); } return { success: true, data: { message: `App installed successfully on ${parsed.platform}`, platform: parsed.platform, appPath: parsed.appPath, deviceId: parsed.deviceId, tool: 'native-run' }, }; } }); // Native-Run - Run app tools.set('native_run_run_app', { name: 'native_run_run_app', description: 'Run/launch app on device using native-run', inputSchema: { type: 'object', properties: { platform: { type: 'string', enum: ['android', 'ios'], default: 'android' }, appId: { type: 'string', minLength: 1 }, deviceId: { type: 'string' } }, required: ['appId'] }, handler: async (args: any) => { const parsed = NativeRunRunAppSchema.parse(args); if (!(await isNativeRunAvailable())) { throw new Error('native-run is not installed. Install with: npm install -g native-run'); } const runArgs = [ parsed.platform, '--app', parsed.appId ]; if (parsed.deviceId) { runArgs.push('--target', parsed.deviceId); } const result = await processExecutor.execute('native-run', runArgs); if (result.exitCode !== 0) { throw new Error(`Failed to run app on ${parsed.platform}: ${result.stderr}`); } return { success: true, data: { message: `App launched successfully on ${parsed.platform}`, platform: parsed.platform, appId: parsed.appId, deviceId: parsed.deviceId, tool: 'native-run' }, }; } }); // Native-Run - Get device info tools.set('native_run_device_info', { name: 'native_run_device_info', description: 'Get detailed device information using native-run', inputSchema: { type: 'object', properties: { platform: { type: 'string', enum: ['android', 'ios'], default: 'android' }, deviceId: { type: 'string' } }, required: [] }, handler: async (args: any) => { const parsed = z.object({ platform: z.enum(['android', 'ios']).default('android'), deviceId: z.string().optional(), }).parse(args); if (!(await isNativeRunAvailable())) { throw new Error('native-run is not installed. Install with: npm install -g native-run'); } const runArgs = [ parsed.platform, '--list', '--json' ]; if (parsed.deviceId) { runArgs.push('--target', parsed.deviceId); } const result = await processExecutor.execute('native-run', runArgs); if (result.exitCode !== 0) { throw new Error(`Failed to get device info: ${result.stderr}`); } let deviceInfo = {}; try { const output = JSON.parse(result.stdout); deviceInfo = output.devices?.[0] || { message: 'Device info retrieved' }; } catch (parseError) { deviceInfo = { platform: parsed.platform, deviceId: parsed.deviceId, raw_output: result.stdout, message: 'Device info retrieved (raw format)' }; } return { success: true, data: { platform: parsed.platform, deviceInfo, tool: 'native-run' }, }; } }); return tools; } /** * Check if native-run can be used as ADB alternative */ export async function canUseNativeRun(): Promise<boolean> { return await isNativeRunAvailable(); }

Implementation Reference

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/cristianoaredes/mcp-mobile-server'

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