Skip to main content
Glama
conorluddy

XC-MCP: XCode CLI wrapper

by conorluddy

simctl-get-details

Retrieve filtered simulator details from cached simctl-list data by specifying cache ID, detail type, device, runtime, or max devices. Optimizes Xcode CLI usage within MCP limits.

Instructions

Get detailed simulator information from cached simctl-list results with progressive disclosure

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
cacheIdYesCache ID from previous simctl-list call
detailTypeYesType of details to retrieve
deviceTypeNoFilter by device type (iPhone, iPad, etc.)
maxDevicesNoMaximum number of devices to return
runtimeNoFilter by runtime version

Implementation Reference

  • Primary handler function that processes arguments, validates cache, parses simulator data, dispatches to formatters based on detailType, and returns formatted JSON response.
    export async function simctlGetDetailsTool(args: any) { const { cacheId, detailType, deviceType, runtime, maxDevices = 20, } = args as SimctlGetDetailsArgs; try { const cached = responseCache.get(cacheId); if (!cached) { throw new McpError( ErrorCode.InvalidParams, `Cache ID '${cacheId}' not found or expired. Use recent simctl-list result.` ); } if (cached.tool !== 'simctl-list') { throw new McpError( ErrorCode.InvalidParams, `Cache ID '${cacheId}' is not from simctl-list tool.` ); } const fullList: CachedSimulatorList = JSON.parse(cached.fullOutput); let responseData: any; switch (detailType) { case 'full-list': responseData = formatFullList(fullList, { deviceType, runtime, maxDevices }); break; case 'devices-only': responseData = formatDevicesOnly(fullList, { deviceType, runtime, maxDevices }); break; case 'runtimes-only': responseData = formatRuntimesOnly(fullList); break; case 'available-only': responseData = formatAvailableOnly(fullList, { deviceType, runtime, maxDevices }); break; default: throw new McpError(ErrorCode.InvalidParams, `Unknown detailType: ${detailType}`); } return { content: [ { type: 'text' as const, text: JSON.stringify(responseData, null, 2), }, ], }; } catch (error) { if (error instanceof McpError) { throw error; } throw new McpError( ErrorCode.InternalError, `simctl-get-details failed: ${error instanceof Error ? error.message : String(error)}` ); } }
  • Registers the 'simctl-get-details' tool with the MCP server in registerSimctlTools function, including schema, description, and error-handling wrapper around the handler.
    server.registerTool( 'simctl-get-details', { description: getDescription(SIMCTL_GET_DETAILS_DOCS, SIMCTL_GET_DETAILS_DOCS_MINI), inputSchema: { cacheId: z.string(), detailType: z.enum(['full-list', 'devices-only', 'runtimes-only', 'available-only']), deviceType: z.string().optional(), runtime: z.string().optional(), maxDevices: z.number().default(20), }, ...DEFER_LOADING_CONFIG, }, async args => { try { await validateXcodeInstallation(); return await simctlGetDetailsTool(args); } catch (error) { if (error instanceof McpError) throw error; throw new McpError( ErrorCode.InternalError, `Tool execution failed: ${error instanceof Error ? error.message : String(error)}` ); } } );
  • Zod input schema defining validation for tool parameters: required cacheId and detailType, optional filters.
    inputSchema: { cacheId: z.string(), detailType: z.enum(['full-list', 'devices-only', 'runtimes-only', 'available-only']), deviceType: z.string().optional(), runtime: z.string().optional(), maxDevices: z.number().default(20), }, ...DEFER_LOADING_CONFIG,
  • TypeScript interface for tool input arguments used in type casting within handler.
    interface SimctlGetDetailsArgs { cacheId: string; detailType: 'full-list' | 'devices-only' | 'runtimes-only' | 'available-only'; deviceType?: string; runtime?: string; maxDevices?: number; }
  • Core helper function that applies deviceType and runtime filters to the full simulator list data.
    function applyFilters( fullList: CachedSimulatorList, filters: { deviceType?: string; runtime?: string; maxDevices?: number } ): CachedSimulatorList { const filtered: CachedSimulatorList = { devices: {}, runtimes: fullList.runtimes, devicetypes: fullList.devicetypes, lastUpdated: fullList.lastUpdated, preferredByProject: fullList.preferredByProject, }; // Filter device types if specified if (filters.deviceType) { filtered.devicetypes = fullList.devicetypes.filter(dt => dt.name.toLowerCase().includes(filters.deviceType!.toLowerCase()) ); } // Filter runtimes if specified if (filters.runtime) { filtered.runtimes = fullList.runtimes.filter( rt => rt.name.toLowerCase().includes(filters.runtime!.toLowerCase()) || rt.version.includes(filters.runtime!) ); } // Filter devices for (const [runtimeKey, devices] of Object.entries(fullList.devices)) { // Skip runtime if it doesn't match filter if (filters.runtime && !runtimeKey.toLowerCase().includes(filters.runtime.toLowerCase())) { continue; } const filteredDevices = devices.filter(device => { // Filter by device type if ( filters.deviceType && !device.name.toLowerCase().includes(filters.deviceType.toLowerCase()) ) { return false; } return true; }); if (filteredDevices.length > 0) { filtered.devices[runtimeKey] = filteredDevices; } } return filtered; }

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/conorluddy/xc-mcp'

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