Skip to content

feat(mcp): add --host flag (and QMD_HOST env) to the HTTP server#677

Open
djalmajr wants to merge 1 commit into
tobi:mainfrom
djalmajr:feat/mcp-host-flag
Open

feat(mcp): add --host flag (and QMD_HOST env) to the HTTP server#677
djalmajr wants to merge 1 commit into
tobi:mainfrom
djalmajr:feat/mcp-host-flag

Conversation

@djalmajr
Copy link
Copy Markdown

Problem

startMcpHttpServer hardcodes httpServer.listen(port, "localhost", …), so the HTTP MCP server only accepts loopback connections. When qmd mcp --http runs inside a container, a Kubernetes liveness/readiness probe connects from the pod IP (e.g. 10.42.x.x), not 127.0.0.1 — the bind refuses it and the probe fails, so the pod never goes ready.

Today the only workaround is to patch the published dist/mcp/server.js at image-build time:

sed -i 's@listen(port, "localhost"@listen(port, process.env.QMD_HOST || "localhost"@g' "$QMD_DIST"

which is brittle and breaks on every release.

Change

Add a --host flag to qmd mcp --http, with a QMD_HOST environment-variable fallback:

host = options.host ?? process.env.QMD_HOST ?? "localhost"
  • Default is unchanged (localhost) — no behavior change out of the box.
  • --host 0.0.0.0 (or QMD_HOST=0.0.0.0) binds all interfaces for container/probe reachability.
  • The flag is forwarded to the detached process in --daemon mode and reflected in the startup log / Started on … message.

Files:

  • src/mcp/server.tsstartMcpHttpServer resolves and binds host; JSDoc + listening log updated.
  • src/cli/qmd.ts--host flag parsed, forwarded to daemon spawn, shown in logs.
  • README.md — documents --host / QMD_HOST.

Verification

  • npm run test:types — passes.
  • test/mcp.test.ts — 57/57 pass (existing HTTP test uses the default and still binds localhost).
  • Functional smoke:
    $ qmd mcp --http --host 0.0.0.0 --port 18234
    QMD MCP server listening on http://0.0.0.0:18234/mcp
    $ lsof -nP -iTCP:18234 -sTCP:LISTEN
    node … TCP *:18234 (LISTEN)        # * = all interfaces
    $ curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:18234/health
    200
    

The MCP HTTP server hardcoded listen(port, "localhost"), so it is
unreachable from any non-loopback address. In a container, a liveness
probe connects from the pod IP rather than 127.0.0.1, and the bind
refuses that connection.

Add a --host flag with a QMD_HOST environment-variable fallback. The
default stays "localhost", so out-of-the-box behavior is unchanged.
Set --host 0.0.0.0 to accept off-host connections (e.g. k8s probes).

- server.ts: startMcpHttpServer binds options.host ?? QMD_HOST ?? "localhost"
- cli: --host flag, forwarded to the daemon spawn and shown in startup logs
- README: document --host / QMD_HOST
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