mcp-xcode
Version:
MCP server that wraps Xcode command-line tools for iOS/macOS development workflows
114 lines • 4.61 kB
JavaScript
import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js';
import { simulatorCache } from '../../state/simulator-cache.js';
import { responseCache, extractSimulatorSummary, createProgressiveSimulatorResponse, } from '../../utils/response-cache.js';
export async function simctlListTool(args) {
const { deviceType, runtime, availability = 'available', outputFormat = 'json', concise = true, } = args;
try {
// Use the new caching system
const cachedList = await simulatorCache.getSimulatorList();
let responseData;
// Use progressive disclosure by default (concise=true)
if (concise && outputFormat === 'json') {
// Generate concise summary
const summary = extractSimulatorSummary(cachedList);
// Store full output in response cache
const cacheId = responseCache.store({
tool: 'simctl-list',
fullOutput: JSON.stringify(cachedList, null, 2),
stderr: '',
exitCode: 0,
command: 'simctl list -j',
metadata: {
totalDevices: summary.totalDevices,
availableDevices: summary.availableDevices,
filters: { deviceType, runtime, availability },
summary,
},
});
// Return progressive disclosure response
responseData = createProgressiveSimulatorResponse(summary, cacheId, {
deviceType,
runtime,
availability,
});
}
else {
// Legacy mode: return full filtered list
if (outputFormat === 'json') {
// Apply filters if specified
const filteredList = filterCachedSimulatorList(cachedList, {
deviceType,
runtime,
availability,
});
responseData = filteredList;
}
else {
// For text format, we need to convert back to original format
responseData =
`Simulator List (cached at ${cachedList.lastUpdated.toISOString()}):\n` +
JSON.stringify(cachedList, null, 2);
}
}
const responseText = outputFormat === 'json' ? JSON.stringify(responseData, null, 2) : responseData;
return {
content: [
{
type: 'text',
text: responseText,
},
],
};
}
catch (error) {
if (error instanceof McpError) {
throw error;
}
throw new McpError(ErrorCode.InternalError, `simctl-list failed: ${error instanceof Error ? error.message : String(error)}`);
}
}
function filterCachedSimulatorList(list, filters) {
const filtered = {
devices: {},
runtimes: list.runtimes,
devicetypes: list.devicetypes,
lastUpdated: list.lastUpdated,
preferredByProject: list.preferredByProject,
};
// Filter device types if specified
if (filters.deviceType) {
filtered.devicetypes = list.devicetypes.filter(dt => dt.name.toLowerCase().includes(filters.deviceType.toLowerCase()));
}
// Filter runtimes if specified
if (filters.runtime) {
filtered.runtimes = list.runtimes.filter(rt => rt.name.toLowerCase().includes(filters.runtime.toLowerCase()) ||
rt.version.includes(filters.runtime));
}
// Filter devices
for (const [runtimeKey, devices] of Object.entries(list.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;
}
// Filter by availability
if (filters.availability === 'available' && !device.isAvailable) {
return false;
}
if (filters.availability === 'unavailable' && device.isAvailable) {
return false;
}
return true;
});
if (filteredDevices.length > 0) {
filtered.devices[runtimeKey] = filteredDevices;
}
}
return filtered;
}
//# sourceMappingURL=list.js.map