Skip to main content
Glama

scaffold_macos_project

Quickly generate a structured macOS Xcode project with workspace, SPM package, and proper configuration. Specify project name, output path, bundle ID, display name, and deployment target for customization.

Instructions

Scaffold a new macOS project from templates. Creates a modern Xcode project with workspace structure, SPM package for features, and proper macOS configuration.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
bundleIdentifierNoBundle identifier (e.g., com.example.myapp). If not provided, will use com.example.projectname
currentProjectVersionNoBuild number (e.g., 1, 42, 100). If not provided, will use 1
customizeNamesNoWhether to customize project names and identifiers. Default is true.
deploymentTargetNomacOS deployment target (e.g., 15.4, 14.0). If not provided, will use 15.4
displayNameNoApp display name (shown on home screen/dock). If not provided, will use projectName
marketingVersionNoMarketing version (e.g., 1.0, 2.1.3). If not provided, will use 1.0
outputPathYesPath where the project should be created
projectNameYesName of the new project

Implementation Reference

  • Core handler function `scaffold_macos_projectLogic` that orchestrates project scaffolding, template processing, error handling, and response generation for the `scaffold_macos_project` tool.
    export async function scaffold_macos_projectLogic( params: ScaffoldMacOSProjectParams, commandExecutor: CommandExecutor, fileSystemExecutor: FileSystemExecutor = getDefaultFileSystemExecutor(), ): Promise<ToolResponse> { try { const projectParams = { ...params, platform: 'macOS' as const }; const projectPath = await scaffoldProject(projectParams, commandExecutor, fileSystemExecutor); const response = { success: true, projectPath, platform: 'macOS', message: `Successfully scaffolded macOS project "${params.projectName}" in ${projectPath}`, nextSteps: [ `Important: Before working on the project make sure to read the README.md file in the workspace root directory.`, `Build for macOS: build_macos({ workspacePath: "${projectPath}/${params.customizeNames ? params.projectName : 'MyProject'}.xcworkspace", scheme: "${params.customizeNames ? params.projectName : 'MyProject'}" })`, `Build & Run on macOS: build_run_macos({ workspacePath: "${projectPath}/${params.customizeNames ? params.projectName : 'MyProject'}.xcworkspace", scheme: "${params.customizeNames ? params.projectName : 'MyProject'}" })`, ], }; return { content: [ { type: 'text', text: JSON.stringify(response, null, 2), }, ], }; } catch (error) { log( 'error', `Failed to scaffold macOS project: ${error instanceof Error ? error.message : String(error)}`, ); return { content: [ { type: 'text', text: JSON.stringify( { success: false, error: error instanceof Error ? error.message : 'Unknown error occurred', }, null, 2, ), }, ], isError: true, }; } }
  • Zod schema definitions: `BaseScaffoldSchema` (shared with iOS) and `ScaffoldmacOSProjectSchema` (macOS-specific with deploymentTarget) for input validation.
    const BaseScaffoldSchema = z.object({ projectName: z.string().min(1).describe('Name of the new project'), outputPath: z.string().describe('Path where the project should be created'), bundleIdentifier: z .string() .optional() .describe( 'Bundle identifier (e.g., com.example.myapp). If not provided, will use com.example.projectname', ), displayName: z .string() .optional() .describe( 'App display name (shown on home screen/dock). If not provided, will use projectName', ), marketingVersion: z .string() .optional() .describe('Marketing version (e.g., 1.0, 2.1.3). If not provided, will use 1.0'), currentProjectVersion: z .string() .optional() .describe('Build number (e.g., 1, 42, 100). If not provided, will use 1'), customizeNames: z .boolean() .default(true) .describe('Whether to customize project names and identifiers. Default is true.'), }); // macOS-specific schema const ScaffoldmacOSProjectSchema = BaseScaffoldSchema.extend({ deploymentTarget: z .string() .optional() .describe('macOS deployment target (e.g., 15.4, 14.0). If not provided, will use 15.4'), });
  • Default export object that registers the `scaffold_macos_project` tool, including name, description, schema reference, and handler that validates inputs and delegates to the core logic function.
    export default { name: 'scaffold_macos_project', description: 'Scaffold a new macOS project from templates. Creates a modern Xcode project with workspace structure, SPM package for features, and proper macOS configuration.', schema: ScaffoldmacOSProjectSchema.shape, async handler(args: Record<string, unknown>): Promise<ToolResponse> { // Validate the arguments against the schema before processing const validatedArgs = ScaffoldmacOSProjectSchema.parse(args); return scaffold_macos_projectLogic( validatedArgs, getDefaultCommandExecutor(), getDefaultFileSystemExecutor(), ); }, };
  • Key helper function `scaffoldProject` that handles template retrieval, validation, directory processing, and cleanup for scaffolding the project structure.
    async function scaffoldProject( params: ScaffoldMacOSProjectParams & { platform: string }, commandExecutor: CommandExecutor, fileSystemExecutor: FileSystemExecutor, ): Promise<string> { const projectName = params.projectName; const outputPath = params.outputPath; const platform = params.platform; const customizeNames = params.customizeNames ?? true; log('info', `Scaffolding project: ${projectName} (${platform}) at ${outputPath}`); // Validate project name if (!/^[a-zA-Z][a-zA-Z0-9_]*$/.test(projectName)) { throw new ValidationError( 'Project name must start with a letter and contain only letters, numbers, and underscores', ); } // Get template path from TemplateManager let templatePath; try { templatePath = await TemplateManager.getTemplatePath( platform as 'macOS' | 'iOS', commandExecutor, fileSystemExecutor, ); } catch (error) { throw new ValidationError( `Failed to get template for ${platform}: ${error instanceof Error ? error.message : String(error)}`, ); } // Use outputPath directly as the destination const projectPath = outputPath; // Check if the output directory already has Xcode project files const xcworkspaceExists = fileSystemExecutor.existsSync( join(projectPath, `${customizeNames ? projectName : 'MyProject'}.xcworkspace`), ); const xcodeprojExists = fileSystemExecutor.existsSync( join(projectPath, `${customizeNames ? projectName : 'MyProject'}.xcodeproj`), ); if (xcworkspaceExists || xcodeprojExists) { throw new ValidationError(`Xcode project files already exist in ${projectPath}`); } try { // Process the template directly into the output path await processDirectory(templatePath, projectPath, params, fileSystemExecutor); return projectPath; } finally { // Clean up downloaded template if needed await TemplateManager.cleanup(templatePath, fileSystemExecutor); } }
  • Recursive helper `processDirectory` that traverses the template directory, customizes names, processes files with placeholders, and copies structure to output.
    async function processDirectory( sourceDir: string, destDir: string, params: ScaffoldMacOSProjectParams & { platform: string }, fileSystemExecutor: FileSystemExecutor, ): Promise<void> { const entries = await fileSystemExecutor.readdir(sourceDir, { withFileTypes: true }); for (const entry of entries) { const dirent = entry as { isDirectory(): boolean; isFile(): boolean; name: string }; const sourcePath = join(sourceDir, dirent.name); let destName = dirent.name; if (params.customizeNames) { // Replace MyProject in directory names destName = destName.replace(/MyProject/g, params.projectName); } const destPath = join(destDir, destName); if (dirent.isDirectory()) { // Skip certain directories if (dirent.name === '.git' || dirent.name === 'xcuserdata') { continue; } await fileSystemExecutor.mkdir(destPath, { recursive: true }); await processDirectory(sourcePath, destPath, params, fileSystemExecutor); } else if (dirent.isFile()) { // Skip certain files if (dirent.name === '.DS_Store' || dirent.name.endsWith('.xcuserstate')) { continue; } await processFile(sourcePath, destPath, params, fileSystemExecutor); } } }

Other Tools

Related Tools

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/cameroncooke/XcodeBuildMCP'

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