Skip to content
Merged
27 changes: 14 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ If you use **Cursor**, no installation is needed — just add this to `~/.cursor
"mcpServers": {
"xcode-tools": {
"command": "uvx",
"args": ["--from", "mcpbridge-wrapper", "mcpbridge-wrapper", "--broker-spawn"]
"args": ["--from", "mcpbridge-wrapper", "mcpbridge-wrapper", "--broker"]
}
}
}
Expand All @@ -75,7 +75,7 @@ With Web UI dashboard (optional — adds real-time monitoring at http://localhos
"--from",
"mcpbridge-wrapper[webui]",
"mcpbridge-wrapper",
"--broker-spawn",
"--broker",
"--web-ui",
"--web-ui-config",
"/Users/YOUR_USERNAME/.mcpbridge_wrapper/webui.json"
Expand Down Expand Up @@ -121,18 +121,19 @@ 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](https://developer.apple.com/documentation/xcode-release-notes/xcode-26_4-release-notes).
- Use `--broker-connect` to attach to an already-running broker.
- Use `--broker-spawn` to auto-start the broker if needed.
- Use `--broker` to auto-detect — connect if daemon is alive, spawn otherwise (recommended).
- Use `--broker-connect` to attach to an already-running broker (legacy alias).
- Use `--broker-spawn` to auto-start the broker if needed (legacy alias for `--broker`).
- Add `--web-ui` (plus optional `--web-ui-config`) when you want the spawned or daemon host to own one shared dashboard endpoint.

Quick migration examples:

```bash
# Claude Code
claude mcp add --transport stdio xcode -- uvx --from mcpbridge-wrapper mcpbridge-wrapper --broker-connect
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 --broker-connect
codex mcp add xcode -- uvx --from mcpbridge-wrapper mcpbridge-wrapper --broker
```

For full start/stop/status commands, Cursor JSON snippets, troubleshooting, and
Expand All @@ -142,7 +143,7 @@ rollback to direct mode, see [Broker Mode Guide](docs/broker-mode.md).

When you run multiple MCP client processes at the same time:

- **Unified single-config pattern:** configure each client with `--broker-spawn --web-ui --web-ui-config <shared-path>`.
- **Unified single-config pattern:** configure each client with `--broker --web-ui --web-ui-config <shared-path>`.
- **Runtime expectation:** the first client that must spawn the broker starts the broker host and dashboard; later clients reuse the same broker and dashboard endpoint.
- **Ownership rule:** only one process can bind a given Web UI `host:port` (for example `127.0.0.1:8080`).
- **Connect-only behavior:** `--broker-connect` clients never start the dashboard by themselves.
Expand Down Expand Up @@ -270,7 +271,7 @@ Broker setup examples are listed first.
"mcpServers": {
"xcode-tools": {
"command": "uvx",
"args": ["--from", "mcpbridge-wrapper", "mcpbridge-wrapper", "--broker-spawn"]
"args": ["--from", "mcpbridge-wrapper", "mcpbridge-wrapper", "--broker"]
}
}
}
Expand All @@ -286,7 +287,7 @@ Broker setup examples are listed first.
"--from",
"mcpbridge-wrapper[webui]",
"mcpbridge-wrapper",
"--broker-spawn",
"--broker",
"--web-ui",
"--web-ui-config",
"/Users/YOUR_USERNAME/.mcpbridge_wrapper/webui.json"
Expand Down Expand Up @@ -383,12 +384,12 @@ Broker setup examples are listed first.
**Using uvx in broker mode (Recommended):**

```bash
claude mcp add --transport stdio xcode -- uvx --from mcpbridge-wrapper mcpbridge-wrapper --broker-spawn
claude mcp add --transport stdio xcode -- uvx --from mcpbridge-wrapper mcpbridge-wrapper --broker
```

**Using uvx in broker mode with Web UI (Optional):**
```bash
claude mcp add --transport stdio xcode -- uvx --from 'mcpbridge-wrapper[webui]' mcpbridge-wrapper --broker-spawn --web-ui --web-ui-config "$HOME/.mcpbridge_wrapper/webui.json"
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:**
Expand Down Expand Up @@ -430,12 +431,12 @@ Broker setup examples are listed first.
**Using uvx in broker mode (Recommended):**

```bash
codex mcp add xcode -- uvx --from mcpbridge-wrapper mcpbridge-wrapper --broker-spawn
codex mcp add xcode -- uvx --from mcpbridge-wrapper mcpbridge-wrapper --broker
```

