lynnswap/xcodemcpkit
XcodeMCPKit is a local proxy for Xcode MCP. It gives your MCP clients one stable
Requirements
- macOS 15.4+
- Swift 6.3+
Install
From GitHub Releases
curl -fsSL https://github.com/lynnswap/XcodeMCPKit/releases/latest/download/install.sh | sh<details> <summary>Other install options</summary>
Custom install directory:
curl -fsSL https://github.com/lynnswap/XcodeMCPKit/releases/latest/download/install.sh | sh -s -- --bindir "$HOME/bin"Install a specific version:
curl -fsSL https://github.com/lynnswap/XcodeMCPKit/releases/download/v0.11.0/install.sh | shFrom Source
Installs both the proxy server and the STDIO adapter:
swift run -c release xcode-mcp-proxy-installCustom install directory:
swift run -c release xcode-mcp-proxy-install --prefix "$HOME/.local"
swift run -c release xcode-mcp-proxy-install --bindir "$HOME/bin"Add to PATH:
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc</details>
Set Up Your MCP Client
1. Enable Xcode MCP Access
Open your project in Xcode, choose Xcode > Settings > Intelligence, and turn on Allow external agents to use Xcode tools under Model Context Protocol. See [Giving external agents access to Xcode][apple-xcode-mcp-access].
This global Xcode setting is separate from the per-connection Allow dialog. --auto-approve handles Xcode connection dialogs, including those that appear while using headless routing; it does not enable headless MCP access.
Xcode 27 also supports optional headless MCP access.
2. Start the Proxy Server
xcode-mcp-proxy-server --auto-approve--auto-approve clicks Allow on recognized Xcode MCP connection dialogs for all agents, including Python scripts and other clients that launch mcpbridge directly. Existing approval based on the proxy's agent name, PID, and executable path is preserved. Additionally, the English heading Allow “…” to access Xcode? with an Allow button is approved for any agent. It applies in both GUI and headless modes while the proxy is running. In System Settings > Privacy & Security > Accessibility, allow the app that launches the proxy (for example, Terminal or iTerm).
Without Accessibility permission, omit --auto-approve and click Allow yourself:
xcode-mcp-proxy-server3. Register the Client
Replace xcrun mcpbridge with the proxy endpoint.
Codex
codex mcp remove xcode
# Recommended: Streamable HTTP
codex mcp add xcode --url http://localhost:8765/mcp
# Compatibility mode: STDIO
codex mcp add xcode -- xcode-mcp-proxyClaude Code
claude mcp remove xcode
# Recommended: Streamable HTTP
claude mcp add --transport http xcode http://localhost:8765/mcp
# Compatibility mode: STDIO
claude mcp add --transport stdio xcode -- xcode-mcp-proxyConfiguration
CLI help:
xcode-mcp-proxy-server --help
xcode-mcp-proxy --helpServer Options
| Option | Description | |--------|-------------| | --listen host:port | Listen address. Defaults to localhost:8765. | | --host host / --port port | Listen host and port when --listen is not used. | | --upstream-processes n | Upstream mcpbridge count: per running Xcode in GUI mode, or total unbound pool size in headless/custom mode. Default: 1, max: 10. | | --request-timeout seconds | Request timeout. 0 disables non-initialize timeouts; initialize still has a bounded handshake timeout. | | --config path | TOML config path. | | --xcode-mode automatic|gui|headless | Select Xcode routing. automatic (default) uses enabled headless MCP when available and otherwise uses GUI routing. headless fails instead of falling back. | | --auto-approve | Automatically approve Xcode MCP connection dialogs for all agents, including direct connections outside the proxy. Requires Accessibility permission. | | --refresh-code-issues-mode proxy|upstream | Serve XcodeRefreshCodeIssuesInFile through proxy diagnostics (proxy, default) or pass through to Xcode live diagnostics (upstream). | | --force-restart | Terminate an existing xcode-mcp-proxy-server on the listen port and start a new one. |
Environment Variables
| Variable | Description | |----------|-------------| | LISTEN | Listen address, for example 127.0.0.1:8765. | | HOST / PORT | Listen host and port when LISTEN is unset. | | MCP_XCODE_PID | Set by the proxy on GUI process-bound upstream mcpbridge children. Headless routing removes inherited values to leave the stock bridge unbound. Custom and GUI fallback upstreams pass inherited values through. | | MCP_XCODE_SESSION_ID | Optional explicit upstream Xcode MCP session ID. | | MCP_XCODE_CONFIG | TOML config path. --config takes precedence. | | MCP_XCODE_REFRESH_CODE_ISSUES_MODE | proxy or upstream. | | MCP_LOG_LEVEL | trace, debug, info, notice, warning, error, or critical. Defaults to info; debug includes HTTP access and route-recovery telemetry. | | XCODE_MCP_PROXY_ENDPOINT | STDIO adapter upstream URL. --url takes precedence. | | XCODE_MCP_PROXY_DISCOVERY_FILE | Discovery file override for isolated local/live test runs. | | XCODE_MCP_PROXY_CACHE_ROOT | Cache root used to derive the discovery path when XCODE_MCP_PROXY_DISCOVERY_FILE is unset. |
TOML Configuration
[upstream_handshake]
clientName = "XcodeMCPKit"
[tools]
disabled = ["RunAllTests", "RunSomeTests"]| Key | Type | Default | |-----|------|---------| | upstream_handshake.clientName | string | "XcodeMCPKit" | | upstream_handshake.clientVersion | string | "dev" | | upstream_handshake.capabilities | table | {} | | tools.disabled | array of strings | `` |
- Omitted
clientVersion: resolved from Xcode's matchingIDEChat*Version
defaults entry when available.
- Disabled tools: removed from
tools/listand rejected on directtools/call. - Config changes require restarting
xcode-mcp-proxy-server.
Migration
v0.14.0
- The Swift client and embedded proxy APIs now use typed connection state,
Duration deadlines, explicit async lifecycle completion, and a smaller server/adapter public surface.
- Deprecated wrappers are not retained.
- CLI users can keep the normal server and adapter commands, but must replace
the adapter's old --stdio alias with --url.
- See the v0.14.0 migration guide for the complete
old-to-new symbol and behavior mapping.
v0.11.0
If you use the proxy through Codex or Claude Code, no migration is required. Only the following cases need changes:
- Direct Streamable HTTP clients:
after initialize, send the server-issued MCP-Session-Id and MCP-Protocol-Version: 2025-06-18. Include Accept: application/json, text/event-stream on POST /mcp, and do not send JSON-RPC batch requests.
Optional: Headless MCP Access (Xcode 27)
Xcode 27 can serve MCP requests without a project or workspace open in the Xcode app. This is optional for XcodeMCPKit.
Enable headless access:
sudo xcrun mcp-server enableOn first workspace access, approve the agent and containing folder in Xcode Service when prompted.
Or enable it with all agents always allowed:
sudo xcrun mcp-server enable --unsafe-always-allow-all-agentsTroubleshooting
Maintainers
Local checks:
swift test -Xswiftc -strict-concurrency=minimal
XCODE_MCP_RUN_PROCESS_TESTS=1 swift test --no-parallel --filter XcodeMCPProcessRuntimeTests -Xswiftc -strict-concurrency=minimal
XCODE_MCP_RUN_PROCESS_TESTS=1 swift test --no-parallel --filter ProxyStdioAdapterTests -Xswiftc -strict-concurrency=minimal
scripts/check.shTo diagnose Xcode permission dialogs without launching mcpbridge, run the package-only maintainer tool with explicit existing process identities:
swift run xcode-mcp-permission-approver \
--xcode-pid <xcode-pid> \
--agent-pid <proxy-server-pid> \
--agent-path <proxy-server-path> \
--assistant-name XcodeMCPKitRelease:
gh workflow run release.yml --ref main -f version=v0.11.0Edit the draft release notes, then publish the release manually.
- Module boundaries, release flow, live tests, benchmarks:
Documentation
License
[apple-xcode-mcp-access]: https://developer.apple.com/documentation/xcode/giving-external-agents-access-to-xcode
Package Metadata
Repository: lynnswap/xcodemcpkit
Default branch: main
README: README.md