Skip to main content
Glama
install-app.ts4.61 kB
/** * install_app Tool Handler * MCP tool for installing apps on devices/simulators */ import { Platform, isPlatform } from '../../models/constants.js'; import { Errors } from '../../models/errors.js'; import { installApk, listDevices as listAndroidDevices } from '../../platforms/android/adb.js'; import { installApp as installIOSApp, listDevices as listIOSDevices, getBootedDevice } from '../../platforms/ios/simctl.js'; import { getToolRegistry, createInputSchema } from '../register.js'; /** * Input arguments for install_app tool */ export interface InstallAppArgs { /** Target platform */ platform: string; /** Path to the app artifact (APK or .app bundle) */ appPath: string; /** Target device ID or name (optional, uses first available if not specified) */ deviceId?: string; } /** * Result of install operation */ export interface InstallResult { success: boolean; platform: Platform; deviceId: string; deviceName: string; appPath: string; } /** * Install app tool handler */ export async function installApp(args: InstallAppArgs): Promise<InstallResult> { const { platform, appPath, deviceId } = args; // Validate platform if (!isPlatform(platform)) { throw Errors.invalidArguments(`Invalid platform: ${platform}. Must be 'android' or 'ios'`); } // Validate app path if (!appPath || appPath.trim().length === 0) { throw Errors.invalidArguments('appPath is required'); } if (platform === 'android') { return installAndroidApp(appPath, deviceId); } else { return installIOSApplication(appPath, deviceId); } } /** * Install Android APK */ async function installAndroidApp( apkPath: string, deviceId?: string ): Promise<InstallResult> { // Find device if not specified let targetDevice: { id: string; name: string }; if (deviceId) { const devices = await listAndroidDevices(); const found = devices.find( (d) => d.id === deviceId || d.name === deviceId || d.model === deviceId ); if (!found) { throw Errors.deviceNotFound(deviceId, devices.map((d) => `${d.id} (${d.name})`)); } targetDevice = { id: found.id, name: found.name }; } else { const devices = await listAndroidDevices(); const bootedDevice = devices.find((d) => d.status === 'booted'); if (!bootedDevice) { throw Errors.invalidArguments('No running Android device found. Boot a device first.'); } targetDevice = { id: bootedDevice.id, name: bootedDevice.name }; } // Install the APK await installApk(apkPath, targetDevice.id); return { success: true, platform: 'android', deviceId: targetDevice.id, deviceName: targetDevice.name, appPath: apkPath, }; } /** * Install iOS app */ async function installIOSApplication( appPath: string, deviceId?: string ): Promise<InstallResult> { // Find device if not specified let targetDevice: { id: string; name: string }; if (deviceId) { const devices = await listIOSDevices(); const found = devices.find((d) => d.id === deviceId || d.name === deviceId); if (!found) { throw Errors.deviceNotFound(deviceId, devices.map((d) => `${d.id} (${d.name})`)); } targetDevice = { id: found.id, name: found.name }; } else { const bootedDevice = await getBootedDevice(); if (!bootedDevice) { throw Errors.invalidArguments('No running iOS simulator found. Boot a simulator first.'); } targetDevice = { id: bootedDevice.id, name: bootedDevice.name }; } // Install the app await installIOSApp(appPath, targetDevice.id); return { success: true, platform: 'ios', deviceId: targetDevice.id, deviceName: targetDevice.name, appPath, }; } /** * Register the install_app tool */ export function registerInstallAppTool(): void { getToolRegistry().register( 'install_app', { description: 'Install an app on a device or simulator. For Android, installs an APK. For iOS, installs an .app bundle.', inputSchema: createInputSchema( { platform: { type: 'string', enum: ['android', 'ios'], description: 'Target platform', }, appPath: { type: 'string', description: 'Path to the app artifact (APK for Android, .app bundle for iOS)', }, deviceId: { type: 'string', description: 'Device ID or name (optional, uses first running device if not specified)', }, }, ['platform', 'appPath'] ), }, (args) => installApp(args as unknown as InstallAppArgs) ); }

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/abd3lraouf/specter-mcp'

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