**Using uvx in broker mode with Web UI (Optional):**
```bash
codex mcp add xcode -- uvx --from 'mcpbridge-wrapper[webui]' mcpbridge-wrapper --broker-spawn --web-ui --web-ui-config "$HOME/.mcpbridge_wrapper/webui.json"
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:**
Expand Down
5 changes: 4 additions & 1 deletion SPECS/ARCHIVE/INDEX.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
# mcpbridge-wrapper Tasks Archive

**Last Updated:** 2026-03-01 (P2-T2 archived)
**Last Updated:** 2026-03-01 (P2-T1 archived)

## Archived Tasks

| Task ID | Folder | Archived | Verdict |
|---------|--------|----------|---------|
| P2-T1 | [P2-T1_Replace_broker_flags_with_single_broker_flag/](P2-T1_Replace_broker_flags_with_single_broker_flag/) | 2026-03-01 | PASS |
| P2-T2 | [P2-T2_Self-healing_stale_socket_and_PID_file_recovery/](P2-T2_Self-healing_stale_socket_and_PID_file_recovery/) | 2026-03-01 | PASS |
| BUG-T8 | [BUG-T8_Fix_broker_proxy_bridge_exits_after_first_write_due_to_BaseProtocol_missing_drain_helper/](BUG-T8_Fix_broker_proxy_bridge_exits_after_first_write_due_to_BaseProtocol_missing_drain_helper/) | 2026-03-01 | PASS |
| P1-T3 | [P1-T3_Improve_MCP_settings_examples_in_README_to_present_broker_setup_first/](P1-T3_Improve_MCP_settings_examples_in_README_to_present_broker_setup_first/) | 2026-03-01 | PASS |
Expand Down Expand Up @@ -172,6 +173,7 @@

| File | Description |
|------|-------------|
| [REVIEW_P2-T1_broker_flag.md](_Historical/REVIEW_P2-T1_broker_flag.md) | Review report for P2-T1 |
| [REVIEW_P2-T2_stale_socket_recovery.md](_Historical/REVIEW_P2-T2_stale_socket_recovery.md) | Review report for P2-T2 |
| [Workplan_0.4.0.md](_Historical/Workplan_0.4.0.md) | Archived workplan snapshot for release 0.4.0 |
| [REVIEW_p1_t1_version_badge_script_tests.md](_Historical/REVIEW_p1_t1_version_badge_script_tests.md) | Review report for P1-T1 (version badge script/tests) |
Expand Down Expand Up @@ -292,6 +294,7 @@

| Date | Task ID | Action |
|------|---------|--------|
| 2026-03-01 | P2-T1 | Archived Replace --broker-spawn/--broker-connect with single --broker flag (PASS) |
| 2026-03-01 | P2-T2 | Archived Self-healing stale socket and PID file recovery (PASS) |
| 2026-03-01 | WORKPLAN | Archived Workplan_0.4.0.md to _Historical and reset SPECS/Workplan.md |
| 2026-02-28 | P15-T1 | Archived REVIEW_p15_t1_next_release_readiness report |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# P2-T1: Replace --broker-spawn/--broker-connect with single --broker flag

**Task ID:** P2-T1
**Status:** In Progress
**Priority:** P1
**Branch:** feature/P2-T1-broker-flag
**Date:** 2026-03-01

## Problem

Users currently must choose between two broker flags with overlapping and confusing semantics:
- `--broker-spawn` — auto-start daemon if absent, then connect
- `--broker-connect` — require daemon already running, connect only

This distinction is invisible to most users who simply want "broker mode". It forces them to know internal daemon lifecycle details before they can configure their MCP client.

## Solution

Add a single `--broker` flag that auto-detects the right action:
- If a live broker is already running → connect to it
- If no broker is running → spawn one, then connect

This is exactly the behavior `--broker-spawn` already implements via `BrokerProxy._spawn_broker_if_needed`. So `--broker` is a user-facing alias for `--broker-spawn`.

Keep `--broker-spawn` and `--broker-connect` working unchanged for backwards compatibility.

## Deliverables

1. **`src/mcpbridge_wrapper/__main__.py`**
- `_parse_broker_args`: recognise `--broker` as equivalent to `--broker-spawn`
- `main()`: no logic change needed (same code path as `--broker-spawn`)

2. **`README.md`**
- Replace all `--broker-spawn` in MCP settings examples with `--broker`
- Keep mention of `--broker-connect` in the reference section as a legacy alias

3. **`tests/unit/test_main.py`**
- Add tests for `--broker` in `_parse_broker_args`
- Add test for `main()` with `--broker` constructing `BrokerProxy(auto_spawn=True)`

## Acceptance Criteria

- [ ] `--broker` flag auto-connects when daemon is alive, spawns when absent (via existing proxy logic)
- [ ] `--broker-spawn` and `--broker-connect` still work unchanged
- [ ] All MCP settings examples in README use `--broker`
- [ ] All existing tests pass
- [ ] New tests for `--broker` flag pass

## Implementation Notes

- No logic change to `BrokerProxy` — `auto_spawn=True` already handles the detect-then-spawn behaviour introduced in P2-T2.
- `_parse_broker_args` returns `(broker_daemon, broker_connect, broker_spawn, remaining)`. Adding `--broker` means: set `broker_spawn = True` and `broker_connect = True`, identical to `--broker-spawn`.
- README lines to update: lines 61, 78, 273, 289, 386, 391, 433, 438 (approximate, verify exact grep output).

## Dependencies

- P2-T2 (stale socket recovery) ✅ — ensures `--broker`/`auto_spawn=True` reliably recovers from stale sockets.
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# P2-T1 Validation Report

**Task:** Replace --broker-spawn/--broker-connect with single --broker flag
**Date:** 2026-03-01
**Verdict:** PASS

## Acceptance Criteria

- [x] `--broker` flag auto-connects when daemon is alive, spawns when absent (via existing `BrokerProxy.auto_spawn=True` logic from P2-T2)
- [x] `--broker-spawn` and `--broker-connect` still work unchanged (no existing tests modified; all 678 pass)
- [x] All MCP settings examples in README use `--broker` (Cursor, Claude Code, Codex CLI sections updated)
- [x] All existing tests pass (678 passed, 2 warnings, 0 failures)
- [x] New tests for `--broker` flag pass (4 new tests added)

## Changes Made

### `src/mcpbridge_wrapper/__main__.py`
- `_parse_broker_args`: added `elif arg == "--broker"` branch — sets `broker_spawn = True` and `broker_connect = True`, identical to `--broker-spawn`
- Docstring updated to describe `--broker` as the recommended flag, `--broker-spawn`/`--broker-connect` as legacy aliases

### `README.md`
- Quick-start Cursor JSON example (×2): `--broker-spawn` → `--broker`
- Broker Mode reference section: replaced single-line `--broker-spawn` note with three-line description of `--broker` (recommended), `--broker-connect` (legacy), `--broker-spawn` (legacy alias)
- Quick migration examples for Claude Code and Codex CLI: `--broker-connect` → `--broker`
- Multi-Agent guidance: `--broker-spawn --web-ui` → `--broker --web-ui`
- Cursor Configuration section (×2): `--broker-spawn` → `--broker`
- Claude Code section (×2): `--broker-spawn` → `--broker`
- Codex CLI section (×2): `--broker-spawn` → `--broker`

### `tests/unit/test_main.py`
- `TestParseBrokerArgs`: added `test_broker_flag_sets_spawn_and_connect` and `test_broker_flag_not_forwarded_to_bridge`
- `TestMainBrokerMode`: added `test_main_broker_flag_sets_auto_spawn` and `test_main_broker_flag_success`

## Quality Gates

| Gate | Result |
|------|--------|
| `pytest tests/unit/` | 678 passed, 2 warnings |
| `ruff check src/` | All checks passed |
| `pytest --cov` | 91.41% (≥ 90% required) |
37 changes: 37 additions & 0 deletions SPECS/ARCHIVE/_Historical/REVIEW_P2-T1_broker_flag.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
## REVIEW REPORT — P2-T1: --broker flag

**Scope:** origin/main..HEAD
**Files:** 4 changed (src/__main__.py, README.md, tests/unit/test_main.py, SPECS docs)

### Summary Verdict
- [ ] Approve
- [x] Approve with comments
- [ ] Request changes
- [ ] Block

### Critical Issues

None.

### Secondary Issues

- **[Low]** `_parse_broker_args` docstring says `--broker-spawn` and `--broker-connect` are "hidden aliases" but they still appear in the README reference section (lines 125-126) as documented legacy options. The word "hidden" may confuse contributors who see them still documented. Suggestion: use "legacy aliases" consistently in the docstring (already done in inline comments; just the docstring header wording).

- **[Nit]** The quick migration example at README lines 133-136 was changed from `--broker-connect` to `--broker`. This is correct for new users but could break copy-paste instructions in existing bookmarks or external guides that showed `--broker-connect` as the quick migration command. No action required — backwards compatibility is maintained — but worth noting for CHANGELOG.

### Architectural Notes

- `--broker` maps exactly to `broker_spawn=True, broker_connect=True` — same as `--broker-spawn`. No `BrokerProxy` logic change was needed because P2-T2 already implemented liveness-aware auto-spawn. This is a clean layering: the CLI surface changed, the underlying machinery did not.
- The return type of `_parse_broker_args` remains `Tuple[bool, bool, bool, list]` — the `broker_spawn` bool now covers both `--broker` and `--broker-spawn`. A future refactor could introduce an enum for clarity, but it's not warranted now.

### Tests

- 4 new unit tests added to `TestParseBrokerArgs` and `TestMainBrokerMode`.
- All 678 unit tests pass.
- Coverage: 91.41% (≥ 90% required). No regression.
- No integration tests needed: the proxy behaviour for `auto_spawn=True` is covered by existing `TestBrokerProxy` tests from P2-T2.

### Next Steps

- No blockers. The "hidden" vs "legacy" wording is a nit and does not require a follow-up task.
- Consider adding `--broker` to CHANGELOG when next release is cut.
6 changes: 3 additions & 3 deletions SPECS/INPROGRESS/next.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
# No Active Task

**Status:** Idle — P2-T2 archived. Select the next task from `SPECS/Workplan.md`.
**Status:** Idle — P2-T1 archived. Select the next task from `SPECS/Workplan.md`.

## Recently Archived

- **P2-T1** — Replace --broker-spawn/--broker-connect with single --broker flag (2026-03-01, PASS)
- **P2-T2** — Self-healing stale socket and PID file recovery (2026-03-01, PASS)
- **BUG-T8** — Fix broker proxy bridge exits after first write due to BaseProtocol missing _drain_helper (2026-03-01, PASS)
- **P1-T3** — Improve MCP settings examples in README to present broker setup first (2026-03-01, PASS)
- **P1-T2** — Add Xcode 26.4 known issue release-notes link to README (2026-02-28, PASS)
- **P1-T1** — Add the version badge in the README.md (2026-02-28, PASS)

## Suggested Next Tasks

- **P2-T1** (P1) — Replace --broker-spawn/--broker-connect with single --broker flag
- **P2-T3** (P1) — Fix double-spawn race condition when MCP client toggles rapidly (depends on P2-T2 ✅)
- **P2-T4** (P1) — Surface broker unavailability as JSON-RPC error instead of silent timeout
- **P2-T5** (P2) — Warn or restart daemon when --web-ui requested but running broker lacks it
14 changes: 7 additions & 7 deletions SPECS/Workplan.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,20 +56,20 @@ Add new tasks using the canonical template in [TASK_TEMPLATE.md](TASK_TEMPLATE.m

### Phase 2: Broker Robustness

#### ⬜️ P2-T1: Replace --broker-spawn/--broker-connect with single --broker flag
#### ✅ P2-T1: Replace --broker-spawn/--broker-connect with single --broker flag
- **Status:** ✅ Completed (2026-03-01)
- **Description:** Users currently must choose between `--broker-spawn` (auto-start daemon if absent) and `--broker-connect` (require daemon already running). This distinction is invisible to users — they just want broker mode. Introduce a single `--broker` flag that auto-detects: connect if daemon is alive, spawn otherwise. Keep `--broker-spawn` and `--broker-connect` as hidden aliases for backwards compatibility. Update all documentation and MCP settings examples to use `--broker`.
- **Priority:** P1
- **Dependencies:** none
- **Parallelizable:** yes
- **Outputs/Artifacts:**
- `src/mcpbridge_wrapper/__main__.py` — `--broker` flag added, auto-detect logic
- `src/mcpbridge_wrapper/broker/proxy.py` — auto_spawn defaults to auto-detect
- README, DocC, and all docs updated to use `--broker`
- README updated to use `--broker` in all MCP settings examples
- **Acceptance Criteria:**
- [ ] `--broker` flag auto-connects when daemon is alive, spawns when absent
- [ ] `--broker-spawn` and `--broker-connect` still work unchanged
- [ ] All MCP settings examples in README and DocC use `--broker`
- [ ] All existing tests pass
- [x] `--broker` flag auto-connects when daemon is alive, spawns when absent
- [x] `--broker-spawn` and `--broker-connect` still work unchanged
- [x] All MCP settings examples in README use `--broker`
- [x] All existing tests pass

#### ✅ P2-T2: Self-healing stale socket and PID file recovery
- **Status:** ✅ Completed (2026-03-01)
Expand Down
Loading