v0.6.0
Pre-releaseIBM i MCP Server v0.6.0
Overview
- DNS rebinding protection for the HTTP transport (Server) — Every request's
HostandOriginheaders are validated, and a server that holds IBM i credentials refuses to start unauthenticated on a network address - New defaults for HTTP deployments (Server) —
MCP_HTTP_HOSTdefaults to127.0.0.1; remote and container deployments needMCP_ALLOWED_HOSTSand an authentication mode, or an explicit opt-out - dependency audit — 52 vulnerabilities cleared across both packages, including
axios,hono,sanitize-html, andjs-yaml - Docker image binds all interfaces (Server) — The published image sets
MCP_HTTP_HOST=0.0.0.0so published ports work with the new default
Stdio deployments (Claude Desktop, Cursor, VS Code, MCP Inspector) and the ibmi CLI are not affected by the HTTP changes.
Docker & Podman | Configuration | IBM i Authentication
Breaking Changes
HTTP transport hardening against DNS rebinding
The vulnerability: The HTTP transport holds the IBM i credentials it is started with. Through DNS rebinding, a web page opened in a browser on the same machine could send requests to the local server and run its SQL tools with those credentials. CORS does not prevent this; the request is same-origin from the browser's point of view.
What changed.
- Every request's
Hostheader must be a loopback name (localhost,127.x.x.x,::1) or listed inMCP_ALLOWED_HOSTS. Any other name returns403 Forbidden: Host not allowed.A browserOriginheader, when present, must matchMCP_ALLOWED_ORIGINSor an allowlisted host. Non-browser clients send noOriginand are unaffected by that rule. - The server refuses to start when it is bound to a non-loopback address, holds IBM i credentials (
DB2i_*variables or a tools YAML), and authentication is not enforced. "Not enforced" meansMCP_AUTH_MODE=none, orMCP_AUTH_MODE=jwtwithoutMCP_AUTH_SECRET_KEY. The log line beginsRefusing to start: unauthenticated HTTP transport. Override withMCP_ALLOW_UNAUTHENTICATED_HTTP=true. MCP_HTTP_HOSTdefaults to127.0.0.1(was0.0.0.0).- The development CORS
*fallback is removed. WithMCP_ALLOWED_ORIGINSunset, noAccess-Control-Allow-Originheader is sent.
Running the server over HTTP.
Local, with the client on the same machine: no configuration is needed. If your .env sets MCP_HTTP_HOST=0.0.0.0, remove that line.
Docker, local only, without authentication:
docker run -d --name ibmi-mcp-server \
-p 127.0.0.1:3010:3010 \
-e DB2i_HOST=your-ibmi-host -e DB2i_USER=your-username -e DB2i_PASS=your-password \
-e MCP_ALLOW_UNAUTHENTICATED_HTTP=true \
ghcr.io/ibm/ibmi-mcp-server:v0.6.0On a network (remote host, OpenShift, Docker Compose): bind all interfaces, allowlist every name clients use to reach the server, and enable authentication.
MCP_HTTP_HOST=0.0.0.0
MCP_ALLOWED_HOSTS=mcp.example.com,ibmi-mcp-server
MCP_AUTH_MODE=ibmiKubernetes and OpenShift probes send the pod IP as Host; add httpHeaders: Host: localhost to the probe. Browser clients need their origin in MCP_ALLOWED_ORIGINS. Do not set MCP_HTTP_HOST=127.0.0.1 inside a container: Docker forwards published ports to the container's network interface, not its loopback, so the server becomes unreachable. Restrict exposure on the host side with -p 127.0.0.1:3010:3010.
New configuration.
| Variable | Default | Purpose |
|---|---|---|
MCP_HTTP_HOST |
127.0.0.1 (was 0.0.0.0) |
Bind address |
MCP_ALLOWED_HOSTS |
loopback only | Comma-separated Host allowlist; extends loopback. * disables the Host check only |
MCP_ALLOW_UNAUTHENTICATED_HTTP |
false |
Accept an unauthenticated, non-loopback server that holds credentials |
Documentation: Docker & Podman, Configuration, Using the default tools
What's Changed
- fix(deps): resolve all npm audit vulnerabilities in server and CLI (52 → 0) by @ajshedivy in #159
- chore(deps): prune example-agent lockfiles feeding Dependabot alert noise by @ajshedivy in #160
- fix(security): validate Host and Origin headers to block DNS rebinding by @ajshedivy in #163
- fix(docker): ship MCP_HTTP_HOST=0.0.0.0 in the CI-built image; update Docker docs for DNS rebinding hardening by @ajshedivy in #169
Full Changelog: v0.5.1...v0.6.0