xcode_refresh_project
Refresh Xcode projects to detect external file changes by closing and reopening the project file.
Instructions
Refresh/reload an Xcode project by closing and reopening it to pick up external changes like modified .xctestplan files
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| xcodeproj | Yes | Absolute path to the .xcodeproj file (or .xcworkspace if available) to refresh |
Implementation Reference
- src/XcodeServer.ts:624-636 (handler)Main handler logic for the xcode_refresh_project tool. Validates input, closes the project, reopens it to refresh, and returns status.case 'xcode_refresh_project': if (!args.xcodeproj) { throw new McpError(ErrorCode.InvalidParams, `Missing required parameter: xcodeproj`); } // Close and reopen the project to refresh it await ProjectTools.closeProject(args.xcodeproj as string); const refreshResult = await ProjectTools.openProjectAndWaitForLoad(args.xcodeproj as string); return { content: [{ type: 'text', text: `Project refreshed: ${refreshResult.content?.[0]?.type === 'text' ? refreshResult.content[0].text : 'Completed'}` }] };
- Tool schema definition including input validation schema, used for tool registration and listTools response.name: 'xcode_refresh_project', description: 'Refresh/reload an Xcode project by closing and reopening it to pick up external changes like modified .xctestplan files', inputSchema: { type: 'object', properties: { xcodeproj: { type: 'string', description: 'Absolute path to the .xcodeproj file (or .xcworkspace if available) to refresh', }, }, required: ['xcodeproj'], }, },
- src/tools/ProjectTools.ts:281-308 (helper)Helper function to close the Xcode project using JXA scripting, called by the refresh handler.public static async closeProject(projectPath: string): Promise<McpResult> { // Simplified close project to prevent crashes - just close without complex error handling const closeScript = ` (function() { try { ${getWorkspaceByPathScript(projectPath)} if (!workspace) { return 'No workspace to close (already closed)'; } // Simple close (no options) to align with test mocks and avoid dialogs workspace.close(); return 'Project close initiated'; } catch (error) { return 'Close completed (may have had dialogs): ' + error.message; } })() `; try { const result = await JXAExecutor.execute(closeScript); return { content: [{ type: 'text', text: result }] }; } catch (error) { // Even if JXA fails, consider it successful to prevent crashes const errorMessage = error instanceof Error ? error.message : String(error); return { content: [{ type: 'text', text: `Project close completed with issues: ${errorMessage}` }] }; } }
- src/tools/ProjectTools.ts:230-279 (helper)Helper function to open the Xcode project and wait for it to fully load, called by the refresh handler.public static async openProjectAndWaitForLoad(projectPath: string): Promise<McpResult> { // First check if project is already open and loaded try { const checkScript = ` (function() { try { ${getWorkspaceByPathScript(projectPath)} if (!workspace) { return JSON.stringify({ isOpen: false }); } // Check if it's the right project const workspacePath = workspace.path(); if (workspacePath === ${JSON.stringify(projectPath)}) { // Try to access schemes to see if it's fully loaded const schemes = workspace.schemes(); return JSON.stringify({ isOpen: true, isLoaded: schemes.length > 0 }); } return JSON.stringify({ isOpen: false, differentProject: workspacePath }); } catch (error) { return JSON.stringify({ isOpen: false, error: error.message }); } })() `; const result = await JXAExecutor.execute(checkScript); const status = JSON.parse(result); if (status.isOpen && status.isLoaded) { return { content: [{ type: 'text', text: 'Project is already open and loaded' }] }; } } catch (error) { // Continue with opening the project } // Open the project const openResult = await this.openProject(projectPath); if (openResult.content?.[0]?.type === 'text' && openResult.content[0].text.includes('Error')) { return openResult; } // Wait for the project to load const waitResult = await this.waitForProjectToLoad(projectPath); if (waitResult) { return waitResult; } return { content: [{ type: 'text', text: 'Project opened and loaded successfully' }] }; }