android_install_apk
Install APK files on Android devices or emulators by specifying device serial and APK path, with options to replace existing apps or allow test APKs.
Instructions
Install an APK file to an Android device or emulator
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| serial | Yes | Device serial number | |
| apkPath | Yes | Path to APK file | |
| options | No |
Implementation Reference
- src/tools/android.ts:773-822 (handler)The asynchronous handler function for the android_install_apk tool. It validates input using Zod schema, checks if the APK file exists and has correct extension, constructs ADB install command with optional flags, executes it via processExecutor, and returns success with output or throws error.handler: async (args: any) => { const validation = AndroidAdbInstallSchema.safeParse(args); if (!validation.success) { throw new Error(`Invalid request: ${validation.error.message}`); } const { serial, apkPath, options = {} } = validation.data; // Validate APK path if (!apkPath.endsWith('.apk')) { throw new Error(`File must have .apk extension. Invalid path: ${apkPath}`); } // Check if APK file exists try { await fs.access(apkPath); } catch { throw new Error(`APK file not found: ${apkPath}`); } const adb_args = ['-s', serial, 'install']; if (options.replace) { adb_args.push('-r'); } if (options.test) { adb_args.push('-t'); } adb_args.push(apkPath); const result = await processExecutor.execute('adb', adb_args, { timeout: 300000, // 5 minutes timeout for APK installation }); if (result.exitCode !== 0) { throw new Error(`APK installation failed: ${result.stderr || result.stdout}`); } return { success: true, data: { serial, apkPath: path.basename(apkPath), output: result.stdout, }, }; } });
- src/tools/android.ts:107-114 (schema)Zod validation schema defining the input parameters for the android_install_apk tool: required serial (device ID), apkPath (file path), and optional options for replace and test flags.const AndroidAdbInstallSchema = z.object({ serial: z.string().min(1), apkPath: z.string().min(1), options: z.object({ replace: z.boolean().optional(), test: z.boolean().optional(), }).optional(), });
- src/tools/android.ts:755-822 (registration)Registration of the android_install_apk tool within the createAndroidTools factory function, including name, description, JSON schema for MCP protocol, and reference to the handler function.tools.set('android_install_apk', { name: 'android_install_apk', description: 'Install an APK file to an Android device or emulator', inputSchema: { type: 'object', properties: { serial: { type: 'string', minLength: 1, description: 'Device serial number' }, apkPath: { type: 'string', minLength: 1, description: 'Path to APK file' }, options: { type: 'object', properties: { replace: { type: 'boolean', description: 'Replace existing app if installed' }, test: { type: 'boolean', description: 'Allow test APKs' } } } }, required: ['serial', 'apkPath'] }, handler: async (args: any) => { const validation = AndroidAdbInstallSchema.safeParse(args); if (!validation.success) { throw new Error(`Invalid request: ${validation.error.message}`); } const { serial, apkPath, options = {} } = validation.data; // Validate APK path if (!apkPath.endsWith('.apk')) { throw new Error(`File must have .apk extension. Invalid path: ${apkPath}`); } // Check if APK file exists try { await fs.access(apkPath); } catch { throw new Error(`APK file not found: ${apkPath}`); } const adb_args = ['-s', serial, 'install']; if (options.replace) { adb_args.push('-r'); } if (options.test) { adb_args.push('-t'); } adb_args.push(apkPath); const result = await processExecutor.execute('adb', adb_args, { timeout: 300000, // 5 minutes timeout for APK installation }); if (result.exitCode !== 0) { throw new Error(`APK installation failed: ${result.stderr || result.stdout}`); } return { success: true, data: { serial, apkPath: path.basename(apkPath), output: result.stdout, }, }; } });