Skip to main content
Glama

scaffold_macos_project

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

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
projectNameYesName of the new project
outputPathYesPath where the project should be created
bundleIdentifierNoBundle identifier (e.g., com.example.myapp). If not provided, will use com.example.projectname
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
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

Implementation Reference

  • The async handler function registered for 'scaffold_macos_project' that handles parameters, calls the core scaffoldProject function, formats success/error responses, and returns MCP content.
    async (params) => {
      try {
        const projectParams: ScaffoldProjectParams = { ...params, platform: 'macOS' };
        const projectPath = await scaffoldProject(projectParams);
    
        const response = {
          success: true,
          projectPath,
          platform: 'macOS',
          message: `Successfully scaffolded macOS project "${params.projectName}" at ${projectPath}`,
          nextSteps: [
            `Open the project: open ${projectPath}/${params.customizeNames ? params.projectName : 'MyProject'}.xcworkspace`,
            `Build for macOS: build_mac_ws --workspace-path "${projectPath}/${params.customizeNames ? params.projectName : 'MyProject'}.xcworkspace" --scheme "${params.customizeNames ? params.projectName : 'MyProject'}"`,
            `Run and run on macOS: build_run_mac_ws --workspace-path "${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,
              ),
            },
          ],
        };
      }
  • macOS-specific Zod schema for scaffold_macos_project parameters, extending the base schema with deploymentTarget.
    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'),
    });
  • Registration of the 'scaffold_macos_project' tool using registerTool, specifying name, description, and schema.
    registerTool<ScaffoldmacOSProjectParams>(
      server,
      'scaffold_macos_project',
      'Scaffold a new macOS project from templates. Creates a modern Xcode project with workspace structure, SPM package for features, and proper macOS configuration.',
      ScaffoldmacOSProjectSchema.shape,
  • Core helper function that performs the actual project scaffolding: validates params, gets template, processes directory recursively, handles cleanup.
    async function scaffoldProject(params: ScaffoldProjectParams): Promise<string> {
      const { projectName, outputPath, platform, customizeNames = true } = params;
    
      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: string;
      try {
        templatePath = await TemplateManager.getTemplatePath(platform);
      } catch (error) {
        throw new ValidationError(
          `Failed to get template for ${platform}: ${error instanceof Error ? error.message : String(error)}`,
        );
      }
    
      // Create output directory
      const projectPath = join(outputPath, customizeNames ? projectName : 'MyProject');
    
      if (existsSync(projectPath)) {
        throw new ValidationError(`Project directory already exists at ${projectPath}`);
      }
    
      try {
        // Process the template
        await processDirectory(templatePath, projectPath, params);
    
        return projectPath;
      } finally {
        // Clean up downloaded template if needed
        await TemplateManager.cleanup(templatePath);
      }
    }
  • Helper function to update .xcconfig files with project parameters, bundle ID, versions, deployment targets, orientations, and platform-specific settings.
    function updateXCConfigFile(content: string, params: ScaffoldProjectParams): string {
      let result = content;
    
      // Update project identity settings
      result = result.replace(/PRODUCT_NAME = .+/g, `PRODUCT_NAME = ${params.projectName}`);
      result = result.replace(
        /PRODUCT_DISPLAY_NAME = .+/g,
        `PRODUCT_DISPLAY_NAME = ${params.displayName || params.projectName}`,
      );
      result = result.replace(
        /PRODUCT_BUNDLE_IDENTIFIER = .+/g,
        `PRODUCT_BUNDLE_IDENTIFIER = ${params.bundleIdentifier || `com.example.${params.projectName.toLowerCase().replace(/[^a-z0-9]/g, '')}`}`,
      );
      result = result.replace(
        /MARKETING_VERSION = .+/g,
        `MARKETING_VERSION = ${params.marketingVersion || '1.0'}`,
      );
      result = result.replace(
        /CURRENT_PROJECT_VERSION = .+/g,
        `CURRENT_PROJECT_VERSION = ${params.currentProjectVersion || '1'}`,
      );
    
      // Platform-specific updates
      if (params.platform === 'iOS') {
        const iosParams = params as ScaffoldiOSProjectParams & { platform: 'iOS' };
    
        // iOS deployment target
        if (iosParams.deploymentTarget) {
          result = result.replace(
            /IPHONEOS_DEPLOYMENT_TARGET = .+/g,
            `IPHONEOS_DEPLOYMENT_TARGET = ${iosParams.deploymentTarget}`,
          );
        }
    
        // Device family
        if (iosParams.targetedDeviceFamily) {
          const deviceFamilyValue = deviceFamilyToNumeric(iosParams.targetedDeviceFamily);
          result = result.replace(
            /TARGETED_DEVICE_FAMILY = .+/g,
            `TARGETED_DEVICE_FAMILY = ${deviceFamilyValue}`,
          );
        }
    
        // iPhone orientations
        if (iosParams.supportedOrientations && iosParams.supportedOrientations.length > 0) {
          // Filter out any empty strings and validate
          const validOrientations = iosParams.supportedOrientations.filter((o) => o && o.trim() !== '');
          if (validOrientations.length > 0) {
            const orientations = validOrientations.map(orientationToIOSConstant).join(' ');
            result = result.replace(
              /INFOPLIST_KEY_UISupportedInterfaceOrientations = .+/g,
              `INFOPLIST_KEY_UISupportedInterfaceOrientations = ${orientations}`,
            );
          }
        }
    
        // iPad orientations
        if (iosParams.supportedOrientationsIpad && iosParams.supportedOrientationsIpad.length > 0) {
          // Filter out any empty strings and validate
          const validOrientations = iosParams.supportedOrientationsIpad.filter(
            (o) => o && o.trim() !== '',
          );
          if (validOrientations.length > 0) {
            const orientations = validOrientations.map(orientationToIOSConstant).join(' ');
            result = result.replace(
              /INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = .+/g,
              `INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = ${orientations}`,
            );
          }
        }
      } else if (params.platform === 'macOS') {
        const macosParams = params as ScaffoldmacOSProjectParams & { platform: 'macOS' };
    
        // macOS deployment target
        if (macosParams.deploymentTarget) {
          result = result.replace(
            /MACOSX_DEPLOYMENT_TARGET = .+/g,
            `MACOSX_DEPLOYMENT_TARGET = ${macosParams.deploymentTarget}`,
          );
        }
    
        // Update entitlements path for macOS
        result = result.replace(
          /CODE_SIGN_ENTITLEMENTS = .+/g,
          `CODE_SIGN_ENTITLEMENTS = ${params.projectName}/${params.projectName}.entitlements`,
        );
      }
    
      // Update test bundle identifier and target name
      result = result.replace(/TEST_TARGET_NAME = .+/g, `TEST_TARGET_NAME = ${params.projectName}`);
    
      return result;
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It states the tool creates files and configures a project, implying mutation, but does not disclose critical behaviors such as whether it overwrites existing files, requires specific permissions, or has side effects like modifying system settings. The description adds some context but leaves significant gaps for a creation tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences, front-loaded with the core purpose and followed by specific outcomes. Every word earns its place with no redundancy or fluff, making it highly efficient and easy to scan.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (creation of a project with multiple configurations), no annotations, and no output schema, the description is adequate but incomplete. It covers the purpose and high-level outcome but lacks details on behavioral traits, error handling, or output format, which are important for a mutation tool with no structured safety hints.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema description coverage is 100%, so the schema already documents all 8 parameters with descriptions and defaults. The description does not add any parameter-specific information beyond what the schema provides, such as examples or constraints not in the schema. Baseline 3 is appropriate as the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the specific action ('scaffold'), target ('new macOS project'), and method ('from templates'), distinguishing it from sibling tools like 'scaffold_ios_project' and various build/clean tools. It specifies the outcome: 'Creates a modern Xcode project with workspace structure, SPM package for features, and proper macOS configuration.'

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for creating new macOS projects from templates, but does not explicitly state when to use this tool versus alternatives like 'scaffold_ios_project' for iOS or 'build_mac_proj' for building existing projects. It provides context but lacks explicit exclusions or named alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other 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/SampsonKY/XcodeBuildMCP'

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