Skip to content

Commit fd0f440

Browse files
committed
docs(workspaces): self-intro hints + manual test guide
- Approval sheet and the Apps page's "Routing is workspace-driven" panel now point users at "Connect apps to this folder" when a client (e.g. Cursor) doesn't report the folder reliably. - Add a manual test guide for header routing, the per-workspace installer, and the disable-auth toggle, with log lines to look for. Claude-Session: https://claude.ai/code/session_01Baan9JmzR43uxxRUh7CAMF Signed-off-by: Mohammod Al Amin Ashik <maa.ashik00@gmail.com>
1 parent ee995b6 commit fd0f440

3 files changed

Lines changed: 124 additions & 1 deletion

File tree

apps/desktop/src/features/clients/ClientsPage.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,10 @@ function SidePanel({
565565
<p className="text-sm font-semibold">Routing is workspace-driven</p>
566566
<p className="mt-1 text-xs text-[rgb(var(--muted))]">
567567
When this client reports a folder as an MCP root, mcpmux uses the matching Workspace
568-
binding to pick the Space and FeatureSet.
568+
binding to pick the Space and FeatureSet. If it doesn&apos;t report the folder
569+
reliably (e.g. Cursor), open the folder in Workspaces and{' '}
570+
<span className="font-medium text-[rgb(var(--foreground))]">Connect apps to this folder</span>{' '}
571+
to auto-write its config with a workspace header.
569572
</p>
570573
<button
571574
onClick={onOpenWorkspaces}

apps/desktop/src/features/workspaces/WorkspaceBindingSheet.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,15 @@ export function WorkspaceBindingSheet() {
245245
</div>
246246
</div>
247247
</div>
248+
249+
{/* Self-intro: point at the per-workspace installer so apps that
250+
don't report this folder (e.g. Cursor) still route here. */}
251+
<p className="mt-3 text-xs text-[rgb(var(--muted))]" data-testid="binding-sheet-install-hint">
252+
Tip: app not routing here? In the Workspaces tab, open this folder and{' '}
253+
<span className="font-medium text-[rgb(var(--foreground))]">Connect apps to this folder</span>{' '}
254+
to write its config with a workspace header — it works even when the app doesn&apos;t
255+
report the folder.
256+
</p>
248257
</div>
249258

250259
<div className="flex-1 overflow-y-auto px-8 pb-6 space-y-6">
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# Manual test — per-workspace routing via `X-Mcpmux-Workspace`
2+
3+
Covers the feature added on `feat/workspace-header-mapping`:
4+
5+
1. Deterministic per-workspace routing via the `X-Mcpmux-Workspace` header
6+
(fixes Cursor reporting the wrong/another workspace root).
7+
2. One-click per-workspace client config install.
8+
3. System-wide "disable authentication" toggle.
9+
10+
Automated coverage exists for the resolver, the config writer, the gateway
11+
state toggle, and the install panel (see _Automated tests_ at the end). The
12+
steps below verify the end-to-end behavior that automation can't — a real
13+
client connecting through the gateway.
14+
15+
## Prerequisites
16+
17+
- `pnpm dev` (desktop app + gateway) running.
18+
- Two real workspace folders, e.g. `D:\proj\alpha` and `D:\proj\beta`.
19+
- Cursor installed (the client this feature primarily targets). VS Code /
20+
Claude Code are good controls — they already route correctly via roots.
21+
22+
---
23+
24+
## A. Header routing fixes the wrong-workspace bug
25+
26+
**Goal:** prove the header overrides what the client reports.
27+
28+
1. In the app, **Workspaces → New mapping**: map `D:\proj\alpha` to a Space +
29+
a distinctive FeatureSet (call it _Alpha FS_, with a tool only it has).
30+
Map `D:\proj\beta` to a different _Beta FS_.
31+
2. In the `D:\proj\alpha` mapping, open **Connect apps to this folder**, tick
32+
**Cursor**, and click **Install into 1 app**. Confirm
33+
`D:\proj\alpha\.cursor\mcp.json` now contains an `mcpmux` entry with
34+
`"headers": { "X-Mcpmux-Workspace": "D:\\proj\\alpha" }`.
35+
3. Repeat for `D:\proj\beta`.
36+
4. Open **both** folders in Cursor (two windows). In each, ask the agent to
37+
list mcpmux tools (or invoke `@mux`).
38+
39+
**Expected:** the `alpha` window sees _Alpha FS_ tools; the `beta` window sees
40+
_Beta FS_ tools. Before this change, both windows showed whichever folder
41+
Cursor happened to report — the bug.
42+
43+
**Verify in logs** (`%LOCALAPPDATA%\com.mcpmux.desktop\logs\mcpmux.<date>.log`):
44+
45+
- `[SessionRoots] pinned explicit workspace root from X-Mcpmux-Workspace header`
46+
with the right path per session.
47+
- `[FeatureSetResolver] resolved via WorkspaceBinding workspace_root=d:\proj\alpha`
48+
(and `…\beta`) — note the header path wins even if Cursor also reports a
49+
different root.
50+
51+
---
52+
53+
## B. One-click install — create and extend
54+
55+
1. **New folder, no config:** pick a fresh folder with no `.cursor/` etc.
56+
Install for Cursor + Claude Code + VS Code. Confirm three files are
57+
**created**: `.cursor/mcp.json`, `.mcp.json`, `.vscode/mcp.json`, each with
58+
the correct top-level key (`mcpServers` / `mcpServers` / `servers`) and the
59+
workspace header.
60+
2. **Existing config, preserved:** in a folder that already has a
61+
`.cursor/mcp.json` with another server, install again. Confirm:
62+
- the other server is still present,
63+
- an `mcpmux` entry was added/updated,
64+
- a `mcp.json.mcpmux-bak` backup was written.
65+
3. **Non-JSON guard:** put a `//` comment in `.cursor/mcp.json`, install, and
66+
confirm that client reports an **error** ("not plain JSON…") and the file is
67+
left untouched (no clobber).
68+
4. **Copy config:** click the copy icon on a client row, paste — you get a full
69+
`{ "<key>": { "mcpmux": { … } } }` snippet for that client.
70+
71+
---
72+
73+
## C. Disable authentication
74+
75+
1. **Settings → Security → Disable authentication: ON.** Toast confirms.
76+
2. Connect a client whose config has **no** `Authorization` header (the
77+
installer writes none) — e.g. the Cursor config from step A.
78+
79+
**Expected:** the client connects and resolves normally (no 401). Logs show
80+
`→ MCP` lines with `client=mcpmux-anon…` for tokenless requests.
81+
82+
3. **Toggle OFF again.** A tokenless client now gets `401`; a client with a
83+
valid access key still connects (lenient — a valid token is always honored).
84+
4. Restart the app with the toggle ON and confirm it persists (seeded into the
85+
gateway at startup).
86+
87+
The install panel's inline **Disable authentication** button (shown when auth
88+
is on) performs the same toggle without leaving the flow.
89+
90+
---
91+
92+
## D. Self-introductory hints (discoverability)
93+
94+
- **Approval sheet** (open an unmapped folder in a connected app): shows the
95+
"Connect apps to this folder" tip.
96+
- **Apps page → a client → "Routing is workspace-driven":** mentions installing
97+
a per-workspace config when a client doesn't report folders reliably.
98+
- **Install panel:** shows the auth state and offers to disable it inline.
99+
100+
---
101+
102+
## Automated tests (run before manual)
103+
104+
```bash
105+
pnpm test:rust:int # resolver: pinned-header routing, override, fallback
106+
pnpm test:rust:unit # session_roots pin/shadow/clear; GatewayState auth toggle;
107+
# workspace_install merge/create/extend/backup
108+
pnpm test:ts -- WorkspaceInstallPanel
109+
```
110+
111+
All should pass.

0 commit comments

Comments
 (0)