Quick Start
The commands below start a server for clients on the same machine. The server answers athttp://localhost:3010/mcp and is not reachable from other hosts.
- Docker
- Podman
-p 127.0.0.1:3010:3010publishes the port on the host’s loopback address only.-p 3010:3010publishes it on every host interface, which makes an unauthenticated server that holds IBM i credentials reachable from the network.MCP_ALLOW_UNAUTHENTICATED_HTTP=trueaccepts running without authentication. Without this variable or anMCP_AUTH_MODEsetting, a container that holds IBM i credentials exits at startup. Network Exposure and Authentication describes both settings.
Network Exposure and Authentication
The server holds the IBM i credentials it is started with. Any client that can send it a request can run SQL with those credentials. Two checks limit which clients can do so.Host header validation
Every request must address the server aslocalhost, 127.0.0.1, or a name listed in MCP_ALLOWED_HOSTS. A request that uses any other name receives 403 Forbidden: Host not allowed. The check applies to every route, including /healthz.
The check blocks DNS rebinding: a web page changes the DNS record for its own hostname to 127.0.0.1 after loading, then sends requests from the browser to the server on the visitor’s machine. Those requests carry the page’s hostname in the Host header and are rejected.
MCP_ALLOWED_HOSTS accepts a comma-separated list. The 403 response body does not include the rejected name; the container log does.
Startup check for unauthenticated servers
The image setsMCP_HTTP_HOST=0.0.0.0, which published ports require. A server bound this way, holding IBM i credentials, with no authentication configured, is usable by anyone who can reach the port. The server refuses this configuration and exits with:
DB2i_* variables or a tools YAML, since YAML sources: entries carry their own connection details. Set one of the following:
Available Images
Images are published to GitHub Container Registry on each release. Multi-architecture tags select the image for the host’s architecture; single-architecture tags pin one platform.Using an Environment File
Store the configuration in a.env file:
- Docker
- Podman
Mounting Custom SQL Tools
To use your own YAML tool configurations, mount them into the container:- Docker
- Podman
The
:ro flag mounts the directory as read-only inside the container, which is a security best practice.sources: entries carry connection details. The .env file must set MCP_AUTH_MODE or MCP_ALLOW_UNAUTHENTICATED_HTTP=true.
Docker Compose
For a more complete setup, use Docker Compose to run the MCP server alongside supporting services.Standalone Server
Create adocker-compose.yml:
.env file is the one from Using an Environment File. The healthcheck addresses the server as localhost and passes the Host check. Other services in the same Compose file reach the server as http://ibmi-mcp-server:3010/mcp; that name must be listed in MCP_ALLOWED_HOSTS.
Start the service:
- Docker
- Podman
With MCP Context Forge Gateway
The repository includes a full-stack Docker Compose configuration with MCP Context Forge — a gateway that provides tool federation, authentication, rate limiting, and an admin UI..env:
- Set
DB2i_HOST,DB2i_USER, andDB2i_PASS. - Set
MCP_ALLOWED_HOSTS=ibmi-mcp-server. The gateway addresses the server by container name. - Set
MCP_AUTH_MODE, or setMCP_ALLOW_UNAUTHENTICATED_HTTP=true. The stack mounts the repository’stools/directory, which counts as IBM i credentials for the startup check. - Remove the
MCP_HTTP_HOST=127.0.0.1line. Compose passes.envto the container, and that value makes the server unreachable through the published port.
The MCP Context Forge Gateway image must be built locally before starting the stack. See the MCP Context Forge docs for build instructions.
Container Management
Viewing Logs
- Docker
- Podman
Stopping and Removing
- Docker
- Podman
Health Checks
The server exposes a health endpoint at/healthz:
localhost and pass. A probe that addresses the server by IP address, such as a Kubernetes probe using the pod IP, receives 403. Set a Host: localhost header on such probes; the repository’s OpenShift deployment manifest does this.
Building from Source
The image is built frompackages/server/Dockerfile with the repository root as the build context. The root is required because the npm workspaces layout keeps a single package-lock.json there.
ibmi-mcp-server:local for ghcr.io/ibm/ibmi-mcp-server:latest in any command on this page.
The Dockerfile has three stages:
- builder — installs all workspace dependencies and runs
npm run build -w @ibm/ibmi-mcp-server - prod-deps — installs the server’s production dependencies only; the CLI workspace is excluded
- runner — copies
node_modulesfromprod-depsand the compiledpackages/server/distfrombuilder, then startsnode packages/server/dist/index.js
.dockerignore keeps node_modules/, dist/, .git/, .github/, .claude/, agents/, and .env files out of the build context.
The image runs as a non-root user (
appuser) for security. Port 3010 is exposed by default.Troubleshooting
Container won't start
Container won't start
Check the container logs for error details:Common causes:
- The log contains
Refusing to start. See the next entry. - Missing or incorrect
DB2i_*environment variables - Mapepire not running on the IBM i system
- Network connectivity issues to IBM i host
Container exits with 'Refusing to start: unauthenticated HTTP transport'
Container exits with 'Refusing to start: unauthenticated HTTP transport'
The server holds IBM i credentials, has no authentication configured, and is bound to
0.0.0.0. It refuses this combination. Set MCP_AUTH_MODE, or set MCP_ALLOW_UNAUTHENTICATED_HTTP=true and publish the port with -p 127.0.0.1:3010:3010. See Network Exposure and Authentication.MCP_AUTH_MODE=jwt without MCP_AUTH_SECRET_KEY produces the same error, with Auth mode: jwt - MCP_AUTH_SECRET_KEY is unset in the message.Requests return 403 Forbidden
Requests return 403 Forbidden
Forbidden: Host not allowed. means the client addresses the server by a name that is not localhost and is not listed in MCP_ALLOWED_HOSTS. The container log records the rejected name. Add it to MCP_ALLOWED_HOSTS and restart the container.Forbidden: Origin not allowed. means the request came from a browser page whose origin is not listed in MCP_ALLOWED_ORIGINS. Add the origin, for example MCP_ALLOWED_ORIGINS=http://localhost:3000.Cannot connect to IBM i from container
Cannot connect to IBM i from container
Verify the container can reach your IBM i system:If using Docker Desktop on macOS/Windows, ensure the IBM i host is reachable from within the VM.
Port conflicts
Port conflicts
If port 3010 is already in use, map to a different host port:
Permission denied on mounted volumes
Permission denied on mounted volumes
The container runs as a non-root user. Ensure mounted files are readable:On SELinux-enabled systems (RHEL/Fedora), add the
:z flag: