Skip to main content

Docker

The Zscaler MCP Server is published as a multi-arch (amd64 + arm64) Docker image on Docker Hub: zscaler/zscaler-mcp-server.

Pull and run (stdio)

docker pull zscaler/zscaler-mcp-server:latest

docker run --rm \
--env-file /path/to/.env \
zscaler/zscaler-mcp-server:latest

SSE transport

docker run --rm -p 8000:8000 \
--env-file /path/to/.env \
zscaler/zscaler-mcp-server:latest \
--transport sse --host 0.0.0.0

Streamable-HTTP transport

docker run --rm -p 8000:8000 \
--env-file /path/to/.env \
zscaler/zscaler-mcp-server:latest \
--transport streamable-http --host 0.0.0.0

Custom port

docker run --rm -p 8080:8080 \
--env-file /path/to/.env \
zscaler/zscaler-mcp-server:latest \
--transport streamable-http --host 0.0.0.0 --port 8080

With service selection

docker run --rm \
--env-file /path/to/.env \
zscaler/zscaler-mcp-server:latest \
--services zia,zpa,zdx

Pin a specific version

docker run --rm \
--env-file /path/to/.env \
zscaler/zscaler-mcp-server:1.2.3

Individual environment variables (no .env)

docker run --rm \
-e ZSCALER_CLIENT_ID=your_client_id \
-e ZSCALER_CLIENT_SECRET=your_secret \
-e ZSCALER_CUSTOMER_ID=your_customer_id \
-e ZSCALER_VANITY_DOMAIN=your_vanity_domain \
zscaler/zscaler-mcp-server:latest

Build locally (development)

git clone https://github.com/zscaler/zscaler-mcp-server.git
cd zscaler-mcp-server

docker build -t zscaler-mcp-server .

docker run --rm -e ZSCALER_CLIENT_ID=... -e ZSCALER_CLIENT_SECRET=... \
zscaler-mcp-server

Live .env reloading

For production, bind-mount the .env file so the container can re-read it on zscaler-mcp restart:

docker run -d --name zscaler-mcp-server \
--env-file /path/to/.env \
-v /path/to/.env:/app/.env:ro \
-e ZSCALER_MCP_DOTENV_PATH=/app/.env \
-p 8000:8000 \
zscaler/zscaler-mcp-server:latest \
--transport streamable-http --host 0.0.0.0

Then to apply a config change without recreating the container:

$EDITOR /path/to/.env # edit on the host
docker exec zscaler-mcp-server zscaler-mcp restart # re-read + execvp inside the container

The restart subcommand uses execvp so the PID stays the same — Docker doesn't notice the swap. Sessions die; clients reconnect.

Alternative one-off (no bind mount):

docker cp /path/to/.env zscaler-mcp-server:/app/.env
docker exec zscaler-mcp-server zscaler-mcp restart

When HTTP transport, set --host 0.0.0.0

Always set --host 0.0.0.0 for HTTP transports in Docker, otherwise the server binds to the container loopback and is unreachable from outside.

TLS in containers

For platforms that terminate TLS at the edge (Cloud Run, Azure Container Apps, ALB), set:

ZSCALER_MCP_ALLOW_HTTP=true

For self-hosted containers, mount certificates and configure:

ZSCALER_MCP_TLS_CERTFILE=/certs/cert.pem
ZSCALER_MCP_TLS_KEYFILE=/certs/key.pem

Cloud deployment guides