Contributing
How to set up, build, and submit changes to XcodeBuildMCP.
XcodeBuildMCP lives at getsentry/XcodeBuildMCP. Use the issue tracker for bugs, proposals, and larger changes that need design discussion before code.
Prerequisites
| Requirement | Notes |
|---|---|
| macOS | XcodeBuildMCP shells out to Apple developer tools, so development is macOS-only. |
| Xcode | Install Xcode and make sure Command Line Tools point at the Xcode you use for testing. |
| Node.js 18+ | The package targets Node 18 and later. |
| npm | Used for install, build, test, and local scripts. |
| AXe (optional) | Required only if you work on UI automation or simulator capture tools. Bundle it locally with npm run bundle:axe. The script downloads pre-built artifacts into bundled/axe, which the server resolves automatically at runtime. |
npm run bundle:axeIf you prefer a system-wide install on PATH, brew tap cameroncooke/axe && brew install axe also works, the resolver falls back to PATH after checking bundled/.
Clone, install, build
git clone https://github.com/getsentry/XcodeBuildMCP.git
cd XcodeBuildMCP
npm install
npm run hooks:install
npm run build
# Verify the build via the CLI
node build/cli.js --help
# Or start the MCP server (stdio)
node build/cli.js mcpnpm run hooks:install configures the repository-managed git hooks from .githooks/.
Point your MCP client at the dev build
Use the built cli.js directly while developing. Replace the path with your checkout path.
{
"mcpServers": {
"XcodeBuildMCP": {
"command": "node",
"args": ["/path/to/XcodeBuildMCP/build/cli.js", "mcp"],
"env": {
"XCODEBUILDMCP_DEBUG": "true"
}
}
}
}Iterating
Most XcodeBuildMCP code is shared between the CLI and MCP server: the tools themselves, the manifests that describe them, the runtime layer that receives a request, and the rendering layer that turns its output into text or JSON. That means most tool behavior is testable through the CLI without an MCP client in the loop:
node build/cli.js simulator list
node build/cli.js simulator build --scheme MyApp --project-path ./MyApp.xcodeprojReach for the tools below only when you are validating MCP-specific behavior: tool advertising in tools/list, the structured content envelope, annotations, the server lifecycle, or anything the CLI surface does not exercise.
Testing the MCP layer
When an MCP client launches the server, it spawns the server as a long-lived subprocess at startup. The running Node process holds the build that was on disk when it spawned, so rebuilding does not affect it. To pick up changes you have to kill and respawn the server, which drops the client's MCP connection and forces a reconnect (a manual click or a full editor restart, depending on the client). Three patterns avoid that loop:
Run npm run inspect for the MCP Inspector interactive UI. Browser-based MCP client where you can list tools, call them with form inputs, view structured responses, and (importantly) see the server's stderr logs that real MCP clients usually hide.
Best for human exploration and debugging when you want the full server-side picture.
npm run inspectRun npm run dev:tsup in your terminal so the build rebuilds on save. The Inspector flows pick up the latest build on the next call (fresh subprocess); Reloaderoo needs an explicit restart_server call after each rebuild.
Pre-commit checks
If you ran npm run hooks:install, the git pre-commit hook automatically runs npm run format:check, npm run lint, npm run build, and npm run docs:check when you commit. That is a safety net, not a substitute for development-time checks. Catching problems while you iterate is faster than catching them at commit time, and the hook does not run typecheck, lint:fix, or test.
Full checklist to run yourself during development:
npm run lint:fix
npm run typecheck
npm run format
npm run build
npm run docs:check
npm testDo not commit TypeScript errors. Fix the type issue instead of suppressing it with unsafe casts, any, @ts-ignore, or @ts-nocheck.
Making a change
Start from an up-to-date main branch and create a focused branch:
git checkout main
git pull origin main
git checkout -b feature/issue-123-add-simulator-filterCommon branch prefixes:
| Prefix | Use it for |
|---|---|
feature/issue-123-description | New behavior. |
bugfix/issue-456-description | Bug fixes. |
hotfix/critical-description | Urgent production fixes. |
docs/update-topic | Documentation-only work. |
refactor/improve-topic | Internal restructuring without behavior changes. |
Keep commits atomic. Each commit should explain one logical change. If your change affects users, add a CHANGELOG.md entry under ## [Unreleased] in the correct section: Added, Changed, Fixed, or Removed.
Follow the existing TypeScript patterns:
- Use Zod schemas for runtime validation.
- Keep tool logic testable through injected executors when it orchestrates external commands.
- Test logic functions, not handler functions.
- Do not add formatted output by hand. Use the domain result and rendering model described in Architecture.
Submitting
Open a pull request from your branch and include:
| Section | What reviewers need |
|---|---|
| Summary | What changed and why. |
| Background or details | Context, issue links, and important constraints. |
| Solution | The implementation approach and key tradeoffs. |
| Testing | Commands you ran and any manual validation. |
| Notes | Risk, follow-up work, or reviewer focus areas. |
Link related issues. For major features or risky behavior changes, open an issue first and get alignment before spending time on implementation.
Project templates
The scaffolding tools pull iOS and macOS templates from separate repositories:
Use local template overrides when developing template changes:
export XCODEBUILDMCP_IOS_TEMPLATE_PATH=/path/to/XcodeBuildMCP-iOS-Template
export XCODEBUILDMCP_MACOS_TEMPLATE_PATH=/path/to/XcodeBuildMCP-macOS-TemplateOptional version overrides:
| Env var | Scope |
|---|---|
XCODEBUILD_MCP_TEMPLATE_VERSION | Shared fallback for both templates. |
XCODEBUILD_MCP_IOS_TEMPLATE_VERSION | iOS template only. |
XCODEBUILD_MCP_MACOS_TEMPLATE_VERSION | macOS template only. |
When testing through an MCP client, put the same env vars in that client's mcpServers.XcodeBuildMCP.env block.
Related
- Architecture, how the runtime, manifests, and rendering model fit together
- Tool Authoring, adding or changing tools end to end
- Testing, test structure and snapshot rules
- GitHub repo, source, issues, and pull requests