Skip to content

feat: MCP-over-HTTP + --bind/--token for headless/LAN mode#23

Merged
NJannasch merged 1 commit into
mainfrom
feat/mcp-over-http
May 9, 2026
Merged

feat: MCP-over-HTTP + --bind/--token for headless/LAN mode#23
NJannasch merged 1 commit into
mainfrom
feat/mcp-over-http

Conversation

@NJannasch

Copy link
Copy Markdown
Owner

Summary

Lets a single vibecockpit instance run headless on a server and act as a central memory hub for multiple machines.

  • New `--bind ` flag (default `127.0.0.1`); pass `0.0.0.0` or a specific IP to expose to the LAN.
  • New `--token` / `VIBECOCKPIT_TOKEN`. Required when `--bind` is non-loopback — Start() refuses to listen otherwise.
  • `bearerAuthMiddleware`: loopback requests (incl. SSH-tunneled) bypass entirely; non-loopback requests need `Authorization: Bearer ` (constant-time compare) or `?token=` for download links.
  • New `POST /mcp` endpoint speaking the MCP Streamable HTTP transport. Same toolset as `vibecockpit --mcp` (stdio); both transports share one `Server` and one audit log. Notifications get 204; MCP disabled returns 503.

Verified live

  • `--bind 0.0.0.0` with no token → refuses to start with a clear error.
  • Loopback hit → 200 (no token needed).
  • Remote hit no token → 401. Wrong bearer → 401. Correct bearer → 200.
  • `POST /mcp` `tools/list` → returns 19 tools incl. `search_memory`, `get_session_context`.
  • `tools/call search_memory` over HTTP returns the same hits the local stdio MCP returns.

Test plan

  • CI green
  • Configure Claude Desktop with `{ "url": "http://server:3456/mcp", "headers": { "Authorization": "Bearer ..." } }` and run `search_memory`
  • Configure Cursor MCP similarly
  • Verify server's `/api/mcp-audit` feed shows the remote tool calls

Lets a vibecockpit instance run on a server (e.g. via --autostart on a
Linux box) and serve as a central memory hub for multiple machines.

Web server:
- New --bind <addr> flag (default 127.0.0.1). Pass 0.0.0.0 or a specific
  IP to expose to the LAN.
- New --token / VIBECOCKPIT_TOKEN. Required when --bind is non-loopback;
  Start() refuses to listen otherwise — better to fail loud than ship
  an unauthenticated dashboard onto a network.
- bearerAuthMiddleware: loopback requests bypass entirely (so SSH-tunnel
  + the auto-launched browser keep working). Non-loopback requests must
  carry Authorization: Bearer <token>, with a ?token= query fallback for
  download flows. Constant-time compare.
- Auto-open-browser is now skipped on non-loopback bind (no browser on
  a headless server).

MCP transport:
- Same internal/mcp.Server now exposes a HandleHTTPRequest(body []byte)
  []byte method backed by the same dispatcher the stdio transport uses.
- /mcp endpoint on the web server speaks the MCP "Streamable HTTP"
  transport: each POST is one JSON-RPC request; response is the encoded
  reply, or 204 No Content for notifications.
- /mcp is registered behind the same auth middleware as everything else,
  and gated by enable_mcp in config.yaml just like the stdio path.
- Audit log is shared, so both transports' tool calls land in the same
  /api/mcp-audit feed.

Tests:
- isLoopbackBind table test for IPv4/IPv6 + localhost.
- bearerAuthMiddleware: loopback bypass, missing/wrong/correct bearer,
  query-string fallback, defensive 401 when token unset on remote.
- /mcp end-to-end: tools/list returns the full toolset, notifications
  return 204, MCP-disabled returns 503.

Docs: README has a Remote/Headless Mode section with Claude Desktop
and Cursor MCP-over-HTTP config snippets. CLAUDE.md notes the new
flags and that the MCP toolset is identical across both transports.

Verified live: --bind 0.0.0.0 without --token refuses to start; with
--token, remote requests need the bearer (401 without, 200 with);
loopback requests stay token-free; tools/list and search_memory
round-trip correctly over HTTP.
@NJannasch NJannasch merged commit d47f099 into main May 9, 2026
6 checks passed
@NJannasch NJannasch deleted the feat/mcp-over-http branch May 9, 2026 20:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant