|
| 1 | +# P1-T10 — Document Xcode First-Approval Timing Race |
| 2 | + |
| 3 | +**Task ID:** P1-T10 |
| 4 | +**Priority:** P1 |
| 5 | +**Phase:** Phase 1 — Documentation |
| 6 | +**Status:** In Progress |
| 7 | + |
| 8 | +## Problem Statement |
| 9 | + |
| 10 | +When broker mode is used for the first time (or after a daemon restart), Xcode shows a per-process |
| 11 | +"Allow Connection?" dialog for the new `mcpbridge` process. If an MCP client (Zed, Cursor, Claude Code) |
| 12 | +connects and sends `tools/list` *before* Xcode grants approval, it receives an empty tools list and |
| 13 | +**caches it permanently** — showing 0 tools with a green "connected" indicator and no actionable error. |
| 14 | + |
| 15 | +The user sees: |
| 16 | +- Green connected indicator in their MCP client |
| 17 | +- 0 tools visible |
| 18 | +- No error message — just silence |
| 19 | + |
| 20 | +This is a usability trap with no obvious recovery path unless you know the root cause. |
| 21 | + |
| 22 | +### Key Facts Discovered During Live Testing |
| 23 | + |
| 24 | +1. **Per-process identity**: Each unique binary path triggers a separate Xcode dialog: |
| 25 | + - Direct wrapper (`mcpbridge-wrapper` without `--broker`) — one approval |
| 26 | + - Broker daemon (`mcpbridge-wrapper --broker-daemon`) — a *different* approval |
| 27 | + |
| 28 | +2. **Client caching**: MCP clients cache the `tools/list` response. An empty list received |
| 29 | + during the approval window is stored and served indefinitely until the user manually |
| 30 | + reloads/restarts the MCP connection. |
| 31 | + |
| 32 | +3. **Broker reconnect cycling**: During the Xcode approval dialog, the broker's upstream |
| 33 | + `xcrun mcpbridge` detects EOF and cycles. Logs show: |
| 34 | + ``` |
| 35 | + Upstream EOF detected; scheduling reconnect |
| 36 | + ``` |
| 37 | + repeated 2–3 times before Xcode approval stabilizes the connection. |
| 38 | + |
| 39 | +4. **Recovery sequence**: After clicking Allow in Xcode, MCP clients still show 0 tools |
| 40 | + because they cache the old empty response. Users must manually reload the MCP connection |
| 41 | + (disable → re-enable in client settings). |
| 42 | + |
| 43 | +## Deliverables |
| 44 | + |
| 45 | +### 1. `docs/troubleshooting.md` — New Section |
| 46 | + |
| 47 | +Add a new troubleshooting entry titled: |
| 48 | +`"MCP client shows 0 tools (green dot) after first broker connection"` |
| 49 | + |
| 50 | +Content must include: |
| 51 | +- Symptom description (green dot, 0 tools, no error) |
| 52 | +- Root cause explanation (Xcode per-process approval + client caching) |
| 53 | +- Per-process identity note (direct mode vs broker daemon are separate approvals) |
| 54 | +- Correct first-time setup sequence (start broker → watch for Xcode dialog → approve → then reload client) |
| 55 | +- Client-specific recovery steps: |
| 56 | + - Zed: disable MCP in settings → save → enable → save, wait for spinner |
| 57 | + - Cursor: open MCP settings → disconnect → reconnect (or restart Cursor) |
| 58 | + - Claude Code: `claude mcp remove xcode && claude mcp add ...` (or session restart) |
| 59 | +- Broker log diagnostic hint (look for `Upstream EOF detected`) |
| 60 | + |
| 61 | +Place this section after the existing `"Found 0 tools"` section (line ~5 of troubleshooting.md) |
| 62 | +since it is the next most common variation. |
| 63 | + |
| 64 | +### 2. `README.md` — Expand Known Issues Entry |
| 65 | + |
| 66 | +The existing entry (line 618) reads: |
| 67 | +> **Broker cold-start — first use requires Xcode approval:** [brief text] |
| 68 | +
|
| 69 | +Expand it to include: |
| 70 | +- The client-caching consequence (empty list gets cached permanently) |
| 71 | +- The green-dot-with-0-tools symptom |
| 72 | +- The per-process identity note |
| 73 | +- A link to the new troubleshooting section: `[Troubleshooting: Xcode first-approval timing race](docs/troubleshooting.md#mcp-client-shows-0-tools-green-dot-after-first-broker-connection)` |
| 74 | + |
| 75 | +### 3. `Sources/XcodeMCPWrapper/Documentation.docc/Troubleshooting.md` — Mirror |
| 76 | + |
| 77 | +Add the same new section to the DocC troubleshooting file (mirrors `docs/troubleshooting.md`), |
| 78 | +using DocC link syntax where needed. |
| 79 | + |
| 80 | +## Acceptance Criteria |
| 81 | + |
| 82 | +- [ ] `docs/troubleshooting.md` contains a new section for the Xcode first-approval timing race |
| 83 | +- [ ] The new section includes: symptom, root cause, per-process identity note, first-time setup |
| 84 | + sequence, and recovery steps for at least Zed and Cursor |
| 85 | +- [ ] `README.md` Known Issues entry for broker cold-start is expanded with client-caching |
| 86 | + consequence and links to the new troubleshooting section |
| 87 | +- [ ] DocC `Troubleshooting.md` mirrors the new section |
| 88 | +- [ ] No existing documentation is removed or broken |
| 89 | +- [ ] All links resolve correctly |
| 90 | + |
| 91 | +## Implementation Notes |
| 92 | + |
| 93 | +- Insert the new troubleshooting section near the top of `docs/troubleshooting.md`, after |
| 94 | + the existing "Found 0 tools" section (around line 31), since it is a variant of that symptom. |
| 95 | +- The DocC file uses `##` headings for its sections — match that style. |
| 96 | +- The README Known Issues list uses bold key phrases followed by colon — match that style. |
| 97 | +- Anchor for the new troubleshooting section (for deep linking from README): |
| 98 | + `#mcp-client-shows-0-tools-green-dot-after-first-broker-connection` |
| 99 | + |
| 100 | +## Out of Scope |
| 101 | + |
| 102 | +- Code changes to fix the race (tracked as P4-T2) |
| 103 | +- Changes to broker-mode.md (that doc covers operational flows; troubleshooting lives here) |
0 commit comments