Skip to content

Commit 5e04746

Browse files
committed
docs: add macOS build-from-source and app swap guide
Document how to replace /Applications/McpMux.app with a local build while preserving user data in Application Support and the keychain. Signed-off-by: crimsonsunset <jsangio1@gmail.com>
1 parent 7bf4cb1 commit 5e04746

1 file changed

Lines changed: 182 additions & 0 deletions

File tree

docs/build-from-source-macos.md

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
# Build from Source and Replace the Installed App (macOS)
2+
3+
Replace the release McpMux in `/Applications` with a locally built copy from this repo. Useful when running a fork, a feature branch, or patches that haven't shipped yet.
4+
5+
---
6+
7+
## What survives a swap
8+
9+
Replacing the `.app` bundle does **not** touch your data. McpMux stores everything outside the app:
10+
11+
| Data | Location |
12+
| ---- | -------- |
13+
| SQLite DB (spaces, servers, clients, settings) | `~/Library/Application Support/com.mcpmux.desktop/mcpmux.db` |
14+
| Per-space files | `~/Library/Application Support/com.mcpmux.desktop/spaces/` |
15+
| Logs | `~/Library/Application Support/com.mcpmux.desktop/logs/` |
16+
| Encryption master key | macOS Keychain (`com.mcpmux.desktop` service) |
17+
| OAuth tokens / credentials | Encrypted in SQLite + Keychain |
18+
19+
The app identifier (`com.mcpmux.desktop`) is unchanged between release and source builds, so the new binary reads the same data directory and keychain entries.
20+
21+
**What you might need to redo:** OAuth re-auth in Cursor/Claude Desktop if DCR or token validation changed on your branch. Your McpMux config, spaces, and server installs stay put.
22+
23+
---
24+
25+
## Prerequisites
26+
27+
From repo root (`mcp-mux/`):
28+
29+
- Rust 1.75+
30+
- Node.js 20+
31+
- pnpm 9+
32+
- Xcode Command Line Tools (`xcode-select --install`)
33+
34+
First-time setup (if deps aren't installed):
35+
36+
```bash
37+
pnpm install
38+
```
39+
40+
---
41+
42+
## Option A — Full build (recommended)
43+
44+
Rebuilds the React frontend and produces a fresh `.app` bundle. Use this when frontend or Tauri config changed, or when you want a clean bundle.
45+
46+
### 1. Quit the running app
47+
48+
```bash
49+
osascript -e 'tell application "McpMux" to quit' 2>/dev/null || true
50+
# Give it a moment to release the gateway port
51+
sleep 2
52+
```
53+
54+
### 2. Build
55+
56+
```bash
57+
cd /path/to/mcp-mux
58+
pnpm build
59+
```
60+
61+
First build: ~5–10 min. Incremental: ~1–3 min.
62+
63+
Output:
64+
65+
```
66+
target/release/bundle/macos/McpMux.app
67+
target/release/bundle/dmg/McpMux_*.dmg # optional installer artifact
68+
```
69+
70+
### 3. Backup and swap
71+
72+
```bash
73+
# Backup current install (skip if you already have a recent .bak)
74+
sudo mv /Applications/McpMux.app /Applications/McpMux.app.bak
75+
76+
# Install the new build
77+
sudo cp -R target/release/bundle/macos/McpMux.app /Applications/
78+
79+
# Fix ownership (sudo cp leaves root-owned files)
80+
sudo chown -R "$(whoami):admin" /Applications/McpMux.app
81+
```
82+
83+
### 4. Re-sign (required after manual swap)
84+
85+
macOS Gatekeeper rejects a bundle whose binary was replaced without re-signing:
86+
87+
```bash
88+
xattr -dr com.apple.quarantine /Applications/McpMux.app 2>/dev/null || true
89+
codesign --force --deep --sign - /Applications/McpMux.app
90+
```
91+
92+
### 5. Launch
93+
94+
```bash
95+
open /Applications/McpMux.app
96+
```
97+
98+
Verify: spaces, installed servers, and gateway on `localhost:45818` should look exactly as before.
99+
100+
---
101+
102+
## Option B — Binary-only swap (fast path)
103+
104+
When you changed **Rust only** (no frontend, no `tauri.conf.json` changes). Skips the Vite build and DMG step.
105+
106+
```bash
107+
osascript -e 'tell application "McpMux" to quit' 2>/dev/null || true
108+
sleep 2
109+
110+
cd /path/to/mcp-mux
111+
cargo build --release -p mcpmux
112+
113+
cp /Applications/McpMux.app/Contents/MacOS/mcpmux \
114+
/Applications/McpMux.app/Contents/MacOS/mcpmux.bak
115+
cp target/release/mcpmux /Applications/McpMux.app/Contents/MacOS/mcpmux
116+
117+
xattr -dr com.apple.quarantine /Applications/McpMux.app 2>/dev/null || true
118+
codesign --force --deep --sign - /Applications/McpMux.app
119+
120+
open /Applications/McpMux.app
121+
```
122+
123+
Keeps the existing bundle shell (icons, Info.plist, embedded frontend from last full build). Only the Rust binary updates.
124+
125+
---
126+
127+
## Rollback
128+
129+
### Full build rollback
130+
131+
```bash
132+
osascript -e 'tell application "McpMux" to quit' 2>/dev/null || true
133+
sudo rm -rf /Applications/McpMux.app
134+
sudo mv /Applications/McpMux.app.bak /Applications/McpMux.app
135+
open /Applications/McpMux.app
136+
```
137+
138+
### Binary-only rollback
139+
140+
```bash
141+
osascript -e 'tell application "McpMux" to quit' 2>/dev/null || true
142+
cp /Applications/McpMux.app/Contents/MacOS/mcpmux.bak \
143+
/Applications/McpMux.app/Contents/MacOS/mcpmux
144+
codesign --force --deep --sign - /Applications/McpMux.app
145+
open /Applications/McpMux.app
146+
```
147+
148+
---
149+
150+
## Troubleshooting
151+
152+
| Symptom | Fix |
153+
| ------- | --- |
154+
| "App is damaged" / won't open | Re-run `codesign --force --deep --sign - /Applications/McpMux.app` |
155+
| Gateway port already in use | Old process still running — `pkill -f mcpmux` then relaunch |
156+
| Cursor OAuth fails after swap | Re-trigger MCP OAuth in Cursor (DCR redirect URI validation may have changed) |
157+
| Empty app / missing UI | You used binary-only swap but frontend changed — run Option A (full build) |
158+
| Permission denied on `/Applications` | Use `sudo` for mv/cp/chown, or install to `~/Applications/` and skip sudo |
159+
160+
---
161+
162+
## One-liner (full build + swap)
163+
164+
Assumes you're in repo root and have a recent backup:
165+
166+
```bash
167+
osascript -e 'tell application "McpMux" to quit' 2>/dev/null; sleep 2 && \
168+
pnpm build && \
169+
sudo rm -rf /Applications/McpMux.app && \
170+
sudo cp -R target/release/bundle/macos/McpMux.app /Applications/ && \
171+
sudo chown -R "$(whoami):admin" /Applications/McpMux.app && \
172+
xattr -dr com.apple.quarantine /Applications/McpMux.app 2>/dev/null; \
173+
codesign --force --deep --sign - /Applications/McpMux.app && \
174+
open /Applications/McpMux.app
175+
```
176+
177+
---
178+
179+
## Related
180+
181+
- [`AGENTS.md`](../AGENTS.md) — build commands and project layout
182+
- [`CLAUDE.md`](../CLAUDE.md) — full dev environment reference

0 commit comments

Comments
 (0)