Skip to main content
Run the IBM i MCP Server as a container using the official pre-built images from GitHub Container Registry. Supports amd64, arm64, and ppc64le architectures.

Quick Start

The commands below start a server for clients on the same machine. The server answers at http://localhost:3010/mcp and is not reachable from other hosts.
Verify the server is running:
Two parts of this command control who can reach the server:
  • -p 127.0.0.1:3010:3010 publishes the port on the host’s loopback address only. -p 3010:3010 publishes it on every host interface, which makes an unauthenticated server that holds IBM i credentials reachable from the network.
  • MCP_ALLOW_UNAUTHENTICATED_HTTP=true accepts running without authentication. Without this variable or an MCP_AUTH_MODE setting, a container that holds IBM i credentials exits at startup. Network Exposure and Authentication describes both settings.
Replace the DB2i_* values with your actual IBM i credentials. Never commit credentials to source control.

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 as localhost, 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 sets MCP_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:
“IBM i credentials” means DB2i_* variables or a tools YAML, since YAML sources: entries carry their own connection details. Set one of the following:
Do not set MCP_HTTP_HOST=127.0.0.1 for a container. Docker and Podman forward published ports to the container’s network interface, not to its loopback address, so a server bound to 127.0.0.1 inside the container is unreachable from the host. Limit exposure with -p 127.0.0.1:3010:3010 instead. The repository’s .env.example sets MCP_HTTP_HOST=127.0.0.1; remove that line from any .env file passed to a container.

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.
Running on IBM Power Systems? Use the ppc64le image to run the MCP server natively on the same hardware as your IBM i partition — no emulation overhead.

Using an Environment File

Store the configuration in a .env file:
Then run with the env file:

Mounting Custom SQL Tools

To use your own YAML tool configurations, mount them into the container:
The :ro flag mounts the directory as read-only inside the container, which is a security best practice.
A mounted tools directory counts as IBM i credentials for the startup check, because YAML 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 a docker-compose.yml:
The .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:

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.
Before starting the stack, edit .env:
  • Set DB2i_HOST, DB2i_USER, and DB2i_PASS.
  • Set MCP_ALLOWED_HOSTS=ibmi-mcp-server. The gateway addresses the server by container name.
  • Set MCP_AUTH_MODE, or set MCP_ALLOW_UNAUTHENTICATED_HTTP=true. The stack mounts the repository’s tools/ directory, which counts as IBM i credentials for the startup check.
  • Remove the MCP_HTTP_HOST=127.0.0.1 line. Compose passes .env to the container, and that value makes the server unreachable through the published port.
This starts the following services:
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

Stopping and Removing

Health Checks

The server exposes a health endpoint at /healthz:
The health endpoint is subject to the Host check. Both commands above address the server as 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 from packages/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.
To run the local image, substitute ibmi-mcp-server:local for ghcr.io/ibm/ibmi-mcp-server:latest in any command on this page. The Dockerfile has three stages:
  1. builder — installs all workspace dependencies and runs npm run build -w @ibm/ibmi-mcp-server
  2. prod-deps — installs the server’s production dependencies only; the CLI workspace is excluded
  3. runner — copies node_modules from prod-deps and the compiled packages/server/dist from builder, then starts node 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

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
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.
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.
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.
If port 3010 is already in use, map to a different host port:
The container runs as a non-root user. Ensure mounted files are readable:
On SELinux-enabled systems (RHEL/Fedora), add the :z flag: