list_simulators
Retrieve available iOS simulators for testing and development, with options to filter by platform, state, or device name.
Instructions
List available iOS simulators
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| platform | No | Filter by platform | |
| state | No | Filter by simulator state | |
| name | No | Filter by device name (partial match, case-insensitive) |
Implementation Reference
- MCPController implementation for 'list_simulators' tool, including name, description, input schema, tool definition, and execute method that handles filtering and formatting of simulator list.export class ListSimulatorsController implements MCPController { readonly name = 'list_simulators'; readonly description = 'List available iOS simulators'; constructor( private useCase: ListSimulatorsUseCase ) {} get inputSchema() { return { type: 'object' as const, properties: { platform: { type: 'string' as const, description: 'Filter by platform', enum: ['iOS', 'tvOS', 'watchOS', 'visionOS'] as const }, state: { type: 'string' as const, description: 'Filter by simulator state', enum: ['Booted', 'Shutdown'] as const }, name: { type: 'string' as const, description: 'Filter by device name (partial match, case-insensitive)' } }, required: [] as const }; } getToolDefinition() { return { name: this.name, description: this.description, inputSchema: this.inputSchema }; } async execute(args: unknown): Promise<{ content: Array<{ type: string; text: string }> }> { try { // Cast to expected shape const input = args as { platform?: string; state?: string; name?: string }; // Use the new validation functions const platform = Platform.parseOptional(input.platform); const state = SimulatorState.parseOptional(input.state); const request = ListSimulatorsRequest.create(platform, state, input.name); const result = await this.useCase.execute(request); if (!result.isSuccess) { return { content: [{ type: 'text', text: `❌ ${ErrorFormatter.format(result.error!)}` }] }; } if (result.count === 0) { return { content: [{ type: 'text', text: '🔍 No simulators found' }] }; } const lines: string[] = [ `✅ Found ${result.count} simulator${result.count === 1 ? '' : 's'}`, '' ]; for (const simulator of result.simulators) { lines.push(`• ${simulator.name} (${simulator.udid}) - ${simulator.state} - ${simulator.runtime}`); } return { content: [{ type: 'text', text: lines.join('\n') }] }; } catch (error) { return { content: [{ type: 'text', text: `❌ ${ErrorFormatter.format(error as Error)}` }] }; } } }
- src/index.ts:77-118 (registration)Registers the ListSimulatorsController (via factory) along with other tools in the MCP server's tool map.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'); }
- Input schema definition for the list_simulators tool, defining optional filters for platform, state, and name.get inputSchema() { return { type: 'object' as const, properties: { platform: { type: 'string' as const, description: 'Filter by platform', enum: ['iOS', 'tvOS', 'watchOS', 'visionOS'] as const }, state: { type: 'string' as const, description: 'Filter by simulator state', enum: ['Booted', 'Shutdown'] as const }, name: { type: 'string' as const, description: 'Filter by device name (partial match, case-insensitive)' } }, required: [] as const }; }
- Factory that creates the ListSimulatorsController with its dependencies (use case, repository, shell executor).export class ListSimulatorsControllerFactory { static create(): ListSimulatorsController { const execAsync = promisify(exec); const executor = new ShellCommandExecutorAdapter(execAsync); const deviceRepository = new DeviceRepository(executor); const useCase = new ListSimulatorsUseCase(deviceRepository); return new ListSimulatorsController(useCase); } }
- src/utils/devices/Devices.ts:71-102 (helper)Low-level helper method that executes 'xcrun simctl list devices --json' and parses available simulators, used indirectly via repository.async listSimulators(platform?: Platform): Promise<SimulatorDevice[]> { try { const { stdout } = await execAsync('xcrun simctl list devices --json'); const data = JSON.parse(stdout); const devices: SimulatorDevice[] = []; for (const [runtime, deviceList] of Object.entries(data.devices)) { const extractedPlatform = this.extractPlatformFromRuntime(runtime); // Filter by platform if specified if (platform && !this.matchesPlatform(extractedPlatform, platform)) { continue; } for (const device of deviceList as any[]) { if (device.isAvailable) { devices.push(new SimulatorDevice( device.udid, device.name, extractedPlatform, runtime )); } } } return devices; } catch (error: any) { logger.error({ error: error.message }, 'Failed to list simulators'); throw new Error(`Failed to list simulators: ${error.message}`); } }