Skip to main content
Glama

build_run_mac_proj

Build and run macOS applications from Xcode project files in a single command, specifying scheme and configuration options.

Instructions

Builds and runs a macOS app from a project file in one step.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
projectPathYesPath to the .xcodeproj file (Required)
schemeYesThe scheme to use (Required)
configurationNoBuild configuration (Debug, Release, etc.)
derivedDataPathNoPath where build products and other derived data will go
extraArgsNoAdditional xcodebuild arguments
preferXcodebuildNoIf true, prefers xcodebuild over the experimental incremental build system, useful for when incremental build system fails.

Implementation Reference

  • Core handler function for the 'build_run_mac_proj' tool. Builds the macOS project using xcodebuild, extracts the app path from build settings, and launches the app using the 'open' command.
    async function _handleMacOSBuildAndRunLogic(params: { workspacePath?: string; projectPath?: string; scheme: string; configuration: string; derivedDataPath?: string; arch?: string; extraArgs?: string[]; preferXcodebuild?: boolean; }): Promise<ToolResponse> { log('info', 'Handling macOS build & run logic...'); const _warningMessages: { type: 'text'; text: string }[] = []; const _warningRegex = /\[warning\]: (.*)/g; try { // First, build the app const buildResult = await _handleMacOSBuildLogic(params); // 1. Check if the build itself failed if (buildResult.isError) { return buildResult; // Return build failure directly } const buildWarningMessages = buildResult.content?.filter((c) => c.type === 'text') ?? []; // 2. Build succeeded, now get the app path using the helper const appPathResult = await _getAppPathFromBuildSettings(params); // 3. Check if getting the app path failed if (!appPathResult.success) { log('error', 'Build succeeded, but failed to get app path to launch.'); const response = createTextResponse( `✅ Build succeeded, but failed to get app path to launch: ${appPathResult.error}`, false, // Build succeeded, so not a full error ); if (response.content) { response.content.unshift(...buildWarningMessages); } return response; } const appPath = appPathResult.appPath; // We know this is a valid string now log('info', `App path determined as: ${appPath}`); // 4. Launch the app using the verified path // Launch the app try { await promisify(exec)(`open "${appPath}"`); log('info', `✅ macOS app launched successfully: ${appPath}`); const successResponse: ToolResponse = { content: [ ...buildWarningMessages, { type: 'text', text: `✅ macOS build and run succeeded for scheme ${params.scheme}. App launched: ${appPath}`, }, ], }; return successResponse; } catch (launchError) { const errorMessage = launchError instanceof Error ? launchError.message : String(launchError); log('error', `Build succeeded, but failed to launch app ${appPath}: ${errorMessage}`); const errorResponse = createTextResponse( `✅ Build succeeded, but failed to launch app ${appPath}. Error: ${errorMessage}`, false, // Build succeeded ); if (errorResponse.content) { errorResponse.content.unshift(...buildWarningMessages); } return errorResponse; } } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); log('error', `Error during macOS build & run logic: ${errorMessage}`); const errorResponse = createTextResponse( `Error during macOS build and run: ${errorMessage}`, true, ); return errorResponse; } }
  • Direct registration of the 'build_run_mac_proj' tool, defining its name, description, input schema, and handler function.
    // Register macOS build and run project tool export function registerMacOSBuildAndRunProjectTool(server: McpServer): void { type ProjectParams = { projectPath: string; scheme: string; configuration?: string; derivedDataPath?: string; arch?: string; extraArgs?: string[]; preferXcodebuild?: boolean; }; registerTool<ProjectParams>( server, 'build_run_mac_proj', 'Builds and runs a macOS app from a project file in one step.', { projectPath: projectPathSchema, scheme: schemeSchema, configuration: configurationSchema, derivedDataPath: derivedDataPathSchema, extraArgs: extraArgsSchema, preferXcodebuild: preferXcodebuildSchema, }, async (params) => _handleMacOSBuildAndRunLogic({ ...params, configuration: params.configuration ?? 'Debug', preferXcodebuild: params.preferXcodebuild ?? false, }), ); }
  • Private helper that executes the xcodebuild 'build' action for macOS targets.
    async function _handleMacOSBuildLogic(params: { workspacePath?: string; projectPath?: string; scheme: string; configuration: string; derivedDataPath?: string; arch?: string; extraArgs?: string[]; preferXcodebuild?: boolean; }): Promise<ToolResponse> { log('info', `Starting macOS build for scheme ${params.scheme} (internal)`); return executeXcodeBuildCommand( { ...params, }, { platform: XcodePlatform.macOS, arch: params.arch, logPrefix: 'macOS Build', }, params.preferXcodebuild, 'build', ); }
  • Private helper that runs 'xcodebuild -showBuildSettings' to parse and return the built app's path.
    async function _getAppPathFromBuildSettings(params: { workspacePath?: string; projectPath?: string; scheme: string; configuration: string; derivedDataPath?: string; arch?: string; extraArgs?: string[]; }): Promise<{ success: boolean; appPath?: string; error?: string }> { try { // Create the command array for xcodebuild const command = ['xcodebuild', '-showBuildSettings']; // Add the workspace or project if (params.workspacePath) { command.push('-workspace', params.workspacePath); } else if (params.projectPath) { command.push('-project', params.projectPath); } // Add the scheme and configuration command.push('-scheme', params.scheme); command.push('-configuration', params.configuration); // Add derived data path if provided if (params.derivedDataPath) { command.push('-derivedDataPath', params.derivedDataPath); } // Add extra args if provided if (params.extraArgs && params.extraArgs.length > 0) { command.push(...params.extraArgs); } // Execute the command directly const result = await executeCommand(command, 'Get Build Settings for Launch'); if (!result.success) { return { success: false, error: result.error || 'Failed to get build settings', }; } // Parse the output to extract the app path const buildSettingsOutput = result.output; const builtProductsDirMatch = buildSettingsOutput.match(/BUILT_PRODUCTS_DIR = (.+)$/m); const fullProductNameMatch = buildSettingsOutput.match(/FULL_PRODUCT_NAME = (.+)$/m); if (!builtProductsDirMatch || !fullProductNameMatch) { return { success: false, error: 'Could not extract app path from build settings' }; } const appPath = `${builtProductsDirMatch[1].trim()}/${fullProductNameMatch[1].trim()}`; return { success: true, appPath }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); return { success: false, error: errorMessage }; } }
  • Invocation of the tool's registration function in the central tool registry array, enabling it conditionally via environment variable.
    { register: registerMacOSBuildAndRunProjectTool, groups: [ToolGroup.MACOS_WORKFLOW, ToolGroup.APP_DEPLOYMENT], envVar: 'XCODEBUILDMCP_TOOL_MACOS_BUILD_AND_RUN_PROJECT', },
  • Zod-based input schema definition for the 'build_run_mac_proj' tool parameters.
    { projectPath: projectPathSchema, scheme: schemeSchema, configuration: configurationSchema, derivedDataPath: derivedDataPathSchema, extraArgs: extraArgsSchema, preferXcodebuild: preferXcodebuildSchema, },

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