Skip to main content
Glama

start_sim_log_cap

Capture structured logs from a simulator by specifying its UUID and app bundle ID. Optionally include console output by relaunching the app.

Instructions

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

Input Schema

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

Implementation Reference

  • The main handler function implementing the tool logic: validates input, invokes startLogCapture helper, handles errors, and returns formatted response with session ID.
    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 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 using registerTool, specifying name, description, schema, and handler.
    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, );
  • Top-level conditional registration entry invoking registerStartSimulatorLogCaptureTool as part of the toolRegistrations array.
    { register: registerStartSimulatorLogCaptureTool, groups: [ToolGroup.DIAGNOSTICS, ToolGroup.IOS_SIMULATOR_WORKFLOW], envVar: 'XCODEBUILDMCP_TOOL_START_SIMULATOR_LOG_CAPTURE', },
  • Core helper function that starts log capture by spawning xcrun simctl processes for os_log stream and optional console output, piping to a temp log file, and managing active sessions via Map.
    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