Skip to content

provencher/xcodemcpcli

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

xcodemcpcli

A CLI for driving Xcode builds, tests, and launches through the Xcode MCP bridge. It solves two problems when working with AI coding agents:

  1. Persistent daemon — a shared process holds the MCP session, so Xcode's permission prompt fires once instead of once per agent.
  2. Build/test queue — serializes Xcode work through a ticketed queue so multiple parallel agents share a single Xcode session without stomping on each other, optimizing compile time.

Features

  • build, test, and launch commands routed through an Xcode MCP server.
  • Local daemon with serialized queue, async tickets, --request-key reuse, status/wait/cancel, and protocol restart handling.
  • Persistent MCP session management over stdio or streamable HTTP server configs.
  • Raw MCP discovery via tools and call.
  • Compact rendering for Xcode build and test structured results, with warning and issue controls.
  • Configuration via xcodemcpcli.config.json and XCODEMCPCLI_* environment variables.

Requirements

  • Node.js 20 or newer.
  • Xcode with the MCP bridge available, usually through xcrun mcpbridge.
  • An Xcode project or workspace and scheme configured by env, config file, or flags.

Install from source

npm install
npm run build
npm link

During development you can run commands without linking:

npm run dev -- config
npm run dev -- daemon status

Quick project setup

From your Xcode project root, run:

xcodemcpcli init --scheme MyApp
xcodemcpcli doctor
xcodemcpcli build

init writes xcodemcpcli.config.json in the current directory. If the directory contains exactly one .xcworkspace, it uses that; otherwise, if it contains exactly one .xcodeproj, it uses that. If your project has multiple containers, pass the path explicitly:

xcodemcpcli init --scheme MyApp --workspace-path ./MyApp.xcworkspace
# or
xcodemcpcli init --scheme MyApp --project-path ./MyApp.xcodeproj

Useful setup flags:

  • --output <path> writes the config somewhere else. Use XCODEMCPCLI_CONFIG=/path/to/config.json when running commands from another directory.
  • --configuration <name> sets the Xcode configuration; default is Debug.
  • --derived-data-base-path <path> sets a project-specific DerivedData root.
  • --daemon-state-dir <path> keeps the local daemon socket/pid files with your project.
  • --mcp-url <url> configures a streamable HTTP MCP server instead of the default stdio xcrun mcpbridge.
  • --mcp-command <cmd> and repeated --mcp-arg <arg> customize the stdio MCP command.
  • --force overwrites an existing config file.

The generated config is plain JSON; review it before committing it if it contains machine-specific absolute paths.

Configuration

xcodemcpcli loads built-in generic defaults, then xcodemcpcli.config.json from the current directory (or XCODEMCPCLI_CONFIG), then XCODEMCPCLI_* environment variables. There is no default scheme; pass --scheme, set XCODEMCPCLI_SCHEME, or add scheme to xcodemcpcli.config.json.

Minimal environment setup:

export XCODEMCPCLI_PROJECT_PATH="$PWD/MyApp.xcodeproj"
export XCODEMCPCLI_SCHEME="MyApp"
export XCODEMCPCLI_CONFIGURATION="Debug"

Or create xcodemcpcli.config.json:

{
  "projectPath": "/path/to/MyApp.xcodeproj",
  "scheme": "MyApp",
  "configuration": "Debug",
  "derivedDataBasePath": "/tmp/MyAppDerivedData",
  "mcp": {
    "transport": "stdio",
    "command": "xcrun",
    "args": ["mcpbridge"],
    "buildTool": "BuildProject",
    "testTool": "RunSomeTests"
  },
  "daemon": {
    "stateDir": "/tmp/xcodemcpcli-state"
  }
}

