|
| 1 | +# MCP Stability Implementation Plan |
| 2 | + |
| 3 | +> **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking. |
| 4 | +
|
| 5 | +**Goal:** Make MCP stdio transport standards-compliant and align runtime lifecycle behavior with app startup and settings actions. |
| 6 | + |
| 7 | +**Architecture:** Keep the current MCP client and manager structure, but move lifecycle authority into `MCPServerManager`, remove duplicate startup connects, and make the Rust stdio transport use standard framed MCP messages. Settings actions will call explicit connect, disconnect, and test flows instead of relying on indirect store behavior. |
| 8 | + |
| 9 | +**Tech Stack:** Tauri, Rust, TypeScript, Zustand, Next.js |
| 10 | + |
| 11 | +--- |
| 12 | + |
| 13 | +## Chunk 1: Stdio Framing |
| 14 | + |
| 15 | +### Task 1: Add failing Rust tests for MCP stdio framing |
| 16 | + |
| 17 | +**Files:** |
| 18 | +- Modify: `src-tauri/src/mcp.rs` |
| 19 | +- Test: `src-tauri/src/mcp.rs` |
| 20 | + |
| 21 | +- [ ] **Step 1: Write failing tests for frame encoding and decoding** |
| 22 | + |
| 23 | +Add unit tests for: |
| 24 | +- writing a `Content-Length` header plus JSON body |
| 25 | +- reading a complete framed message |
| 26 | +- rejecting malformed or truncated input |
| 27 | + |
| 28 | +- [ ] **Step 2: Run Rust tests to verify the new framing tests fail** |
| 29 | + |
| 30 | +Run: `cargo test mcp --manifest-path src-tauri/Cargo.toml` |
| 31 | +Expected: FAIL because framing helpers do not exist yet |
| 32 | + |
| 33 | +- [ ] **Step 3: Implement minimal framing helpers** |
| 34 | + |
| 35 | +Add small helper functions in `src-tauri/src/mcp.rs` that: |
| 36 | +- encode a JSON body into a framed message |
| 37 | +- parse headers from a reader |
| 38 | +- read the exact byte length advertised by `Content-Length` |
| 39 | + |
| 40 | +- [ ] **Step 4: Refactor stdio request/response to use framing** |
| 41 | + |
| 42 | +Update `send_mcp_message` so it writes framed payloads and reads framed responses instead of newline-delimited JSON. |
| 43 | + |
| 44 | +- [ ] **Step 5: Run Rust tests to verify framing passes** |
| 45 | + |
| 46 | +Run: `cargo test mcp --manifest-path src-tauri/Cargo.toml` |
| 47 | +Expected: PASS for framing tests |
| 48 | + |
| 49 | +- [ ] **Step 6: Commit** |
| 50 | + |
| 51 | +```bash |
| 52 | +git add src-tauri/src/mcp.rs |
| 53 | +git commit -m "fix: use framed stdio transport for mcp" |
| 54 | +``` |
| 55 | + |
| 56 | +## Chunk 2: Single Initialization Path |
| 57 | + |
| 58 | +### Task 2: Remove duplicate auto-connect behavior |
| 59 | + |
| 60 | +**Files:** |
| 61 | +- Modify: `src/stores/mcp.ts` |
| 62 | +- Modify: `src/lib/mcp/init.ts` |
| 63 | +- Modify: `src/lib/mcp/integration.ts` |
| 64 | + |
| 65 | +- [ ] **Step 1: Write a failing lifecycle test or isolate logic for direct verification** |
| 66 | + |
| 67 | +If an existing TS test harness is present, add a test showing enabled servers are connected once on startup. If not, extract the startup path into a function small enough to verify by inspection and command-level validation. |
| 68 | + |
| 69 | +- [ ] **Step 2: Run the targeted verification and confirm the duplicate-connect case is still possible** |
| 70 | + |
| 71 | +Run the smallest available validation command for the chosen test or check path. |
| 72 | +Expected: existing logic still shows two startup connect paths in code. |
| 73 | + |
| 74 | +- [ ] **Step 3: Remove store-side delayed auto-connect** |
| 75 | + |
| 76 | +Change `src/stores/mcp.ts` so `initMcpData()` only loads persisted config and marks initialization complete. |
| 77 | + |
| 78 | +- [ ] **Step 4: Keep exactly one startup connection path** |
| 79 | + |
| 80 | +Make `src/lib/mcp/init.ts` the only startup entry point that connects enabled servers through the manager. |
| 81 | + |
| 82 | +- [ ] **Step 5: Run verification** |
| 83 | + |
| 84 | +Run: `cargo test --manifest-path src-tauri/Cargo.toml` |
| 85 | +Expected: PASS |
| 86 | + |
| 87 | +- [ ] **Step 6: Commit** |
| 88 | + |
| 89 | +```bash |
| 90 | +git add src/stores/mcp.ts src/lib/mcp/init.ts src/lib/mcp/integration.ts |
| 91 | +git commit -m "fix: remove duplicate mcp startup connections" |
| 92 | +``` |
| 93 | + |
| 94 | +## Chunk 3: Lifecycle Cleanup for Disable and Delete |
| 95 | + |
| 96 | +### Task 3: Ensure settings actions disconnect active servers |
| 97 | + |
| 98 | +**Files:** |
| 99 | +- Modify: `src/stores/mcp.ts` |
| 100 | +- Modify: `src/lib/mcp/server-manager.ts` |
| 101 | +- Modify: `src/app/core/setting/mcp/server-config-dialog.tsx` |
| 102 | + |
| 103 | +- [ ] **Step 1: Add a failing test or verification target for disconnect-on-disable/delete** |
| 104 | + |
| 105 | +Cover or explicitly validate: |
| 106 | +- deleting a connected server disconnects it first |
| 107 | +- disabling a connected server disconnects it |
| 108 | +- editing an enabled connected server reconnects with updated config |
| 109 | + |
| 110 | +- [ ] **Step 2: Run the verification and observe the current failure case** |
| 111 | + |
| 112 | +Expected: existing flow updates config without guaranteed disconnect. |
| 113 | + |
| 114 | +- [ ] **Step 3: Implement explicit lifecycle helpers** |
| 115 | + |
| 116 | +Add or refine `disconnectServer`, `reconnectServer`, and related helpers in `src/lib/mcp/server-manager.ts` so callers can safely perform settings-driven lifecycle actions. |
| 117 | + |
| 118 | +- [ ] **Step 4: Update settings save and store behavior** |
| 119 | + |
| 120 | +Make save, disable, and delete flows explicitly disconnect or reconnect through the manager before finalizing persisted state. |
| 121 | + |
| 122 | +- [ ] **Step 5: Run verification** |
| 123 | + |
| 124 | +Run: `cargo test --manifest-path src-tauri/Cargo.toml` |
| 125 | +Expected: PASS |
| 126 | + |
| 127 | +- [ ] **Step 6: Commit** |
| 128 | + |
| 129 | +```bash |
| 130 | +git add src/stores/mcp.ts src/lib/mcp/server-manager.ts src/app/core/setting/mcp/server-config-dialog.tsx |
| 131 | +git commit -m "fix: clean up mcp connections on settings changes" |
| 132 | +``` |
| 133 | + |
| 134 | +## Chunk 4: Non-Destructive Connection Tests |
| 135 | + |
| 136 | +### Task 4: Make single and batch connection tests accurate and non-destructive |
| 137 | + |
| 138 | +**Files:** |
| 139 | +- Modify: `src/lib/mcp/server-manager.ts` |
| 140 | +- Modify: `src/app/core/setting/mcp/server-list.tsx` |
| 141 | +- Modify: `src/app/core/setting/mcp/json-import-dialog.tsx` |
| 142 | + |
| 143 | +- [ ] **Step 1: Write or define the failing verification target for test-all behavior** |
| 144 | + |
| 145 | +Cover: |
| 146 | +- test-all does not reconnect active servers |
| 147 | +- batch results report failures accurately |
| 148 | + |
| 149 | +- [ ] **Step 2: Run verification to confirm the current destructive behavior** |
| 150 | + |
| 151 | +Expected: current implementation uses `reconnectServer` and unconditional success messaging. |
| 152 | + |
| 153 | +- [ ] **Step 3: Implement non-destructive batch testing** |
| 154 | + |
| 155 | +Add a helper that runs `testConnection` per enabled server and returns counts or per-server results without mutating active connections. |
| 156 | + |
| 157 | +- [ ] **Step 4: Update settings UI messaging** |
| 158 | + |
| 159 | +Make `server-list.tsx` show accurate completion messaging for: |
| 160 | +- all success |
| 161 | +- partial success |
| 162 | +- all failure |
| 163 | + |
| 164 | +- [ ] **Step 5: Run verification** |
| 165 | + |
| 166 | +Run: `cargo test --manifest-path src-tauri/Cargo.toml` |
| 167 | +Expected: PASS |
| 168 | + |
| 169 | +- [ ] **Step 6: Commit** |
| 170 | + |
| 171 | +```bash |
| 172 | +git add src/lib/mcp/server-manager.ts src/app/core/setting/mcp/server-list.tsx src/app/core/setting/mcp/json-import-dialog.tsx |
| 173 | +git commit -m "fix: make mcp connection tests non-destructive" |
| 174 | +``` |
| 175 | + |
| 176 | +## Chunk 5: Final Verification |
| 177 | + |
| 178 | +### Task 5: Validate the integrated result |
| 179 | + |
| 180 | +**Files:** |
| 181 | +- Modify: `docs/superpowers/specs/2026-03-17-mcp-stability-design.md` |
| 182 | +- Modify: `docs/superpowers/plans/2026-03-17-mcp-stability.md` |
| 183 | + |
| 184 | +- [ ] **Step 1: Run Rust verification** |
| 185 | + |
| 186 | +Run: `cargo test --manifest-path src-tauri/Cargo.toml` |
| 187 | +Expected: PASS |
| 188 | + |
| 189 | +- [ ] **Step 2: Run frontend verification** |
| 190 | + |
| 191 | +Run: `pnpm lint` |
| 192 | +Expected: PASS, or document the existing nested-worktree ESLint conflict if it still blocks execution |
| 193 | + |
| 194 | +- [ ] **Step 3: Review the diff for MCP-only scope** |
| 195 | + |
| 196 | +Run: `git diff --stat` |
| 197 | +Expected: changes limited to MCP transport, lifecycle, settings, and docs |
| 198 | + |
| 199 | +- [ ] **Step 4: Commit final polish if needed** |
| 200 | + |
| 201 | +```bash |
| 202 | +git add docs/superpowers/specs/2026-03-17-mcp-stability-design.md docs/superpowers/plans/2026-03-17-mcp-stability.md |
| 203 | +git commit -m "docs: add mcp stability design and plan" |
| 204 | +``` |
0 commit comments