# Hermes remote MCP bridge — build transcript (2026-08-06)

Built so Claude Desktop (MSIX build 1.25927, no local-stdio support) can call Hermes on the VPS as a remote MCP connector.

## Final architecture

- systemd unit `hermes-mcp-bridge.service`: `/usr/bin/node node_modules/.bin/supergateway --stdio "/root/.hermes/venv/bin/hermes mcp serve" --outputTransport streamableHttp --port 9121 --streamableHttpPath /mcp --logLevel info`, cwd `/root/.hermes/mcp-bridge`, env PATH=`/root/.hermes/venv/bin:...` + `HERMES_HOME=/root/.hermes`
- nginx `location /mcp` inside the existing robblake.cloud 443 server block → `proxy_pass http://127.0.0.1:9121` with `proxy_read_timeout 86400`
- Auth: nginx `if ($http_authorization != "Bearer <token>") { return 401; }` — token at `/root/.hermes/mcp-bridge/token.env`
- Claude connector: Name `hermes-vps`, URL `https://robblake.cloud/mcp`, OAuth fields empty, then `Bearer <token>` at the auth prompt

## Failure modes hit (in order)

1. `hermes mcp serve` is stdio-only — `mcp_serve.py` header says so explicitly; don't look for a --port flag.
2. `mcp-remote` is the WRONG shim direction (stdio→HTTP client proxy). Use `supergateway` for stdio→HTTP server.
3. VPS node was v18.19.1 → mcp-remote/supergateway deps (undici) crash with `ReferenceError: File is not defined`. Fix: NodeSource setup_20.x + apt install nodejs → v20.20.2.
4. nginx `location` appended after the server block's closing `}` → `emerg: "location" directive is not allowed here`. Fix: `sed -i '<line-of-close>a\...'` to insert INSIDE the block.
5. First auth check appeared not to fire because the bare `curl` returned 405 — the `if` WAS working; the initial test happened before `systemctl reload nginx`. Verify auth with three curls: no header → 401, wrong → 401, correct → 405 (405 = MCP server alive, GET rejected, POST-only is correct for Streamable HTTP).

## Verification commands

```bash
systemctl is-active hermes-mcp-bridge.service
ss -tlnp | grep 9121
curl -s -o /dev/null -w "%{http_code}\n" https://robblake.cloud/mcp                                  # expect 401
curl -s -o /dev/null -w "%{http_code}\n" -H "Authorization: Bearer $(cut -d= -f2 /root/.hermes/mcp-bridge/token.env)" https://robblake.cloud/mcp   # expect 405
```

## Note on supergateway + hermes mcp serve child

supergateway spawns ONE `hermes mcp serve` stdio child per unit lifetime. `hermes mcp serve` exposes *conversations as tools* (messaging-session oriented: create session, send message, read replies). It is NOT a raw tool passthrough of the agent's full toolset — Claude gets "talk to a Hermes session" tools, not "run web_search directly."
