diff --git a/README.md b/README.md index 117603b..5174e2c 100644 --- a/README.md +++ b/README.md @@ -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"] } } } @@ -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" @@ -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 @@ -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 `. +- **Unified single-config pattern:** configure each client with `--broker --web-ui --web-ui-config `. - **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. @@ -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"] } } } @@ -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" @@ -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:** @@ -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:** diff --git a/SPECS/ARCHIVE/INDEX.md b/SPECS/ARCHIVE/INDEX.md index c65b74e..e5f9526 100644 --- a/SPECS/ARCHIVE/INDEX.md +++ b/SPECS/ARCHIVE/INDEX.md @@ -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 | @@ -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) | @@ -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 | diff --git a/SPECS/ARCHIVE/P2-T1_Replace_broker_flags_with_single_broker_flag/P2-T1_Replace_broker_flags_with_single_broker_flag.md b/SPECS/ARCHIVE/P2-T1_Replace_broker_flags_with_single_broker_flag/P2-T1_Replace_broker_flags_with_single_broker_flag.md new file mode 100644 index 0000000..bfa2706 --- /dev/null +++ b/SPECS/ARCHIVE/P2-T1_Replace_broker_flags_with_single_broker_flag/P2-T1_Replace_broker_flags_with_single_broker_flag.md @@ -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. diff --git a/SPECS/ARCHIVE/P2-T1_Replace_broker_flags_with_single_broker_flag/P2-T1_Validation_Report.md b/SPECS/ARCHIVE/P2-T1_Replace_broker_flags_with_single_broker_flag/P2-T1_Validation_Report.md new file mode 100644 index 0000000..e27c14e --- /dev/null +++ b/SPECS/ARCHIVE/P2-T1_Replace_broker_flags_with_single_broker_flag/P2-T1_Validation_Report.md @@ -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) | diff --git a/SPECS/ARCHIVE/_Historical/REVIEW_P2-T1_broker_flag.md b/SPECS/ARCHIVE/_Historical/REVIEW_P2-T1_broker_flag.md new file mode 100644 index 0000000..aca8e62 --- /dev/null +++ b/SPECS/ARCHIVE/_Historical/REVIEW_P2-T1_broker_flag.md @@ -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. diff --git a/SPECS/INPROGRESS/next.md b/SPECS/INPROGRESS/next.md index 1bb60f4..fc558bf 100644 --- a/SPECS/INPROGRESS/next.md +++ b/SPECS/INPROGRESS/next.md @@ -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 diff --git a/SPECS/Workplan.md b/SPECS/Workplan.md index 52eb7d0..6a6e998 100644 --- a/SPECS/Workplan.md +++ b/SPECS/Workplan.md @@ -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) diff --git a/Sources/XcodeMCPWrapper/Documentation.docc/XcodeMCPWrapper.md b/Sources/XcodeMCPWrapper/Documentation.docc/XcodeMCPWrapper.md index 0d73055..2283b1b 100644 --- a/Sources/XcodeMCPWrapper/Documentation.docc/XcodeMCPWrapper.md +++ b/Sources/XcodeMCPWrapper/Documentation.docc/XcodeMCPWrapper.md @@ -53,7 +53,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"] } } } @@ -70,7 +70,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" @@ -115,18 +115,19 @@ Restart Cursor and you're done. For other clients or installation methods, read Broker mode lets short-lived MCP sessions share one persistent upstream bridge. - **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). -- `--broker-connect`: attach to an already-running broker. -- `--broker-spawn`: best-effort auto-start, then connect. +- `--broker`: auto-detect — connect if daemon is alive, spawn otherwise (recommended). +- `--broker-connect`: attach to an already-running broker (legacy alias). +- `--broker-spawn`: 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 troubleshooting and rollback details, see , @@ -136,7 +137,7 @@ For troubleshooting and rollback details, see , 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 `. +- **Unified single-config pattern:** configure each client with `--broker --web-ui --web-ui-config `. - **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. @@ -220,7 +221,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"] } } } @@ -236,7 +237,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" @@ -332,12 +333,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:** @@ -379,12 +380,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:** diff --git a/src/mcpbridge_wrapper/__main__.py b/src/mcpbridge_wrapper/__main__.py index 4a1663a..37bf017 100644 --- a/src/mcpbridge_wrapper/__main__.py +++ b/src/mcpbridge_wrapper/__main__.py @@ -283,9 +283,15 @@ def _parse_broker_args( ) -> Tuple[bool, bool, bool, list]: """Parse broker arguments from command-line args. - Extracts ``--broker-daemon``, ``--broker-connect``, and ``--broker-spawn`` - flags and returns them along with the remaining args to forward to the - bridge. Broker-only flags are *never* forwarded to ``xcrun mcpbridge``. + Extracts ``--broker-daemon``, ``--broker-connect``, ``--broker-spawn``, + and ``--broker`` flags and returns them along with the remaining args to + forward to the bridge. Broker-only flags are *never* forwarded to + ``xcrun mcpbridge``. + + ``--broker`` is the recommended flag: it auto-detects whether a daemon is + already running and spawns one if needed (equivalent to ``--broker-spawn``). + ``--broker-spawn`` and ``--broker-connect`` are kept as hidden aliases for + backwards compatibility. Args: args: Command-line arguments list. @@ -302,9 +308,14 @@ def _parse_broker_args( if arg == "--broker-daemon": broker_daemon = True elif arg == "--broker-connect": + # Legacy alias: connect-only (no auto-spawn). broker_connect = True elif arg == "--broker-spawn": - # --broker-spawn implies --broker-connect + # Legacy alias: auto-spawn then connect. + broker_spawn = True + broker_connect = True + elif arg == "--broker": + # Recommended flag: auto-detect (spawn if needed, then connect). broker_spawn = True broker_connect = True else: diff --git a/tests/unit/test_main.py b/tests/unit/test_main.py index cc86cef..2339a51 100644 --- a/tests/unit/test_main.py +++ b/tests/unit/test_main.py @@ -942,6 +942,22 @@ def test_broker_daemon_not_in_remaining(self): assert "--broker-daemon" not in remaining assert remaining == ["--some-bridge-arg"] + def test_broker_flag_sets_spawn_and_connect(self): + from mcpbridge_wrapper.__main__ import _parse_broker_args + + daemon, connect, spawn, remaining = _parse_broker_args(["--broker"]) + assert daemon is False + assert connect is True + assert spawn is True + assert remaining == [] + + def test_broker_flag_not_forwarded_to_bridge(self): + from mcpbridge_wrapper.__main__ import _parse_broker_args + + daemon, connect, spawn, remaining = _parse_broker_args(["--broker", "--some-bridge-arg"]) + assert "--broker" not in remaining + assert remaining == ["--some-bridge-arg"] + class TestMainBrokerMode: """Tests for main() broker proxy mode branch.""" @@ -978,6 +994,41 @@ def test_main_broker_connect_timeout_returns_1(self): assert result == 1 + def test_main_broker_flag_sets_auto_spawn(self): + """main() with --broker constructs BrokerProxy(auto_spawn=True).""" + argv = ["mcpbridge-wrapper", "--broker"] + with patch("mcpbridge_wrapper.__main__.sys.argv", argv), patch( + "mcpbridge_wrapper.broker.proxy.BrokerProxy" + ) as mock_proxy_cls, patch( + "mcpbridge_wrapper.broker.types.BrokerConfig" + ) as mock_cfg_cls, patch("asyncio.run") as mock_run: + mock_cfg_cls.default.return_value = MagicMock() + mock_proxy_cls.return_value = MagicMock() + mock_run.return_value = None + + result = main() + + assert result == 0 + _, kwargs = mock_proxy_cls.call_args + assert kwargs.get("auto_spawn") is True + + def test_main_broker_flag_success(self): + """main() with --broker runs proxy and returns 0.""" + argv = ["mcpbridge-wrapper", "--broker"] + with patch("mcpbridge_wrapper.__main__.sys.argv", argv), patch( + "mcpbridge_wrapper.broker.proxy.BrokerProxy" + ) as mock_proxy_cls, patch( + "mcpbridge_wrapper.broker.types.BrokerConfig" + ) as mock_cfg_cls, patch("asyncio.run") as mock_run: + mock_cfg_cls.default.return_value = MagicMock() + mock_proxy_cls.return_value = MagicMock() + mock_run.return_value = None + + result = main() + + assert result == 0 + mock_run.assert_called_once() + def test_main_broker_spawn_sets_auto_spawn(self): """main() with --broker-spawn constructs BrokerProxy(auto_spawn=True).""" argv = ["mcpbridge-wrapper", "--broker-spawn"]