Skip to main content
Glama
xcode-mcp-server (drewster99)

xcode-mcp-server (drewster99)

by drewster99

Drew's Xcode MCP Server (drews-xcode-mcp)

PyPI Python Versions Downloads MCP macOS Only Xcode License: MIT

GitHub last commit

An MCP (Model Context Protocol) server that enables AI assistants to control and interact with Xcode for Apple platform development.

Renamed from xcode-mcp-server. With several unrelated projects sharing that name — and Xcode itself now shipping a built-in MCP server — this project is now drews-xcode-mcp. Existing setups keep working: the old PyPI name is a compatibility package that forwards to this one, and all settings carry over. When convenient, update your MCP configuration to run drews-xcode-mcp. If your server key/name is the old default xcode-mcp-server, we recommend renaming it to drews-xcode-mcp too — just remember to update any tool permission allowlists referencing the old tool names (mcp__xcode-mcp-server__* becomes mcp__drews-xcode-mcp__*). If you chose a custom key, keep it and tool permissions are unaffected.

What It Does

This server allows AI assistants (like Claude, Cursor, or other MCP clients) to:

  • Discover and navigate your Xcode projects and source files

  • Build and run iOS, macOS, tvOS, and watchOS applications

  • Execute and monitor tests with detailed results

  • Debug build failures by retrieving errors and warnings

  • Capture console output from running applications

  • Take screenshots of Xcode windows and iOS simulators

  • Manage simulators and view their status

The AI can perform complete development workflows - from finding a project, to building it, running tests, debugging failures, and capturing results.

Related MCP server: Xcode Diagnostics MCP Plugin

Requirements

  • macOS - This server only works on macOS

  • Xcode - Xcode must be installed

  • Python 3.10+ - For running the server (uvx will fetch a compatible Python automatically if your system Python is older)

Security

The server implements path-based security to control which directories are accessible:

  • With restrictions: Set XCODEMCP_ALLOWED_FOLDERS=/path1:/path2:/path3 to limit access to specific directories

  • Default: If not specified, allows access to your home directory ($HOME)

Security requirements:

  • All paths must be absolute (starting with /)

  • No .. path components allowed

  • All paths must exist and be directories

Setup

First, ensure uv is installed (required for all methods below):

which uv || brew install uv
claude mcp add --scope user --transport stdio -- drews-xcode-mcp `which uvx` drews-xcode-mcp

To run a specific version, use:

# Example: How to run v1.3.0b6
claude mcp add --scope user --transport stdio -- drews-xcode-mcp `which uvx` drews-xcode-mcp==1.3.0b6

That's it! Claude Code handles the rest automatically.

2. Claude Desktop

Edit your Claude Desktop config file (~/Library/Application Support/Claude/claude_desktop_config.json):

{
    "mcpServers": {
        "drews-xcode-mcp": {
            "command": "uvx",
            "args": [
                "drews-xcode-mcp"
            ]
        }
    }
}

If you'd like to allow only certain projects or folders to be accessible by drews-xcode-mcp, add the env option, with a colon-separated list of absolute folder paths, like this:

{
    "mcpServers": {
        "drews-xcode-mcp": {
            "command": "uvx",
            "args": [
                "drews-xcode-mcp"
            ],
            "env": {
                "XCODEMCP_ALLOWED_FOLDERS": "/Users/andrew/my_project:/Users/andrew/Documents/source"
            }
        }
    }
}

3. Cursor AI

In Cursor: Settings → Tools & Integrations → + New MCP Server

Or edit ~/.cursor/mcp.json directly:

{
    "mcpServers": {
        "drews-xcode-mcp": {
            "command": "uvx",
            "args": ["drews-xcode-mcp"]
        }
    }
}

Optional: Add folder restrictions with an env section (same format as Claude Desktop above).

Usage

Once configured, simply ask your AI assistant to help with Xcode tasks:

  • "Find all Xcode projects in my home directory"

  • "Build the project at /path/to/MyProject.xcodeproj"

  • "Run tests for this project and show me any failures"

  • "What are the build errors in this project?"

  • "Show me the directory structure of this project"

  • "Take a screenshot of the Xcode window"

Most tools work with paths to .xcodeproj or .xcworkspace files, or with regular directory paths for browsing and navigation.

Advanced Configuration

Command Line Arguments

When running the server directly (for development or custom setups), these options are available:

Build output control:

  • --no-build-warnings - Show only errors, exclude warnings

  • --always-include-build-warnings - Always show warnings (default)

Notifications:

  • --show-notifications - Enable macOS notifications for operations

  • --hide-notifications - Disable notifications (default)

Access control:

  • --allowed /path - Add allowed folder (can be repeated)

Example:

drews-xcode-mcp --no-build-warnings --show-notifications --allowed ~/Projects

Note: When using MCP clients (Claude, Cursor), configure these via the env section in your client's config file instead.

Development

The server is built with FastMCP and uses AppleScript to communicate with Xcode.

Local Testing

Test with MCP Inspector:

export XCODEMCP_ALLOWED_FOLDERS=~/Projects
mcp dev drews_xcode_mcp/__main__.py

This opens an inspector interface where you can test tools directly. Provide paths as quoted strings: "/Users/you/Projects/MyApp.xcodeproj"

Limitations

  • AppleScript syntax may need adjustments for specific Xcode versions

  • Some operations require the project to be open in Xcode first

Available Tools

29 tools
build_projectA
Destructive
Build the specified Xcode project or workspace.

Builds run for up to `timeout` seconds (default 600, i.e. 10 minutes) before
timing out, which guards against a build that hangs indefinitely. Raise it
for large projects whose cold build exceeds the default.

Args:
    project_path: Path to an Xcode project or workspace directory.
    scheme: Name of the scheme to build. If not provided, uses the active scheme.
    include_warnings: Include warnings in build output. If not provided, uses global setting.
    regex_filter: Optional regex to filter error/warning lines
    max_lines: Maximum number of error/warning lines to show (default 25)
    timeout: Maximum seconds to wait for the build to complete. If not
        provided, defaults to 600. Must be a positive integer.

