From 39d0723c581fe30660f45ba70b90187126ab16f4 Mon Sep 17 00:00:00 2001 From: Cho Young-Hwi Date: Tue, 7 Jul 2026 01:18:29 +0000 Subject: [PATCH] [#961] Clarify Operator MCP VPS loopback and SSH forwarding troubleshooting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Docs-only. The VPS path in operator-mcp.md was technically correct but easy to misread while troubleshooting. Adds a focused "Remote / VPS troubleshooting" subsection under the existing Registration section (references it, no duplication): - restates the loopback rule (client always hits 127.0.0.1 of the machine running the MCP command) - "Expected failures": nc/browser to :8400 refused is NORMAL when the backend is loopback-only; do NOT open 8400 publicly to fix it - the exact tunnel command `ssh -N -L 8400:127.0.0.1:8400 ` - a bottom-up verify checklist (ssh -G, lsof, quadwork-mcp-operator) - warns that `ssh ` vs `ssh ` can resolve to different users/identity files — verify with `ssh -G` - a symptom → cause → fix table Also notes why the stdio examples carry a trailing `sleep` (keep stdin open so the MCP server can flush responses before the pipe closes). No code or behavior change. Co-Authored-By: Claude Opus 4.8 --- docs/operator-mcp.md | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/docs/operator-mcp.md b/docs/operator-mcp.md index c216a0d..e78b7d2 100644 --- a/docs/operator-mcp.md +++ b/docs/operator-mcp.md @@ -84,6 +84,45 @@ The operator server speaks to `127.0.0.1:8400` — the loopback of **whatever ma > ⚠️ **A local Claude Desktop registration reaches THIS device's `127.0.0.1`, not the VPS.** Use SSH or a port-forward so the client and QuadWork share a loopback. +### Remote / VPS troubleshooting + +`quadwork-mcp-operator --port 8400` **always** connects to `127.0.0.1:8400` of the machine where that command runs (see [Remote / VPS registration](#remote--vps-registration) above). Most VPS confusion comes from expecting a *direct* connection to the VPS's public IP — which is deliberately closed. + +**Expected failures — these are normal, not bugs:** + +- `nc -vz 8400` → *connection refused*, and a browser to `http://:8400` failing, are **expected** when the backend binds VPS loopback only (the default). Nothing is broken — the port is simply not exposed publicly. +- **Do not open port 8400 publicly to "fix" this.** The backend is not meant to be a public, internet-facing auth boundary; exposing it is a security regression. Forward it over SSH instead. + +**The fix — forward the port over SSH, then connect to the local loopback:** + +```bash +ssh -N -L 8400:127.0.0.1:8400 +# then, in another local shell: +quadwork-mcp-operator --port 8400 # now reaches the VPS via the forwarded 127.0.0.1:8400 +``` + +`-N` opens the tunnel without starting a remote shell; `-L 8400:127.0.0.1:8400` maps your **local** `127.0.0.1:8400` onto the VPS's loopback `8400`. (Alternatively, run the MCP client over SSH *on* the VPS, as in option 1 above — then no forward is needed.) + +**Verify each layer independently, bottom-up:** + +```bash +ssh -G | sed -n '1,20p' # 1. confirm the alias's user + hostname +lsof -iTCP:8400 -sTCP:LISTEN -n -P # 2. is something listening on local 8400 (the tunnel)? +quadwork-mcp-operator --port 8400 # 3. end-to-end: list_projects should return +``` + +> ⚠️ **`ssh ` and `ssh ` can resolve to different users and identity files.** `ssh -G quadwork` may report `user quadwork`, while `ssh -G 178.x.x.x` falls back to your **local** username — so a direct-IP check can silently test the wrong login. Always confirm with `ssh -G` before assuming you're reaching the intended VPS account. + +**Symptom → cause → fix:** + +| Symptom | Cause | Fix | +|---------|-------|-----| +| `nc -vz 8400` → refused | Backend binds VPS loopback only (expected) | Not a bug — use the SSH tunnel; do **not** expose 8400 publicly | +| MCP client can't reach QuadWork from your laptop | The client hits **your laptop's** `127.0.0.1`, not the VPS | `ssh -N -L 8400:127.0.0.1:8400 `, then rerun the client | +| `nc -vz 22` works but MCP still fails | SSH host reachable, but no forward for 8400 | Add `-L 8400:127.0.0.1:8400` (or run the client on the VPS) | +| `ssh ` uses the wrong user | Direct IP uses your **local** username, not the alias's | Use the alias (`ssh quadwork`) or `user@ip`; confirm with `ssh -G` | +| stdio JSON-RPC returns nothing | Pipe closed before the server wrote its responses | Keep the trailing `sleep` in the [stdio examples](#direct-stdio-json-rpc-invocation) below (raise it on slow links) | + ## Direct stdio JSON-RPC invocation Use this only when your MCP client does not surface tools directly, or when you @@ -108,6 +147,10 @@ The minimal flow is: Each request is one JSON object. The examples below write newline-delimited JSON-RPC requests and pipe them into the installed bin. +The trailing `sleep` in each example keeps stdin open long enough for the MCP +server to write its responses before the pipe closes — without it you may see +no output. Raise it for slower links or heavier calls. + ### List projects / verify connection ```bash