-
Notifications
You must be signed in to change notification settings - Fork 522
Description
Problem
qmd mcp --http --daemon binds using httpServer.listen(port, "localhost") in src/mcp.ts.
On macOS, Node resolves "localhost" to ::1 (IPv6 loopback), so the server listens on IPv6 only.
This works from the host when using curl http://localhost:8181/health, but fails from any IPv4 client — including containers reaching the host via host.docker.internal.
This is a loopback-only issue, not a security exposure. The server never listens on external interfaces either way.
Why this matters
Many setups run an MCP client in a Docker container and connect back to the host QMD daemon. With Docker via Colima (and likely Podman), host.docker.internal resolves to the host's IPv4 address. An IPv6-only listener is unreachable from these clients — even though /health looks fine on the host.
Reproduction
qmd mcp --http --daemon
# 1. Host via localhost — works (resolves to ::1)
curl -s http://localhost:8181/health
# → {"status":"ok","uptime":123}
# 2. Host via 127.0.0.1 — fails (IPv4, nothing listening)
curl -s http://127.0.0.1:8181/health
# → curl: (7) Failed to connect to 127.0.0.1 port 8181
# 3. From container — fails (host.docker.internal → IPv4)
docker exec <container> curl -s http://host.docker.internal:8181/health
# → curl: (7) Failed to connect to host.docker.internal port 8181
# 4. Confirm IPv6-only binding
lsof -i :8181
# Shows TCP [::1]:8181 only, no 127.0.0.1:8181Expected behavior
The server should be reachable from both IPv4 and IPv6 loopback clients.
Suggested fix
Bind to "127.0.0.1" instead of "localhost" — this makes the server reachable from IPv4 clients while remaining local-only (no security change):
httpServer.listen(port, "127.0.0.1", () => resolve());Or add a --bind/--host flag to let users choose the bind address.
Workaround
We patch mcp.js at every daemon start via sed:
sed -i'' -e 's/listen(port, "localhost"/listen(port, "127.0.0.1"/' "$QMD_MCP_JS"Environment
- OS: macOS 15.3 (Apple Silicon)
- qmd: v1.0.7 (
@tobilu/qmd) - Docker: via Colima (
host.docker.internal→ IPv4) - Node: v22