Common environment variables:

  • XCODEMCPCLI_CONFIG
  • XCODEMCPCLI_PROJECT_PATH
  • XCODEMCPCLI_WORKSPACE_PATH
  • XCODEMCPCLI_SCHEME
  • XCODEMCPCLI_CONFIGURATION
  • XCODEMCPCLI_DERIVED_DATA_BASE_PATH
  • XCODEMCPCLI_CLONED_SOURCE_PACKAGES_DIR_PATH
  • XCODEMCPCLI_MCP_TRANSPORT (stdio or streamable-http)
  • XCODEMCPCLI_MCP_URL (sets streamable HTTP transport when provided)
  • XCODEMCPCLI_MCP_COMMAND (default xcrun)
  • XCODEMCPCLI_MCP_ARGS (JSON string array or whitespace-separated string; default mcpbridge)
  • XCODEMCPCLI_MCP_BUILD_TOOL
  • XCODEMCPCLI_MCP_TEST_TOOL (default RunSomeTests)
  • XCODEMCPCLI_MCP_TAB_IDENTIFIER
  • XCODEMCPCLI_MCP_CONNECT_TIMEOUT_MS
  • XCODEMCPCLI_MCP_TOOL_TIMEOUT_MS
  • XCODEMCPCLI_MCP_TEST_TOOL_TIMEOUT_MS
  • XCODEMCPCLI_DAEMON_STATE_DIR
  • XCODEMCPCLI_DAEMON_STARTUP_TIMEOUT_MS
  • XCODEMCPCLI_DAEMON_POLL_INTERVAL_MS
  • XCODEMCPCLI_DAEMON_HEARTBEAT_INTERVAL_MS
  • XCODEMCPCLI_APP_LAUNCH_COMMAND (advanced/testing override; default /usr/bin/open)
  • XCODEMCPCLI_MCP_XCODE_PID and XCODEMCPCLI_MCP_XCODE_SESSION_ID (forwarded to the MCP bridge as MCP_XCODE_PID and MCP_XCODE_SESSION_ID)

Usage

xcodemcpcli config
xcodemcpcli daemon start
xcodemcpcli doctor
xcodemcpcli tools
xcodemcpcli build
xcodemcpcli launch
xcodemcpcli build --async --request-key my-build
xcodemcpcli job list
xcodemcpcli job status <ticket>
xcodemcpcli job wait <ticket>
xcodemcpcli job cancel <ticket>
xcodemcpcli test AppTests/MyFeatureTests
xcodemcpcli test --only-testing AppTests/MyFeatureTests/testExample
xcodemcpcli tests classes --match MyFeatureTests
xcodemcpcli call XcodeListWindows --input '{}' --yes

Global flags:

  • --async: enqueue build/launch/test work and print a job ticket immediately.
  • --request-key <id>: reuse an existing queued/running job for the same logical request; mismatched active reuse fails.
  • --json: print raw JSON output where supported.
  • --refresh: refresh cached MCP tool discovery.
  • --yes: skip confirmation for raw call.
  • --full-issues: print all build/test issues instead of compact output.
  • --max-issues <n>: cap visible failures/tests in compact output.
  • --max-error-lines <n>: cap visible error lines per failed test.
  • --warnings <none|count|full>: warning display mode.

Suggested AGENTS.md note

If your project uses agent instructions, add a short note like this and adjust the config path/request keys for your repo:

Use `xcodemcpcli` for Xcode MCP build/test/launch work. If the config is not in the repo root, set `XCODEMCPCLI_CONFIG=/path/to/xcodemcpcli.config.json`.

Useful commands:
- `xcodemcpcli daemon start` and `xcodemcpcli daemon status` to check the local MCP daemon.
- `xcodemcpcli build --async --request-key project-build`, then `xcodemcpcli job status <ticket>` or `xcodemcpcli job wait <ticket>`.
- `xcodemcpcli launch --async --request-key project-launch`, then wait on the returned ticket.
- `xcodemcpcli tests classes --match SomeTests` to discover tests before running them.
- `xcodemcpcli test --only-testing TargetName/SomeTests/testMethod --async --request-key project-test`, then wait on the returned ticket.

Prefer async build/test/launch when agents may need to poll or coordinate. Use stable `--request-key` values for retryable submissions.

Daemon and jobs

All build, launch, test, tools, and call requests go through a Unix socket daemon. The daemon owns the MCP session and serializes Xcode actions so concurrent callers receive distinct tickets rather than racing the same Xcode session.

xcodemcpcli daemon start
xcodemcpcli daemon status
xcodemcpcli job list
xcodemcpcli job wait <ticket>
xcodemcpcli daemon stop

build, launch, and test without --async still submit a ticket and wait for it, printing reconnect guidance while they poll.

Notes and follow-up

  • test intentionally requires a selector or --only-testing; full-suite test runs are refused by default.
  • launch runs an MCP build, searches the build result/log/DerivedData for the newest matching .app, terminates older matching DerivedData app processes, and opens the selected bundle locally.
  • Real daemon integration tests require a fuller MCP SDK fixture. Current tests prioritize TypeScript compile coverage and core unit behavior.

About

CLI for driving Xcode builds, tests, and launches through the Xcode MCP bridge

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors