A Python wrapper that makes Xcode 26.3's MCP bridge compatible with Cursor and other strict MCP-spec-compliant clients.
Xcode's mcpbridge returns tool responses in the content field but omits the required structuredContent field when a tool declares an outputSchema. According to the MCP specification, when outputSchema is declared, responses must include structuredContent.
- ✅ Claude Code and Codex CLI work (they have special handling for Apple's responses)
- ❌ Cursor strictly follows the spec and rejects non-compliant responses
mcpbridge-wrapper intercepts responses from xcrun mcpbridge and copies the data from content into structuredContent, making Xcode's MCP tools fully compatible with all MCP clients.
┌─────────────┐ MCP Protocol ┌──────────────────┐ MCP Protocol ┌────────────┐ XPC ┌─────────┐
│ Cursor │ ◄────────────────► │ mcpbridge-wrapper│ ◄──────────────► │ mcpbridge │ ◄───────► │ Xcode │
│ (MCP Client)│ │ (This Project) │ │ (Bridge) │ │ (IDE) │
└─────────────┘ └──────────────────┘ └────────────┘ └─────────┘
- macOS with Xcode 26.3+
- Python 3.9+
- Xcode Tools MCP Server enabled (see below)
⚠️ Important: You MUST enable Xcode Tools MCP in Xcode settings:
- Open Xcode > Settings (⌘,)
- Select Intelligence in the sidebar
- Under Model Context Protocol, toggle Xcode Tools ON
If you see "Found 0 tools" in your MCP client logs, this setting is not enabled.
If you use Cursor, no installation is needed — just add this to ~/.cursor/mcp.json:
Broker mode (Recommended):
{
"mcpServers": {
"xcode-tools": {
"command": "uvx",
"args": ["--from", "mcpbridge-wrapper", "mcpbridge-wrapper", "--broker"]
}
}
}With Web UI dashboard (optional — adds real-time monitoring at http://localhost:8080):
{
"mcpServers": {
"xcode-tools": {
"command": "uvx",
"args": [
"--from",
"mcpbridge-wrapper[webui]",
"mcpbridge-wrapper",
"--broker",
"--web-ui",
"--web-ui-config",
"/Users/YOUR_USERNAME/.mcpbridge_wrapper/webui.json"
]
}
}
}Direct mode (Alternative):
{
"mcpServers": {
"xcode-tools": {
"command": "uvx",
"args": ["--from", "mcpbridge-wrapper", "mcpbridge-wrapper"]
}
}
}If you upgrade and want to confirm the currently running dashboard process version:
PORT=8080
PID=$(lsof -tiTCP:$PORT -sTCP:LISTEN | head -n1)
PY=$(ps -p "$PID" -o command= | awk '{print $1}')
"$PY" -c 'import importlib.metadata as m; print(m.version("mcpbridge-wrapper"))'If needed, do a one-time refresh start:
uvx --refresh --from 'mcpbridge-wrapper[webui]' mcpbridge-wrapper --web-ui --web-ui-port 8080Restart Cursor and you're done. For other clients or installation methods, read on.
Broker mode lets multiple short-lived MCP client sessions share one persistent upstream bridge session.
- Why this mode exists: Apple documents a Coding Intelligence known issue in Xcode 26.4 where external development tools may trigger repeated "Allow Connection?" dialogs during normal usage (
170721057). Reusing one long-lived upstream session via broker mode can reduce reconnect churn that surfaces this prompt pattern. See Apple's official Xcode 26.4 release notes. - Use
--brokerto auto-detect — connect if daemon is alive, spawn otherwise (recommended). - Add
--web-ui(plus optional--web-ui-config) when you want the spawned or daemon host to own one shared dashboard endpoint. - If you want one explicit daemon owner plus one visible monitoring surface across multiple editors, prefer a dedicated host: start
--broker-daemon --web-uionce, keep clients on--broker, and attach the browser dashboard and/or--tuito that host.
Quick migration examples:
# Claude Code
claude mcp add --transport stdio xcode -- uvx --from mcpbridge-wrapper mcpbridge-wrapper --broker
# Codex CLI
codex mcp add xcode -- uvx --from mcpbridge-wrapper mcpbridge-wrapper --brokerAfter upgrading, stop the old singleton daemon once so the next --broker client
starts the new package version:
uvx --from mcpbridge-wrapper mcpbridge-wrapper --broker-stopFor full start/stop/status commands, Cursor JSON snippets, troubleshooting, and
rollback to direct mode, see
When you run multiple MCP client processes at the same time:
- Dedicated host frontend workflow (recommended when visibility matters): start one
--broker-daemon --web-uiprocess, keep every editor/client on--broker, and attach the browser dashboard and/ormcpbridge-wrapper --tuito the same host. - Unified single-config auto-spawn: configure each client with
--broker --web-ui --web-ui-config <shared-path>when you want less setup and can accept implicit host ownership. - Runtime expectation: a dedicated host is the clearest way to control lifecycle; in unified auto-spawn, the first client that must spawn the broker starts the broker host and dashboard and later clients reuse it.
- Ownership rule: only one process can bind a given Web UI
host:port(for example127.0.0.1:8080). - Connection behavior: when a broker is already running,
--brokerreuses it and does not retrofit dashboard settings onto that existing host. - Fallback behavior: if dashboard bind fails (port already in use), broker MCP transport continues and only dashboard startup is skipped.
- Verification flow: use
mcpbridge-wrapper --broker-status, the files under~/.mcpbridge_wrapper/, and the shared dashboard/TUI state to verify that both editors are attached to one daemon.
See
If you plan to run make install, pytest, or other development commands, create and activate a virtual environment first. This avoids Homebrew Python's externally-managed-environment (PEP 668) error.
cd XcodeMCPWrapper
python3 -m venv .venv
source .venv/bin/activate
python3 -m pip install --upgrade pip
make installQuick checks:
which python3
which pipBoth should point to .venv/bin/... while the environment is active.
The fastest way to install is using uvx (requires uv to be installed):
# No manual installation needed - uvx will automatically download and run
uvx --from mcpbridge-wrapper mcpbridge-wrapperOr add to your MCP client configuration directly (see configuration sections below).
If your MCP client supports the MCP Registry:
Server name: io.github.SoundBlaster/xcode-mcpbridge-wrapper
# Using mcp-publisher CLI
mcp-publisher install io.github.SoundBlaster/xcode-mcpbridge-wrapperpython3 -m pip install mcpbridge-wrapperThen use mcpbridge-wrapper or xcodemcpwrapper command.
git clone https://github.com/SoundBlaster/XcodeMCPWrapper.git
cd XcodeMCPWrapper
./scripts/install.shThe install script creates a virtual environment, installs the package, and places a wrapper at ~/bin/xcodemcpwrapper.
If you plan to use --web-ui MCP args, install Web UI extras explicitly:
./scripts/install.sh --webuiAdd the following to your ~/.bashrc or ~/.zshrc:
export PATH="$HOME/bin:$PATH"Then reload:
source ~/.zshrc
# or
. ~/.zshrcFor development or if you want to run directly from the cloned repository:
git clone https://github.com/SoundBlaster/XcodeMCPWrapper.git
cd XcodeMCPWrapper
python3 -m venv .venv
source .venv/bin/activate
make install # or: make install-webui (for Web UI support)The entry point is .venv/bin/mcpbridge-wrapper. Use the full absolute path when configuring MCP clients (see configuration sections below).
To remove xcodemcpwrapper from your system:
./scripts/uninstall.shOptions:
--dry-runor-n: Show what would be removed without removing--yesor-y: Skip confirmation prompt
Broker setup examples are listed first.
Using uvx in broker mode (Recommended):
{
"mcpServers": {
"xcode-tools": {
"command": "uvx",
"args": ["--from", "mcpbridge-wrapper", "mcpbridge-wrapper", "--broker"]
}
}
}Using uvx in broker mode with Web UI (Optional):
{
"mcpServers": {
"xcode-tools": {
"command": "uvx",
"args": [
"--from",
"mcpbridge-wrapper[webui]",
"mcpbridge-wrapper",
"--broker",
"--web-ui",
"--web-ui-config",
"/Users/YOUR_USERNAME/.mcpbridge_wrapper/webui.json"
]
}
}
}Using uvx in direct mode:
{
"mcpServers": {
"xcode-tools": {
"command": "uvx",
"args": ["--from", "mcpbridge-wrapper", "mcpbridge-wrapper"]
}
}
}Using uvx in direct mode with Web UI (Optional):
{
"mcpServers": {
"xcode-tools": {
"command": "uvx",
"args": [
"--from",
"mcpbridge-wrapper[webui]",
"mcpbridge-wrapper",
"--web-ui",
"--web-ui-port",
"8080"
]
}
}
}Using manual installation (Direct mode):
{
"mcpServers": {
"xcode-tools": {
"command": "/Users/YOUR_USERNAME/bin/xcodemcpwrapper",
"args": []
}
}
}Using manual installation with Web UI (Direct mode, optional):
Requires installing with
./scripts/install.sh --webui(or equivalent.[webui]dependencies).
{
"mcpServers": {
"xcode-tools": {
"command": "/Users/YOUR_USERNAME/bin/xcodemcpwrapper",
"args": ["--web-ui", "--web-ui-port", "8080"]
}
}
}Using local development (venv, direct mode):
{
"mcpServers": {
"xcode-tools": {
"command": "/path/to/XcodeMCPWrapper/.venv/bin/mcpbridge-wrapper"
}
}
}Using local development with Web UI (Direct mode, optional):
{
"mcpServers": {
"xcode-tools": {
"command": "/path/to/XcodeMCPWrapper/.venv/bin/mcpbridge-wrapper",
"args": ["--web-ui", "--web-ui-port", "8080"]
}
}
}Broker setup examples are listed first.
Using uvx in broker mode (Recommended):
claude mcp add --transport stdio xcode -- uvx --from mcpbridge-wrapper mcpbridge-wrapper --brokerUsing uvx in broker mode with Web UI (Optional):
claude mcp add --transport stdio xcode -- uvx --from 'mcpbridge-wrapper[webui]' mcpbridge-wrapper --broker --web-ui --web-ui-config "$HOME/.mcpbridge_wrapper/webui.json"Using uvx in direct mode:
claude mcp add --transport stdio xcode -- uvx --from mcpbridge-wrapper mcpbridge-wrapperUsing uvx in direct mode with Web UI (Optional):
claude mcp add --transport stdio xcode -- uvx --from 'mcpbridge-wrapper[webui]' mcpbridge-wrapper --web-ui --web-ui-port 8080Using manual installation (Direct mode):
claude mcp add --transport stdio xcode -- ~/bin/xcodemcpwrapperUsing manual installation with Web UI (Direct mode, optional):
Requires installing with ./scripts/install.sh --webui (or equivalent .[webui] dependencies).
claude mcp add --transport stdio xcode -- ~/bin/xcodemcpwrapper --web-ui --web-ui-port 8080Using local development (venv, direct mode):
claude mcp add --transport stdio xcode -- /path/to/XcodeMCPWrapper/.venv/bin/mcpbridge-wrapperUsing local development with Web UI (Direct mode, optional):
claude mcp add --transport stdio xcode -- /path/to/XcodeMCPWrapper/.venv/bin/mcpbridge-wrapper --web-ui --web-ui-port 8080Broker setup examples are listed first.
Using uvx in broker mode (Recommended):
codex mcp add xcode -- uvx --from mcpbridge-wrapper mcpbridge-wrapper --brokerUsing uvx in broker mode with Web UI (Optional):
codex mcp add xcode -- uvx --from 'mcpbridge-wrapper[webui]' mcpbridge-wrapper --broker --web-ui --web-ui-config "$HOME/.mcpbridge_wrapper/webui.json"Using uvx in direct mode:
codex mcp add xcode -- uvx --from mcpbridge-wrapper mcpbridge-wrapperUsing uvx in direct mode with Web UI (Optional):
codex mcp add xcode -- uvx --from 'mcpbridge-wrapper[webui]' mcpbridge-wrapper --web-ui --web-ui-port 8080Using manual installation (Direct mode):
codex mcp add xcode -- ~/bin/xcodemcpwrapperUsing manual installation with Web UI (Direct mode, optional):
Requires installing with ./scripts/install.sh --webui (or equivalent .[webui] dependencies).
codex mcp add xcode -- ~/bin/xcodemcpwrapper --web-ui --web-ui-port 8080Using local development (venv, direct mode):
codex mcp add xcode -- /path/to/XcodeMCPWrapper/.venv/bin/mcpbridge-wrapperUsing local development with Web UI (Direct mode, optional):
codex mcp add xcode -- /path/to/XcodeMCPWrapper/.venv/bin/mcpbridge-wrapper --web-ui --web-ui-port 8080Using uvx (Recommended):
Edit ~/.zed/settings.json:
{
"xcode-tools": {
"command": "uvx",
"args": ["--from", "mcpbridge-wrapper", "mcpbridge-wrapper"],
"env": {}
}
}Using uvx with Web UI (Optional):
{
"xcode-tools": {
"command": "uvx",
"args": [
"--from",
"mcpbridge-wrapper[webui]",
"mcpbridge-wrapper",
"--web-ui",
"--web-ui-port",
"8080"
],
"env": {}
}
}Using manual installation:
{
"xcode-tools": {
"command": "/Users/YOUR_USERNAME/bin/xcodemcpwrapper",
"args": [],
"env": {}
}
}Using manual installation with Web UI (Optional):
Requires installing with ./scripts/install.sh --webui (or equivalent .[webui] dependencies).
{
"xcode-tools": {
"command": "/Users/YOUR_USERNAME/bin/xcodemcpwrapper",
"args": ["--web-ui", "--web-ui-port", "8080"],
"env": {}
}
}Using local development (venv, direct mode):
{
"xcode-tools": {
"command": "/path/to/XcodeMCPWrapper/.venv/bin/mcpbridge-wrapper",
"args": [],
"env": {}
}
}Using local development with Web UI (Direct mode, optional):
{
"xcode-tools": {
"command": "/path/to/XcodeMCPWrapper/.venv/bin/mcpbridge-wrapper",
"args": ["--web-ui", "--web-ui-port", "8080"],
"env": {}
}
}Using uvx (Recommended):
Edit ~/.kimi/mcp.json:
{
"xcode-tools": {
"command": "uvx",
"args": ["--from", "mcpbridge-wrapper", "mcpbridge-wrapper"],
"env": {}
}
}Using manual installation:
{
"xcode-tools": {
"command": "/Users/YOUR_USERNAME/bin/xcodemcpwrapper",
"args": [],
"env": {}
}
}Once configured, ask your AI assistant to use Xcode tools:
"Build my project"
"Run the tests"
"Find all Swift files in the project"
"Show me the build errors"
The wrapper includes an optional Web UI dashboard for real-time monitoring and audit logging:
# Start with Web UI
make webui
# Or directly
python -m mcpbridge_wrapper --web-ui --web-ui-port 8080Features:
- Real-time metrics: RPS, latency percentiles (p50, p95, p99), error rates
- Tool usage analytics: Visual charts of most frequently used tools
- Audit logging: Persistent log of all MCP tool calls with export (JSON/CSV)
- Request inspector: Live log stream with filtering
Open http://localhost:8080 in your browser to view the dashboard.
Important for multi-agent setups:
- The dashboard is hosted by one wrapper process, not by Xcode or
mcpbridge. - A single
host:portcan have only one listener; additional processes on the same port skip dashboard startup and continue MCP traffic. - For the explicit Phase 6 operator workflow, run one dedicated broker host with
--broker-daemon --web-ui, then monitor that same host from the browser dashboard and/ormcpbridge-wrapper --tui.
See
- Broker cold-start — Xcode approval timing race (0 tools with green dot): When the broker daemon starts a new
xcrun mcpbridgeprocess (on first launch or after a daemon restart), Xcode shows a per-process "Allow Connection?" dialog. If your MCP client sendstools/listbefore Xcode grants approval, it receives an empty list and caches it permanently — showing 0 tools with a green connected indicator and no error message. Each unique binary path (direct wrapper vs broker daemon) triggers a separate dialog. After approval the permission persists — no re-approval is needed on subsequent sessions. Workaround: watch for the Xcode dialog immediately after enabling broker mode; after clicking Allow, reload the MCP connection in your client (disable → re-enable in settings). SeeTroubleshooting: 0 tools after first broker connection for client-specific recovery steps and the diagnostic command. - Singleton broker host behavior:
--brokerreuses one live daemon per local user, includinguvx --from mcpbridge-wrapper mcpbridge-wrapper --brokerclients. The first client that auto-spawns the daemon determines the Python host identity Xcode sees; for the most stable permission identity, start a dedicated broker host from a fixed path or setMCPBRIDGE_WRAPPER_BROKER_HOST_CMDbefore auto-spawn. - BUG-T5 → FU-P13-T7 (P0): Empty-content tool results can still violate strict
structuredContentexpectations in strict MCP clients. - BUG-T6 → FU-P13-T8 (P0): Web UI port collisions can happen when multiple MCP sessions start with the same
--web-ui-port(for example8080), producingaddress already in use. - BUG-T7 → FU-P13-T9 (P0):
resources/listandresources/templates/listprobing may return non-standard error shapes in some client paths. - Codex Desktop resources probe behavior: Xcode MCP is a tools-focused server. Some Codex Desktop paths may still probe
resources/listandresources/templates/list;-32601("unknown method") on those two calls does not mean tool connectivity is broken. Validate health with an actual Xcode tool call (for exampleXcodeListWindows). - Codex broker-mode timeout fallback: If Codex tool calls time out in broker mode, switch to direct mode (remove
--broker) and validate withXcodeListWindows.
mcpbridge-wrapper normalizes Xcode MCP responses, but it does not control Codex App internals. Codex App transport/session behavior may change independently from Codex CLI and from this wrapper. If App and CLI differ, treat that as client-specific behavior first and verify with exact versions, config, and logs.
Installation Guide Broker Mode Guide - Configuration, migration, rollback, and operations Web UI Dashboard - Real-time monitoring and audit logging Cursor Setup Claude Code Setup Codex CLI Setup Troubleshooting Tools Reference Architecture Contributing - Development guide and quality gates
See
Quick quality gate check:
make test # Run tests with coverage
make lint # Run ruff linter
make typecheck # Run mypy type checkerOr run all gates:
make test && make lint && make typecheck- Overhead: <0.01ms per transformation
- Memory: <10MB footprint
- Coverage: 91.62% test coverage
MIT License - see
- Apple's Xcode team for the MCP bridge functionality
- The MCP protocol specification
- The Cursor, Claude, and Codex teams for AI-powered development tools