Skip to main content
Glama

start_sim_log_cap

Capture structured logs from iOS simulators for app debugging and testing. Specify simulator UUID and bundle ID to start log collection.

Instructions

Starts capturing logs from a specified simulator. Returns a session ID. By default, captures only structured logs.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
simulatorUuidYesUUID of the simulator to capture logs from (obtained from list_simulators).
bundleIdYesBundle identifier of the app to capture logs for.
captureConsoleNoWhether to capture console output (requires app relaunch).

Implementation Reference

  • The handler function that executes the MCP tool logic for 'start_sim_log_cap'. Validates parameters and calls the core startLogCapture helper.
    async function handler(params: {
      simulatorUuid: string;
      bundleId: string;
      captureConsole?: boolean;
    }): Promise<ToolResponse> {
      const validationResult = validateRequiredParam('simulatorUuid', params.simulatorUuid);
      if (!validationResult.isValid) {
        return validationResult.errorResponse!;
      }
    
      const { sessionId, error } = await startLogCapture(params);
      if (error) {
        return {
          content: [createTextContent(`Error starting log capture: ${error}`)],
          isError: true,
        };
      }
      return {
        content: [
          createTextContent(
            `Log capture started successfully. Session ID: ${sessionId}.\n\n${params.captureConsole ? 'Note: Your app was relaunched to capture console output.' : 'Note: Only structured logs are being captured.'}\n\nNext Steps:\n1.  Interact with your simulator and app.\n2.  Use 'stop_sim_log_cap' with session ID '${sessionId}' to stop capture and retrieve logs.`,
          ),
        ],
      };
    }
  • Zod schema defining the input parameters for the 'start_sim_log_cap' tool.
    const schema = {
      simulatorUuid: z
        .string()
        .describe('UUID of the simulator to capture logs from (obtained from list_simulators).'),
      bundleId: z.string().describe('Bundle identifier of the app to capture logs for.'),
      captureConsole: z
        .boolean()
        .optional()
        .default(false)
        .describe('Whether to capture console output (requires app relaunch).'),
    };
  • src/tools/log.ts:64-70 (registration)
    Direct registration of the 'start_sim_log_cap' tool with the MCP server using registerTool.
    registerTool(
      server,
      'start_sim_log_cap',
      'Starts capturing logs from a specified simulator. Returns a session ID. By default, captures only structured logs.',
      schema,
      handler,
    );
  • Core implementation of log capture: spawns xcrun simctl processes to stream structured logs and optional console output to a temporary file, manages active sessions.
    export async function startLogCapture(params: {
      simulatorUuid: string;
      bundleId: string;
      captureConsole?: boolean;
    }): Promise<{ sessionId: string; logFilePath: string; processes: ChildProcess[]; error?: string }> {
      // Clean up old logs before starting a new session
      await cleanOldLogs();
    
      const { simulatorUuid, bundleId, captureConsole = false } = params;
      const logSessionId = uuidv4();
      const logFileName = `${LOG_FILE_PREFIX}${logSessionId}.log`;
      const logFilePath = path.join(os.tmpdir(), logFileName);
    
      try {
        await fs.promises.mkdir(os.tmpdir(), { recursive: true });
        await fs.promises.writeFile(logFilePath, '');
        const logStream = fs.createWriteStream(logFilePath, { flags: 'a' });
        const processes: ChildProcess[] = [];
        logStream.write('\n--- Log capture for bundle ID: ' + bundleId + ' ---\n');
    
        if (captureConsole) {
          const stdoutLogProcess = spawn('xcrun', [
            'simctl',
            'launch',
            '--console-pty',
            '--terminate-running-process',
            simulatorUuid,
            bundleId,
          ]);
          stdoutLogProcess.stdout.pipe(logStream);
          stdoutLogProcess.stderr.pipe(logStream);
          processes.push(stdoutLogProcess);
        }
    
        const osLogProcess = spawn('xcrun', [
          'simctl',
          'spawn',
          simulatorUuid,
          'log',
          'stream',
          '--level=debug',
          '--predicate',
          `subsystem == "${bundleId}"`,
        ]);
        osLogProcess.stdout.pipe(logStream);
        osLogProcess.stderr.pipe(logStream);
        processes.push(osLogProcess);
    
        for (const process of processes) {
          process.on('close', (code) => {
            log('info', `A log capture process for session ${logSessionId} exited with code ${code}.`);
          });
        }
    
        activeLogSessions.set(logSessionId, {
          processes,
          logFilePath,
          simulatorUuid,
          bundleId,
        });
    
        log('info', `Log capture started with session ID: ${logSessionId}`);
        return { sessionId: logSessionId, logFilePath, processes };
      } catch (error) {
        const message = error instanceof Error ? error.message : String(error);
        log('error', `Failed to start log capture: ${message}`);
        return { sessionId: '', logFilePath: '', processes: [], error: message };
      }

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/SampsonKY/XcodeBuildMCP'

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