Skip to main content
Glama

MCP Xcode

by Stefan-Nitu
index.ts5.18 kB
#!/usr/bin/env node /** * MCP Xcode Server * Provides tools for building, running, and testing Apple platform projects */ import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema, } from '@modelcontextprotocol/sdk/types.js'; import { logger, logToolExecution, logError } from './logger.js'; // Import all tool classes // import { // ListSimulatorsTool, // BootSimulatorTool, // ShutdownSimulatorTool, // ViewSimulatorScreenTool, // BuildSwiftPackageTool, // RunSwiftPackageTool, // RunXcodeTool, // TestXcodeTool, // TestSwiftPackageTool, // CleanBuildTool, // ArchiveProjectTool, // ExportIPATool, // ListSchemesTool, // GetBuildSettingsTool, // GetProjectInfoTool, // ListTargetsTool, // InstallAppTool, // UninstallAppTool, // GetDeviceLogsTool, // ManageDependenciesTool // } from './tools/index.js'; // Import factories for Clean Architecture controllers import { BootSimulatorControllerFactory, ShutdownSimulatorControllerFactory, ListSimulatorsControllerFactory } from './features/simulator/index.js'; import { BuildXcodeControllerFactory } from './features/build/index.js'; import { InstallAppControllerFactory } from './features/app-management/index.js'; type Tool = { execute(args: any): Promise<any>; getToolDefinition(): any; }; class XcodeServer { private server: Server; private tools: Map<string, Tool>; constructor() { this.server = new Server( { name: 'mcp-xcode-server', version: '2.4.0', }, { capabilities: { tools: {}, }, } ); // Initialize all tools this.tools = new Map<string, Tool>(); this.registerTools(); this.setupHandlers(); } private registerTools() { // Create instances of all tools const toolInstances = [ // Simulator management ListSimulatorsControllerFactory.create(), BootSimulatorControllerFactory.create(), ShutdownSimulatorControllerFactory.create(), // new ViewSimulatorScreenTool(), // Build and test // new BuildSwiftPackageTool(), // new RunSwiftPackageTool(), BuildXcodeControllerFactory.create(), InstallAppControllerFactory.create(), // new RunXcodeTool(), // new TestXcodeTool(), // new TestSwiftPackageTool(), // new CleanBuildTool(), // Archive and export // new ArchiveProjectTool(), // new ExportIPATool(), // Project info and schemes // new ListSchemesTool(), // new GetBuildSettingsTool(), // new GetProjectInfoTool(), // new ListTargetsTool(), // App management // new InstallAppTool(), // new UninstallAppTool(), // Device logs // new GetDeviceLogsTool(), // Advanced project management // new ManageDependenciesTool() ]; // Register each tool by its name for (const tool of toolInstances) { const definition = tool.getToolDefinition(); this.tools.set(definition.name, tool); } logger.info({ toolCount: this.tools.size }, 'Tools registered'); } private setupHandlers() { // Handle listing all available tools this.server.setRequestHandler(ListToolsRequestSchema, async () => { const tools = Array.from(this.tools.values()).map(tool => tool.getToolDefinition()); return { tools }; }); // Handle tool execution this.server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; const startTime = Date.now(); logger.debug({ tool: name, args }, 'Tool request received'); try { const tool = this.tools.get(name); if (!tool) { throw new Error(`Unknown tool: ${name}`); } const result = await tool.execute(args); // Log successful execution logToolExecution(name, args, Date.now() - startTime); return result; } catch (error: any) { logError(error as Error, { tool: name, args }); return { content: [ { type: 'text', text: `Error: ${error instanceof Error ? error.message : String(error)}` } ] }; } }); } async run() { const transport = new StdioServerTransport(); await this.server.connect(transport); logger.info({ transport: 'stdio' }, 'MCP Xcode server started'); } } const server = new XcodeServer(); // Handle graceful shutdown process.on('SIGTERM', async () => { logger.info('Received SIGTERM, shutting down gracefully'); // Give logger time to flush await new Promise(resolve => setTimeout(resolve, 100)); process.exit(0); }); process.on('SIGINT', async () => { logger.info('Received SIGINT, shutting down gracefully'); // Give logger time to flush await new Promise(resolve => setTimeout(resolve, 100)); process.exit(0); }); server.run().catch((error) => { logger.fatal({ error }, 'Failed to start MCP server'); process.exit(1); });

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/Stefan-Nitu/mcp-xcode'

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