Skip to main content
Glama
qianshang

xcode-mcp-bridge

by qianshang
README.md
# Xcode MCP Bridge

[![License](https://img.shields.io/github/license/qianshang/xcode-mcp-bridge)](LICENSE)
[![GitHub stars](https://img.shields.io/github/stars/qianshang/xcode-mcp-bridge)](https://github.com/qianshang/xcode-mcp-bridge/stargazers)

让 Xcode 的 `mcpbridge` 以**唯一进程**长期稳定驻留,通过 HTTP/SSE 暴露给任意 MCP 客户端(如 WorkBuddy、Claude 等),消除反复授权弹窗。

## 背景:解决的两个问题

Xcode 自带的 `mcpbridge` 有两个缺陷,本桥针对性地修复:

| # | mcpbridge 缺陷 | 桥的解法 |
|---|---|---|
| 1 | 对 `2025-06-18` 协议的 `initialize` 响应后会**主动退出**(exit 0) | 桥启动时用 `2024-11-05` 协议自初始化并缓存能力;客户端发来的 `initialize` 由桥**本地应答**(回显客户端协议版本),`mcpbridge` 进程永不退出 |
| 2 | 不认识 `ping`(返回 `unknown method 'ping'`) | 桥**本地应答** `ping`,不转发 |

**效果**:`mcpbridge` 进程永不换 PID → Xcode 只授权一次 → 不再反复弹窗。

## 特性

- 🔌 **单例 SSE 桥**:一个 `mcpbridge` 子进程服务多个 SSE 客户端连接
- 🪶 **零依赖**:仅使用 Node 内置模块(`http` / `child_process` / `crypto`)
- 🔁 **常驻自愈**:launchd `KeepAlive` 自动重启;手动模式可搭配 watchdog
- 📍 **位置自适应**:所有脚本路径由自身位置推导,clone 到任意目录直接可用

## 工作原理

```
MCP 客户端 (WorkBuddy / Claude / 其他)
        │  HTTP + SSE (127.0.0.1:3811)
        ▼
┌──────────────────────────────────────┐
│  single-sse-bridge.js                │  ← 本地应答 initialize / ping
│  (Node,零第三方依赖)                  │     转发其余 JSON-RPC
└──────────────────┬───────────────────┘
                   │  stdio (JSON-RPC 2.0, 协议 2024-11-05)
                   ▼
┌──────────────────────────────────────┐
│  Xcode mcpbridge 子进程(唯一)        │  ← 永不换 PID
└──────────────────────────────────────┘
```

握手流程:

1. 桥启动 → 用 `2024-11-05` 协议向 `mcpbridge` 发送 `initialize` 并**缓存**能力/服务信息
2. 桥向 `mcpbridge` 发送 `notifications/initialized`(协议要求,否则它不处理请求)
3. 客户端连上 `/sse` → 客户端发 `initialize` → **桥本地应答**(回显客户端协议版本)
4. 客户端发 `ping` → **桥本地应答** `{}`
5. 其余请求(`tools/list` 等)→ 转发 `mcpbridge`,响应按 JSON-RPC id 回路由到对应会话

## 目录结构

```
xcode-mcp-bridge/
├── src/
│   └── single-sse-bridge.js            # 桥主程序(零依赖)
├── scripts/
│   ├── install.sh                      # 注册 launchd 常驻服务(推荐)
│   ├── start.sh                        # 手动启动(nohup 后台)
│   ├── stop.sh                         # 停止
│   ├── status.sh                       # 健康检查
│   └── xcode-mcp-bridge-watchdog.sh    # 手动模式看门狗(每 8s 自愈)
├── launchd/
│   └── com.user.xcode-mcp-bridge.plist # launchd 模板(占位符,install.sh 渲染)
├── logs/                               # 运行日志(已被 .gitignore 忽略)
├── package.json                        # 元数据 + npm scripts(无第三方依赖)
├── CHANGELOG.md
└── README.md
```

## 环境要求

- macOS(需 Xcode,含 `Contents/Developer/usr/bin/mcpbridge`)
- Node.js **>= 18**(推荐 LTS 20;脚本自动探测 `node`,兼容 nvm)

## 快速开始

### 0. 获取代码

```bash
git clone git@github.com:qianshang/xcode-mcp-bridge.git
cd xcode-mcp-bridge
```

### 1. 安装(launchd 常驻模式,推荐)

```bash
bash scripts/install.sh
```

脚本会自动完成:探测 node 绝对路径 → 渲染 plist 到 `~/Library/LaunchAgents/` → `launchctl bootstrap` → 健康检查。

### 2. 验证

```bash
curl http://127.0.0.1:3811/healthz   # 期望输出: ok
bash scripts/status.sh               # 期望输出: bridge OK
```

### 3. Xcode 侧配置(两步 GUI)

1. **Xcode > Settings > Intelligence > Model Context Protocol**,打开 *"Allow external agents to use Xcode tools"*
2. 首次连接时,Xcode 弹出的权限对话框点 **Allow**(之后不再反复弹窗)

### 4. 在 MCP 客户端中接入

SSE 端点:`http://127.0.0.1:3811/sse`

## 常用命令

| 命令 | 说明 |
|---|---|
| `bash scripts/install.sh` | 注册 / 重装 launchd 常驻服务 |
| `bash scripts/start.sh` | 手动启动(后台 nohup) |
| `bash scripts/stop.sh` | 停止 |
| `bash scripts/status.sh` | 健康检查 |
| `nohup bash scripts/xcode-mcp-bridge-watchdog.sh &` | 手动模式自愈看门狗 |

> 说明:`start.sh` / `watchdog.sh` 通过 `NODE=/path/to/node` 环境变量可指定 Node 可执行文件。

## 常见问题

**Q: healthz 返回 DOWN?**
A: 先确认 Xcode 已打开;再查看 `logs/bridge.log`。launchd 模式下若持续失败可运行 `bash scripts/start.sh` 观察输出。

**Q: 端口被占用?**
A: `lsof -i :3811` 查看占用进程,确认没有旧桥进程残留后重启。

**Q: 仍反复弹授权框?**
A: 确认只有一个桥进程(`bash scripts/status.sh` 正常 + `pgrep -f single-sse-bridge` 仅 1 个)。多个桥进程会导致 `mcpbridge` 换 PID。

## 开源许可

[MIT](LICENSE)

## 贡献

欢迎提交 [Issue](https://github.com/qianshang/xcode-mcp-bridge/issues) 与 [PR](https://github.com/qianshang/xcode-mcp-bridge/pulls)。