Skip to main content
Glama

install_app

Install an app bundle on an iOS simulator to test and run applications during development. Specify the app path and optionally target a specific simulator device.

Instructions

Install an app on the simulator

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
appPathYesPath to the .app bundle
simulatorIdNoDevice UDID or name of the simulator (optional, uses booted device if not specified)

Implementation Reference

  • The execute method implements the core logic of the 'install_app' MCP tool: validates input, creates domain request, executes the use case, and returns formatted success/error response.
    async execute(args: unknown): Promise<{ content: Array<{ type: string; text: string }> }> { try { // Type guard for input if (!args || typeof args !== 'object') { throw new Error('Invalid input: expected an object'); } const input = args as InstallAppArgs; // Create domain request (validation happens here) const request = InstallRequest.create(input.appPath, input.simulatorId); // Execute use case const result = await this.useCase.execute(request); // Format response return { content: [{ type: 'text', text: this.formatResult(result) }] }; } catch (error: any) { // Handle validation and use case errors consistently const message = ErrorFormatter.format(error); return { content: [{ type: 'text', text: `❌ ${message}` }] }; } }
  • Defines the input JSON schema for the 'install_app' tool: requires appPath string, optional simulatorId.
    get inputSchema() { return { type: 'object' as const, properties: { appPath: { type: 'string', description: 'Path to the .app bundle' }, simulatorId: { type: 'string', description: 'Device UDID or name of the simulator (optional, uses booted device if not specified)' } }, required: ['appPath'] }; }
  • src/index.ts:77-117 (registration)
    Registers the InstallAppController (created via factory) to the MCP server's tools Map by name for handling tool calls.
    private registerTools() { // Create instances of all tools const toolInstances = [ // Simulator management ListSimulatorsControllerFactory.create(), BootSimulatorControllerFactory.create(), ShutdownSimulatorControllerFactory.create(), // new ViewSimulatorScreenTool(), // Build and test // new BuildSwiftPackageTool(), // new RunSwiftPackageTool(), BuildXcodeControllerFactory.create(), InstallAppControllerFactory.create(), // new RunXcodeTool(), // new TestXcodeTool(), // new TestSwiftPackageTool(), // new CleanBuildTool(), // Archive and export // new ArchiveProjectTool(), // new ExportIPATool(), // Project info and schemes // new ListSchemesTool(), // new GetBuildSettingsTool(), // new GetProjectInfoTool(), // new ListTargetsTool(), // App management // new InstallAppTool(), // new UninstallAppTool(), // Device logs // new GetDeviceLogsTool(), // Advanced project management // new ManageDependenciesTool() ]; // Register each tool by its name for (const tool of toolInstances) { const definition = tool.getToolDefinition(); this.tools.set(definition.name, tool); } logger.info({ toolCount: this.tools.size }, 'Tools registered');
  • Core business logic for app installation: locates/boots simulator if needed, installs app via ports, handles all errors and logging.
    async execute(request: InstallRequest): Promise<InstallResult> { // Get app name from the AppPath value object const appName = request.appPath.name; // Find target simulator const simulator = request.simulatorId ? await this.simulatorLocator.findSimulator(request.simulatorId.toString()) : await this.simulatorLocator.findBootedSimulator(); if (!simulator) { this.logManager.saveDebugData('install-app-failed', { reason: 'simulator_not_found', requestedId: request.simulatorId?.toString() }, appName); const error = request.simulatorId ? new SimulatorNotFoundError(request.simulatorId) : new NoBootedSimulatorError(); return InstallResult.failed(error, request.appPath, request.simulatorId); } // Boot simulator if needed (only when specific ID provided) if (request.simulatorId) { if (simulator.state === SimulatorState.Shutdown) { try { await this.simulatorControl.boot(simulator.id); this.logManager.saveDebugData('simulator-auto-booted', { simulatorId: simulator.id, simulatorName: simulator.name }, appName); } catch (error: any) { this.logManager.saveDebugData('simulator-boot-failed', { simulatorId: simulator.id, error: error.message }, appName); const installError = new InstallCommandFailedError(error.message || error.toString()); return InstallResult.failed( installError, request.appPath, DeviceId.create(simulator.id), simulator.name ); } } } // Install the app try { await this.appInstaller.installApp( request.appPath.toString(), simulator.id ); this.logManager.saveDebugData('install-app-success', { simulator: simulator.name, simulatorId: simulator.id, app: appName }, appName); // Try to get bundle ID from app (could be enhanced later) const bundleId = appName; // For now, use app name as bundle ID return InstallResult.succeeded( bundleId, DeviceId.create(simulator.id), simulator.name, request.appPath ); } catch (error: any) { this.logManager.saveDebugData('install-app-error', { simulator: simulator.name, simulatorId: simulator.id, app: appName, error: error.message }, appName); const installError = new InstallCommandFailedError(error.message || error.toString()); return InstallResult.failed( installError, request.appPath, DeviceId.create(simulator.id), simulator.name ); } }
  • Dependency injection factory that wires all adapters, use case, controller, and decorators for the install_app tool.
    static create(): MCPController { // Create the shell executor that all adapters will use const execAsync = promisify(exec); const executor = new ShellCommandExecutorAdapter(execAsync); // Create infrastructure adapters const simulatorLocator = new SimulatorLocatorAdapter(executor); const simulatorControl = new SimulatorControlAdapter(executor); const appInstaller = new AppInstallerAdapter(executor); const logManager = new LogManagerInstance(); // Create the use case with all dependencies const useCase = new InstallAppUseCase( simulatorLocator, simulatorControl, appInstaller, logManager ); // Create the controller const controller = new InstallAppController(useCase); // Create dependency checker const dependencyChecker = new DependencyChecker(executor); // Wrap with dependency checking decorator const decoratedController = new DependencyCheckingDecorator( controller, ['xcrun'], // simctl is part of xcrun dependencyChecker ); return decoratedController; }

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/Stefan-Nitu/mcp-xcode'

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