Skip to main content
Glama
atom2ueki

MCP Server for iOS Simulator

list-available-simulators

Retrieve a list of available iOS simulators via the MCP Server for iOS Simulator, enabling programmatic control and management of simulator environments.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • The main handler function for the 'list-available-simulators' tool. It calls simulatorManager.getAllSimulators(), groups by iOS version, formats a readable table with UDIDs, states, and provides workflow instructions.
    async () => {
      fileLogger.info('Listing all available simulators');
      try {
        const availableSimulators = await simulatorManager.getAllSimulators();
        
        // Group by iOS version for better readability
        const devicesByVersion: Record<string, string[]> = {};
        const udidMap: Record<string, string> = {};
        
        availableSimulators.forEach(simulator => {
          const version = simulator.runtime.replace('com.apple.CoreSimulator.SimRuntime.iOS-', '').replace(/\./g, '-');
          if (!devicesByVersion[version]) {
            devicesByVersion[version] = [];
          }
          devicesByVersion[version].push(simulator.name);
          udidMap[`${simulator.name}-${version}`] = simulator.udid;
        });
        
        // Generate table format with UDIDs
        let tableText = "⭐️ AVAILABLE SIMULATORS - USE THESE UDIDs TO BOOT DIRECTLY ⭐️\n";
        tableText += "─────────────────────────────────────────────────────\n";
        tableText += "NAME                 | iOS VERSION | STATE    | UDID\n";
        tableText += "─────────────────────────────────────────────────────\n";
        
        for (const [version, devices] of Object.entries(devicesByVersion)) {
          const formattedVersion = version.replace(/-/g, '.');
          devices.sort().forEach((deviceName: string) => {
            const simulator = availableSimulators.find(s => s.name === deviceName && s.runtime.includes(version.replace(/-/g, '.')));
            const state = simulator ? simulator.state : 'Unknown';
            const udid = simulator ? simulator.udid : 'Unknown';
            tableText += `${deviceName.padEnd(20)} | iOS ${formattedVersion.padEnd(9)} | ${state.padEnd(8)} | ${udid}\n`;
          });
        }
        tableText += "─────────────────────────────────────────────────────\n";
        
        tableText += "\n💡 RECOMMENDED WORKFLOW:\n";
        tableText += "1️⃣ FIRST: Find the simulator you want from the list above\n";
        tableText += "2️⃣ THEN: Use 'boot-simulator-by-udid' with udid='COPY_UDID_FROM_ABOVE'\n";
        tableText += "3️⃣ FINALLY: When done, use 'shutdown-simulator-by-udid' with the same UDID\n\n";
        tableText += "❌ AVOID using session-based methods like 'create-simulator-session' unless you specifically need advanced features\n";
        
        // For debugging, append the original JSON at the bottom
        tableText += "\nOriginal JSON data:\n```\n";
        tableText += JSON.stringify(availableSimulators, null, 2);
        tableText += "\n```";
        
        return {
          content: [{
            type: 'text',
            text: tableText
          }]
        };
      } catch (error) {
        fileLogger.error('Failed to list available simulators', { error });
        return {
          content: [{
            type: 'text',
            text: `Error: ${error instanceof Error ? error.message : String(error)}`
          }],
          isError: true
        };
      }
    }
  • Registration of the 'list-available-simulators' MCP tool in the registerSimulatorControl method using this.server.tool with empty input schema.
    this.server.tool(
      'list-available-simulators',
      {},
      async () => {
        fileLogger.info('Listing all available simulators');
        try {
          const availableSimulators = await simulatorManager.getAllSimulators();
          
          // Group by iOS version for better readability
          const devicesByVersion: Record<string, string[]> = {};
          const udidMap: Record<string, string> = {};
          
          availableSimulators.forEach(simulator => {
            const version = simulator.runtime.replace('com.apple.CoreSimulator.SimRuntime.iOS-', '').replace(/\./g, '-');
            if (!devicesByVersion[version]) {
              devicesByVersion[version] = [];
            }
            devicesByVersion[version].push(simulator.name);
            udidMap[`${simulator.name}-${version}`] = simulator.udid;
          });
          
          // Generate table format with UDIDs
          let tableText = "⭐️ AVAILABLE SIMULATORS - USE THESE UDIDs TO BOOT DIRECTLY ⭐️\n";
          tableText += "─────────────────────────────────────────────────────\n";
          tableText += "NAME                 | iOS VERSION | STATE    | UDID\n";
          tableText += "─────────────────────────────────────────────────────\n";
          
          for (const [version, devices] of Object.entries(devicesByVersion)) {
            const formattedVersion = version.replace(/-/g, '.');
            devices.sort().forEach((deviceName: string) => {
              const simulator = availableSimulators.find(s => s.name === deviceName && s.runtime.includes(version.replace(/-/g, '.')));
              const state = simulator ? simulator.state : 'Unknown';
              const udid = simulator ? simulator.udid : 'Unknown';
              tableText += `${deviceName.padEnd(20)} | iOS ${formattedVersion.padEnd(9)} | ${state.padEnd(8)} | ${udid}\n`;
            });
          }
          tableText += "─────────────────────────────────────────────────────\n";
          
          tableText += "\n💡 RECOMMENDED WORKFLOW:\n";
          tableText += "1️⃣ FIRST: Find the simulator you want from the list above\n";
          tableText += "2️⃣ THEN: Use 'boot-simulator-by-udid' with udid='COPY_UDID_FROM_ABOVE'\n";
          tableText += "3️⃣ FINALLY: When done, use 'shutdown-simulator-by-udid' with the same UDID\n\n";
          tableText += "❌ AVOID using session-based methods like 'create-simulator-session' unless you specifically need advanced features\n";
          
          // For debugging, append the original JSON at the bottom
          tableText += "\nOriginal JSON data:\n```\n";
          tableText += JSON.stringify(availableSimulators, null, 2);
          tableText += "\n```";
          
          return {
            content: [{
              type: 'text',
              text: tableText
            }]
          };
        } catch (error) {
          fileLogger.error('Failed to list available simulators', { error });
          return {
            content: [{
              type: 'text',
              text: `Error: ${error instanceof Error ? error.message : String(error)}`
            }],
            isError: true
          };
        }
      }
    );
  • Core helper function that executes 'xcrun simctl list devices -j', parses the JSON output, and returns structured list of all available simulators with UDID, name, state, runtime, and availability.
    async getAllSimulators(): Promise<SimulatorInfo[]> {
      try {
        const execAsync = promisify(exec);
        // Use simctl directly to avoid potential stdout corruption
        const { stdout } = await execAsync('xcrun simctl list devices -j');
        
        // Safely parse the JSON output
        const devices = JSON.parse(stdout).devices;
        const allSimulators: SimulatorInfo[] = [];
        
        // Parse the output to find all devices
        for (const runtime in devices) {
          const runtimeDevices = devices[runtime];
          for (const device of runtimeDevices) {
            allSimulators.push({
              udid: device.udid,
              name: device.name,
              state: device.state,
              runtime: runtime,
              isAvailable: device.isAvailable !== false
            });
          }
        }
        
        fileLogger.info(`Found ${allSimulators.length} simulators`);
        return allSimulators;
      } catch (error) {
        fileLogger.error('Failed to get simulators', { error });
        return [];
      }
    }

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/atom2ueki/mcp-server-ios-simulator'

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