Returns:
    Always returns JSON with format:
    {
        "full_log_path": "~/Library/Caches/xcode-mcp-server/logs/build-{hash}.txt",
        "summary": {"total_errors": N, "total_warnings": M, "showing_errors": X, "showing_warnings": Y},
        "errors_and_warnings": "Build failed with N errors...

error: ... ..." } The errors_and_warnings field contains a summary message followed by the actual errors/warnings. Errors are prioritized over warnings - errors are shown first, then warnings fill remaining slots.

Inputs: project_path (required), scheme, include_warnings, regex_filter, +2 more. Returns: result

clean_projectA
DestructiveIdempotent

Clean the specified Xcode project or workspace.

Args: project_path: Path to an Xcode project/workspace directory. timeout: Maximum seconds to wait for the clean to complete. If not provided, defaults to 600. Must be a positive integer.

Returns: Output message

Inputs: project_path (required), timeout. Returns: result

create_projectA

Create a new Xcode project with a SwiftUI app template.

Creates a complete, buildable Xcode project with a SwiftUI app entry point, ContentView, and asset catalog. The project uses the modern Xcode 16+ format (objectVersion 77) with automatic file discovery.

Args: parent_directory: Directory where the project folder will be created. Must be within the allowed folders configured for this server. project_name: Name of the project (e.g. "MyApp"). Used for the folder name, target name, and scheme name. platform: Target platform - "ios" or "macos" (case-insensitive). Defaults to "ios". bundle_identifier: Bundle identifier (e.g. "com.mycompany.MyApp"). Defaults to "com.example.{ProjectName}". deployment_target: Minimum deployment target version (e.g. "26.0"). Defaults to "26.0".

Returns: JSON string with project_path, project_directory, platform, bundle_identifier, and files_created.

Inputs: parent_directory (required), project_name (required), platform, bundle_identifier, +1 more. Returns: result

debug_list_notification_historyA
Read-onlyIdempotent

List all notifications that have been posted since the server started. This is a debugging tool to help understand notification behavior.

Returns: A formatted list of all notifications with timestamps, titles, messages, and subtitles.

Inputs: no named parameters. Returns: result

get_active_run_destinationA
Read-onlyIdempotent

Get the currently active run destination for a project.

Returns the device or simulator that Xcode will use for the next build or run operation. This reads from Xcode's workspace state file without opening the project in Xcode.

Note: After calling set_run_destination, Xcode may take several seconds to flush its state to disk. If called immediately after set_run_destination, this may return the previous destination.

Args: project_path: Path to an Xcode project (.xcodeproj) or workspace (.xcworkspace).

Returns: JSON with the active destination's name, platform, architecture, and id. Returns an error message if the active destination cannot be determined (e.g. the project has never been opened in Xcode).

Inputs: project_path (required). Returns: result

get_build_errorsA
Read-onlyIdempotent
Get the build errors from the last build for the specified Xcode project or workspace.

Args:
    project_path: Path to an Xcode project or workspace directory.
    include_warnings: Include warnings in output. If not provided, uses global setting.
    regex_filter: Optional regex to filter error/warning lines
    max_lines: Maximum number of error/warning lines to show (default 25)

Returns:
    If no build has been performed: Returns plain text message.
    Otherwise, returns JSON string with format:
    {
        "full_log_path": "~/Library/Caches/xcode-mcp-server/logs/build-{hash}.txt",
        "summary": {"total_errors": N, "total_warnings": M, "showing_errors": X, "showing_warnings": Y},
        "errors_and_warnings": "Build succeeded/failed with N errors...

error: ... ..." } Output is filtered using regex patterns to match compiler errors/warnings, with errors prioritized over warnings. Includes full unfiltered log file for complete analysis.

Inputs: project_path (required), include_warnings, regex_filter, max_lines. Returns: result

get_build_resultsA
Read-onlyIdempotent

Get aggregated build errors and warnings from all builds since the last clean operation.

This tool addresses the issue where incremental builds only show warnings for recompiled files. It parses the build log manifest (LogStoreManifest.plist) and aggregates warnings from all builds since the last clean, excluding warnings from files that were subsequently recompiled.

Strategy:

  1. Locate the project's DerivedData/Logs/Build directory

  2. Parse LogStoreManifest.plist to find all builds since last clean

  3. For each build, parse the .xcactivitylog file to extract:

    • Warnings and errors with file/line/column/message

    • List of files compiled in that build

  4. Aggregate warnings, keeping only the most recent warning for each file

  5. If a file was recompiled in a later build, use warnings from that later build

This ensures you see all current warnings even after incremental builds.

Args: project_path: Path to an Xcode project or workspace directory max_warnings: Maximum number of warnings to show in response (default 50)

Returns: JSON string with format: { "derived_data_path": "/path/to/DerivedData/...", "summary": { "total_builds": N, "builds_since_clean": M, "builds_analyzed": K, "clean_info": "...", "total_warnings": X, "warnings_by_type": {"warnings": W, "errors": E}, "unique_files_with_warnings": F, "files_recompiled_multiple_times": R }, "aggregated_warnings": [ { "file": "/path/to/File.swift", "line": 123, "column": 45, "message": "...", "type": "warning" } ], "files_with_multiple_builds": [ { "file": "/path/to/File.swift", "builds": 3, "warnings_excluded": 2 } ], "builds_analyzed": [ { "uuid": "...", "title": "Build FunVoice", "time": 782185536.0, "warnings_found": 4, "files_compiled": 26 } ] }

Note: Only the first max_warnings warnings are included in aggregated_warnings.
The summary counts reflect the total before limiting.

Inputs: project_path (required), max_warnings. Returns: result

get_directory_listingA
Read-onlyIdempotent

List contents of a directory with file metadata.

Args: directory_path: Path to directory to list regex_filter: Optional regex to filter filenames (applied to basename only) sort_by: Sort by "time" (modification time) or "name" (alphabetical). Default: "time" reverse: Reverse sort order. Default: True (most recent first / Z-A) max_results: Maximum entries to return (default 50, hard limit 100)

Returns: Formatted listing with: name, type (file/dir), size, modified time. Default behavior: 50 most recently modified files/folders. Format: "main.swift [file] 2.5 KB 2025-10-01 14:30"

Inputs: directory_path (required), regex_filter, sort_by, reverse, +1 more. Returns: result

get_directory_treeA
Read-onlyIdempotent

Get a visual tree of directories (folders only) in the specified path.

Shows the folder structure as a tree diagram with box-drawing characters. Does not include individual files - use get_directory_listing for file details.

Special behavior: If directory_path ends with .xcodeproj or .xcworkspace, the tree will show the parent directory structure (since these are typically at the root of a project folder).

Args: directory_path: Path to directory to scan. Can also be a .xcodeproj or .xcworkspace path (will scan parent directory in that case). max_depth: Maximum recursion depth (default 4, prevents excessive output). Depth 1 = immediate subdirectories only, Depth 4 = up to 4 levels deep.

Returns: A visual tree representation showing only directories/folders, with a note about using get_directory_listing for file-level details.

Example:
/Users/you/Projects/MyApp/
├── Sources/
│   ├── Models/
│   └── Views/
├── Tests/
└── Resources/

Inputs: directory_path (required), max_depth. Returns: result

get_latest_test_resultsA
Read-onlyIdempotent

Get the test results from the most recent test run.

Args: project_path: Path to Xcode project/workspace directory

Returns: JSON with test results or plain text error message. Success format: { "xcresult_path": "...", "summary": {"total_tests": N, "passed": M, "failed": K, "skipped": L}, "failed_tests": [{"test_name": "...", "failure_message": "...", ...}] }

Inputs: project_path (required). Returns: result

get_project_schemesA
Read-onlyIdempotent

Get the available build schemes for the specified Xcode project or workspace.

Args: project_path: Path to an Xcode project/workspace directory, which must end in '.xcodeproj' or '.xcworkspace' and must exist.

Returns: A newline-separated list of scheme names, with the active scheme listed first. If no schemes are found, returns an empty string.

Inputs: project_path (required). Returns: result

get_runtime_outputA
Read-onlyIdempotent

Fetches and returns the most relevant runtime console output from the project's most recent run.

Output becomes available 2 seconds after the app terminates.

Args: project_path: Path to an Xcode project (*.xcproject) or workspace (*.xcworkspace) regex_filter: Optional regex pattern to find matching lines in the output max_lines: Maximum number of matching lines to return (default 20)

Returns: JSON string with structured console output including errors, warnings, context, and full_log_path pointing to the complete unfiltered plaintext log file.

Inputs: project_path (required), regex_filter, max_lines. Returns: result

get_xcode_projectsA
Read-onlyIdempotent

Search for .xcodeproj and .xcworkspace files, optionally including recent projects.

If search_path is empty, searches all paths to which this tool has been granted access. Uses mdfind (Spotlight indexing) to find files efficiently.

Args: search_path: Path to search. If empty, searches all allowed folders. include_recents: If True, include recently opened projects first (default: True) max_search_depth: Maximum directory depth from search path (default: 3) Depth 0 = directly in search path, depth 1 = one level down, etc. regex_filter: Optional regex pattern to filter results max_results: Maximum number of results to return (default: 10)

Returns: A newline-separated list of .xcodeproj and .xcworkspace paths. Recent projects appear first if include_recents=True. Returns empty string if none are found.

Inputs: search_path, include_recents, max_search_depth, regex_filter, +1 more. Returns: result

list_booted_simulatorsA
Read-onlyIdempotent

List all currently booted iOS, iPadOS, tvOS, and watchOS simulators.

Returns: A formatted list of booted simulators with their names, UDIDs, and OS versions. Returns "No booted simulators found" if none are running.

Inputs: no named parameters. Returns: result

list_mac_app_windowsA
Read-onlyIdempotent

List all on-screen macOS application windows with their CGWindow IDs. These window IDs can be used to capture screenshots of a given window or app with take_app_screenshot or take_window_screenshot.

Returns: A formatted list of windows grouped by application, including window IDs that can be used with take_window_screenshot.

Inputs: no named parameters. Returns: result

list_project_testsA
Read-onlyIdempotent

List all available tests in the specified Xcode project or workspace.

Args: project_path: Path to Xcode project/workspace directory

Returns: A list of all test identifiers in the format: BundleName/ClassName/testMethodName

Inputs: project_path (required). Returns: result

list_run_destinationsA
Read-onlyIdempotent

List available run destinations (devices and simulators) for a project scheme.

Returns destinations filtered to what's compatible with the given scheme. For example, an iOS scheme will show iOS simulators and devices but not Mac destinations (unless the app supports Mac Catalyst).

Use the 'id' field from the results with set_run_destination to change which device Xcode builds and runs for.

Args: project_path: Path to an Xcode project (.xcodeproj) or workspace (.xcworkspace). scheme: Scheme name to list destinations for. If not provided, uses the first scheme found via xcodebuild.

Returns: JSON array of destinations, each with: name, platform, id, and optionally arch, OS, and variant fields.

Inputs: project_path (required), scheme. Returns: result

list_running_mac_appsA
Read-onlyIdempotent

List all currently running macOS applications.

Returns: A formatted list of running applications with their name, bundle ID, and status flags (frontmost/visible/hidden).

Inputs: no named parameters. Returns: result

run_project_testsA
Destructive

Run tests for the specified Xcode project or workspace.

Tests run for up to timeout seconds (default 600, i.e. 10 minutes) before timing out, which guards against a test run hanging indefinitely. Raise it for large projects whose build-for-testing alone exceeds the default.

Args: project_path: Path to Xcode project/workspace directory scheme: Optional scheme to test (uses active scheme if not specified) timeout: Maximum seconds to wait for the build-for-testing plus test run to complete. If not provided, defaults to 600. Must be a positive integer.

Returns: JSON with test results if tests complete, otherwise plain text status message. Success format: { "xcresult_path": "...", "summary": {"total_tests": N, "passed": M, "failed": K, "skipped": L}, "failed_tests": [{"test_name": "...", "failure_message": "...", ...}] } Timeout: Plain text message indicating timeout

Inputs: project_path (required), scheme, timeout. Returns: result

run_project_unmonitoredA
Destructive

Launch the app in Xcode and return immediately without waiting.

The app will continue running until you stop it manually in Xcode. No monitoring, no automatic termination, no log extraction.

Use get_runtime_output later (after manual termination) to retrieve logs.

Perfect for: Long-running apps, servers, apps needing extended manual testing

Args: project_path: Path to an Xcode project/workspace directory scheme: Optional scheme to run. If not provided, uses the active scheme.

Returns: Success message indicating the app has been launched

Inputs: project_path (required), scheme. Returns: result

run_project_until_terminatedA
Destructive

Run the app and wait for it to terminate naturally (up to timeout seconds).

The app will run in Xcode/Simulator. If it doesn't terminate within timeout seconds (default 600, i.e. 10 minutes), it will be force-stopped and runtime logs will be extracted.

No user interaction required - fully automated.

Perfect for: Automated tests, CLI tools, apps with defined exit points

Args: project_path: Path to an Xcode project/workspace directory scheme: Optional scheme to run. If not provided, uses the active scheme. regex_filter: Optional regex pattern to find matching lines in the output max_lines: Maximum number of matching lines to return (default 20) timeout: Maximum seconds to wait for the app to terminate before force-stopping it. If not provided, defaults to 600. Must be a positive integer.

Returns: JSON string with structured console output

Inputs: project_path (required), scheme, regex_filter, max_lines, +1 more. Returns: result

run_project_with_user_interactionA
Destructive

Run the app and display an alert dialog for you to interact with it.

The app will run in Xcode/Simulator. Once confirmed running, an alert dialog will appear with an "I'm finished - Terminate App" button.

  • Click the button when you're done testing → app will be force-stopped

  • If the app terminates on its own → no force-stop needed

In either case, runtime logs are extracted and returned after a 2-second wait.

Perfect for: Interactive testing, manual QA, debugging UI flows

Args: project_path: Path to an Xcode project/workspace directory scheme: Optional scheme to run. If not provided, uses the active scheme. regex_filter: Optional regex pattern to find matching lines in the output max_lines: Maximum number of matching lines to return (default 20)

Returns: JSON string with structured console output

Inputs: project_path (required), scheme, regex_filter, max_lines. Returns: result

set_run_destinationA
Idempotent

Set the active run destination (device or simulator) in Xcode.

Use list_run_destinations to get available destination IDs, then pass the desired 'id' value here to select it. Subsequent build and run operations will target this destination.

Args: project_path: Path to an Xcode project (.xcodeproj) or workspace (.xcworkspace). destination_id: The destination identifier to select. This is the 'id' field from list_run_destinations output (e.g. a simulator UDID or device UDID).

Returns: JSON with the name and id of the destination that was set.

Inputs: project_path (required), destination_id (required). Returns: result

stop_projectA
Idempotent

Stop the currently running build or run operation for the specified Xcode project or workspace.

Args: project_path: Path to an Xcode project/workspace directory, which must end in '.xcodeproj' or '.xcworkspace' and must exist.

Returns: A message indicating whether the stop was successful

Inputs: project_path (required). Returns: result

take_app_screenshotA
Read-onlyIdempotent

Take screenshots of all windows for an app (case-insensitive substring match). If the app has more than one window, screenshots will be taken for up to 5 of them.

Note: Only apps with at least one on-screen window can be found by this tool.

Args: app_name: Full or partial app name to match.

Returns: Path(s) to saved screenshot file(s), one per line (max 5 windows). If multiple apps match, returns an error with the full window list.

Raises: XCodeMCPError: If no matching app found, multiple apps match, or screenshot fails.

Inputs: app_name (required). Returns: result

take_simulator_screenshotA
Read-onlyIdempotent

Take a screenshot of a booted iOS simulator.

Args: udid: Optional UDID (device identifier) of the simulator to screenshot. If not provided or empty, the first booted simulator found is used. A list of running simulators can be found with list_booted_simulators.

Returns: The file path to the saved screenshot.

Raises: XCodeMCPError: If no booted simulators found or screenshot fails.

Inputs: udid. Returns: result

take_window_screenshotA
Read-onlyIdempotent

Take a screenshot of a window by ID or name (case-insensitive substring match). Window IDs can be obtained by calling list_mac_app_windows, or you can simply pass a partial (or complete) window title, like "News" for the News app. If multiple windows match the provided name, screenshots will be taken for up to the first 5 of them.

Note: Only on-screen windows can be found by name.

Args: window_id_or_name: Window ID number or partial window title to match.

Returns: Path(s) to saved screenshot file(s), one per line if multiple matches.

Raises: XCodeMCPError: If no matching windows found or screenshot fails.

Inputs: window_id_or_name (required). Returns: result

take_xcode_screenshotA
Read-onlyIdempotent

Take a screenshot of the Xcode window for the specified project.

Args: project_path: Path to an Xcode project/workspace directory.

Returns: The file path to the saved screenshot.

Raises: XCodeMCPError: If Xcode window is not found or screenshot fails.

Inputs: project_path (required). Returns: result

versionA
Read-onlyIdempotent

Get the current version of the Xcode MCP Server.

Returns: The version string of the server

Inputs: no named parameters. Returns: result

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    A4.1/5.0

    Scored across 29 tools

    Disambiguation4/5

    Most tools target distinct operations (build, clean, test, screenshot), though the three run variants (unmonitored, until terminated, with user interaction) and multiple get_build* tools could cause minor confusion if descriptions are not read carefully. Overall, boundaries are clear.

    Naming Consistency5/5

    All tools follow a consistent snake_case verb_noun pattern (e.g., build_project, get_build_errors, list_booted_simulators). Even multi-word verbs like debug_list_notification_history remain readable. No mixed conventions or ambiguous abbreviations.

    Tool Count3/5

    With 29 tools, the server is on the heavy side. While Xcode development is complex, some tools like version, debug_list_notification_history, and get_directory_listing feel peripheral. The count is justified but pushes the upper bound of reasonable scope.

    Completeness4/5

    Core workflows are well-covered: build, test, run, clean, destination management, screenshot capture, and error inspection. Minor gaps exist (e.g., no project archiving or code editing), but the surface is sufficient for most development tasks.

    Maintenance

    ActivitySlowing
    ResponsivenessLimited data

    Related MCP Connectors

    Related MCP Servers

    • A
      license
      B
      quality
      D
      maintenance
      Provides programmatic access to Xcode functionality, enabling AI assistants to create, build, test, and manage iOS/macOS projects directly.
      33
      7 npm
      5
      MIT
    • A
      license
      B
      quality
      D
      maintenance
      Enables AI assistants to build, test, run, and manage Apple platform projects (iOS, macOS, tvOS, watchOS, visionOS) directly through Xcode. Provides comprehensive control over Xcode projects, Swift packages, simulators, and development workflows without leaving your editor.
      5
      7 npm
      2
      MIT