使用说明
XCodeMCPService
Local MCP Gateway — Aggregate xcrun mcpbridge and other stdio MCP servers behind one stable Streamable HTTP endpoint.
Xcode 27+ provides native headless MCP and persistent authorization. If you only need one Xcode connection and your client supports stdio, prefer running xcrun mcpbridge directly and do not install this project. Use this project when you need HTTP transport, multi-server aggregation, centralized process management, or compatibility with older Xcode versions.
MCP Client ──HTTP/POST──▶ XCodeMCPService ──stdio──▶ MCP Server (xcrun mcpbridge)
◀──JSON-RPC─── ◀──pipe──
Do You Need This Project?
| Scenario | Recommended approach |
|---|---|
| Xcode 27+, one local agent, client supports stdio | Configure xcrun mcpbridge directly |
| HTTP-only client, or multiple clients need a stable localhost endpoint | Use XCodeMCPService |
| Multiple MCP servers need aggregation, timeouts, restart, and shared logging | Use XCodeMCPService |
| Xcode 26.3+ needs to bind to a running Xcode instance | Use XCodeMCPService compatibility mode |
Direct Xcode 27+ configuration example:
{
"mcpServers": {
"xcode-tools": {
"command": "xcrun",
"args": ["mcpbridge"]
}
}
}
Enable headless MCP once for the Xcode selected by xcode-select:
sudo xcrun mcp-server enable
xcrun mcp-server status
This project never runs
mcp-server enableor enables--unsafe-always-allow-all-agentsautomatically. Apple recommends unsafe mode only for isolated unattended environments; keep per-agent authorization enabled on a daily workstation.
Features
- Multi-server aggregation — Manage multiple MCP subprocesses and auto-aggregate downstream capabilities; tool names stay original in single-server mode and switch to namespace prefixes (
serverName__toolName) only when multiple servers are configured - MCP compatibility — Preserve downstream tool titles, annotations, input/output schemas, icons, metadata, and structured results; optional fields absent in older Xcode versions remain absent
- Streamable HTTP Transport — Lightweight HTTP server based on
NWListener, providing/mcpendpoint, localhost only - Session management — Independent session per client with secure token identification
- Process lifecycle — Crash detection + exponential backoff auto-restart
- macOS status bar app — Visual service status, one-click start/stop
- Device unlock reminder — While
RunAllTests/RunSomeTests/RunProjecttarget a physical device, the service waits for the build to finish (a new build log in DerivedData), then polls the lock state viadevicectl; once the device has stayed locked for 30 seconds, the status bar app shows an Apple Intelligence–style glowing edge and a shaking reminder on every display until the device is unlocked or the call ends or is cancelled
Requirements
- macOS 15.0+
- Swift 6.0+
- Xcode 26.3+ (
xcrun mcpbridgesupport)
Installation
git clone git@github.com:ljh740/XCodeMCPService.git
cd XCodeMCPService
# Build .app (recommended)
bash build-app.sh
# List available identities; durable Xcode 27 trust requires an Apple-issued chain
security find-identity -v -p codesigning
# Apple Development is suitable for a local install; disable distribution timestamps
CODE_SIGN_IDENTITY="Apple Development: Your Name (TEAMID)" \
CODE_SIGN_TIMESTAMP=none \
bash build-app.sh
# Install to Applications
cp -r "build/XCode MCP Service.app" /Applications/
Without
CODE_SIGN_IDENTITY, the script discovers valid Apple code-signing identities in the current Keychain search list. It selects the sole candidate Team matching an unexpired signed Xcode grant, or otherwise the sole candidate Team. Multiple eligible Teams without a unique match require an explicitCODE_SIGN_IDENTITY; the script prints a warning and retains ad-hoc signing instead of choosing a Team for you. Within the selected Team, development certificates take precedence, followed by later expiration dates and fingerprint order. Team IDs come from certificate OU fields, not display names.Discovery uses optional Ruby/OpenSSL support; it installs nothing and does not unlock Keychains or change Xcode permissions. Missing dependencies, inaccessible Keychains, or no eligible certificate fall back to ad-hoc signing. Xcode's
mcp-serveris optional: without it, only an unambiguous Team can be selected. CI without a signing identity continues to work. SetCODE_SIGN_IDENTITY="-"to skip discovery and explicitly retain ad-hoc signing, or specify an identity for a reproducible signed build. Actual signing failures stop the build instead of silently downgrading. Auto-selected development identities disable timestamps unlessCODE_SIGN_TIMESTAMPis explicitly set; Developer ID identities retain secure timestamps by default. Ad-hoc and ordinary self-signed signatures may receive only temporary Xcode grants. For distribution, explicitly chooseDeveloper ID Application. The packaging script preserves the Apple Events entitlement on both executables.
Build output is at build/XCode MCP Service.app, containing:
| Component | Path | Description |
|---|---|---|
| Status bar app | Contents/MacOS/XCodeMCPStatusBar |
Main entry, visual status bar management |
| CLI service | Contents/MacOS/XCodeMCPService |
Command-line service (for background use) |
The packaging script also produces:
| Artifact | Path | Description |
|---|---|---|
| Disk image | build/XCodeMCPService.dmg |
Recommended macOS release package |
| SHA-256 | build/XCodeMCPService.dmg.sha256 |
Disk image checksum |
| Zip archive | build/XCodeMCPService.app.zip |
App archive (automatic identity selection, with ad-hoc fallback) |
| SHA-256 | build/XCodeMCPService.app.zip.sha256 |
Archive checksum |
You can locate standalone binaries with
swift build -c release --show-bin-path.
Quick Start
1. Create config file
mkdir -p ~/Library/Application\ Support/XCodeMCPService
{
"bridge": {
"port": 13339,
"host": "127.0.0.1",
"timeout": 30000,
"toolTimeouts": {
"xcode-tools__BuildProject": 2400000,
"xcode-tools__RunAllTests": 2400000,
"xcode-tools__RunSomeTests": 2400000
},
"capabilityTimeout": 15000,
"logLevel": "info"
},
"servers": [
{
"name": "xcode-tools",
"command": "xcrun",
"args": ["mcpbridge"],
"enabled": true
}
]
}
Save as ~/Library/Application Support/XCodeMCPService/config.json.
Without a config file, the service uses built-in defaults (port 13339, auto-start
xcrun mcpbridge). The service selects the only running Xcode first; with multiple instances it prefers the active orxcode-select-selected installation. When Xcode 27 headless MCP is enabled, it prefers that connection and intentionally leavesMCP_XCODE_PIDunset so persistent agent grants survive service restarts. Older Xcode versions, or Xcode 27 with headless mode disabled, bind to the detected GUI process. When an Xcode launches or quits, the service re-resolves the binding and restarts only servers whose Xcode or connection mode changed, waiting for in-flight tool calls (such as builds or tests) to finish first; the status bar menu can also restart a single server. Setenv.DEVELOPER_DIRorenv.MCP_XCODE_PIDfor an explicit override, which also disables this automatic switching. A default config file is created on first launch.
Enable the Xcode 27 headless MCP experience once for the currently selected Xcode:
sudo xcrun mcp-server enable
xcrun mcp-server status
To target another Xcode explicitly, pass only that installation's Developer directory:
sudo env DEVELOPER_DIR="/path/to/Xcode.app/Contents/Developer" xcrun mcp-server enable
2. Start the service
# Via .app (status bar app)
open "/Applications/XCode MCP Service.app"
# Or via CLI
BIN_DIR="$(swift build -c release --show-bin-path)"
"$BIN_DIR/XCodeMCPService"
# Specify config file
"$BIN_DIR/XCodeMCPService" --config /path/to/config.json
# Via environment variable
CONFIG_PATH=/path/to/config.json "$BIN_DIR/XCodeMCPService"
3. Configure MCP client
Add to your MCP client configuration:
{
"mcpServers": {
"local-mcp": {
"type": "http",
"url": "http://127.0.0.1:13339/mcp"
}
}
}
Configuration Reference
BridgeConfig
| Field | Type | Default | Description |
|---|---|---|---|
port |
Int | 13339 |
HTTP listen port |
host |
String | "127.0.0.1" |
Listen address (127.0.0.1 or localhost only) |
timeout |
Int | 30000 |
Request timeout (ms) |
toolTimeouts |
{String: Int} | Three overrides shown above | Tool timeout overrides (ms), keyed by server__tool canonical name |
capabilityTimeout |
Int | 15000 |
Per-category capability timeout during startup and reconnect (ms) |
logLevel |
String | "info" |
Log level: debug / info / warn / error |
Omitting toolTimeouts enables the three 40-minute defaults, including in existing config files. An explicit table replaces those defaults; {} disables all overrides. Keys use the configured server name even when a single-server client calls an unprefixed tool. Other tools, resources, and prompts retain timeout. Override values must be at least 1000 ms. HTTP waits for the longest configured request timeout plus 5 seconds for the response. Restart the service after changing configuration, and set client tool timeouts to at least 40 minutes for these long tasks.
ServerConfig
| Field | Type | Default | Description |
|---|---|---|---|
name |
String | — | Unique server name |
command |
String | — | Launch command |
args |
[String] | [] |
Command arguments |
env |
{String: String}? | nil |
Environment variables |
enabled |
Bool | true |
Whether enabled |
Config file lookup order
--configCLI argumentCONFIG_PATHenvironment variable~/Library/Application Support/XCodeMCPService/config.json- Built-in defaults (auto-written to default path on first launch)
Logs
Log files are stored by date in ~/Library/Application Support/XCodeMCPService/logs/ as yyyy-MM-dd.log. Also output to stderr.
Testing
swift test
Tests cover HTTP parsing/serialization/routing, session management, ResponseQueue, ID mapping, Xcode runtime selection, process lifecycle management, and more.
CI/CD
.github/workflows/ci.yml: runsswift build -c releaseandswift test --parallelon every push and pull request..github/workflows/release.yml: runsbash build-app.shon everyv*tag push or manual dispatch, then uploads the.appbundle,dmg,zip, and SHA-256 checksum files as workflow artifacts.- Tag builds also publish
build/XCodeMCPService-<tag>.dmg,build/XCodeMCPService-<tag>.dmg.sha256,build/XCodeMCPService-<tag>.zip, andbuild/XCodeMCPService-<tag>.zip.sha256to the matching GitHub Release.
License
MIT License
Acknowledgments
- Model Context Protocol — MCP specification
- swift-sdk — MCP Swift SDK
