Skip to content

Docker documentation is incorrect #8

@imichaelmoore

Description

@imichaelmoore

Docker Documentation Incorrectly Shows CLI Arguments Instead of Environment Variables

Summary

The documentation for running Purple MCP in Docker (README.md and DOCKER.md) shows examples using command-line arguments (e.g., --mode streamable-http) which are silently ignored by the Docker entrypoint script. This causes the server to start in the wrong mode (defaulting to stdio instead of the requested mode), leading to confusion and potentially broken deployments.

Problem

The docker-entrypoint.sh script uses environment variables (MCP_MODE, MCP_HOST, MCP_PORT) to configure the server, not command-line arguments passed to docker run. Any CLI arguments provided after the image name are discarded.

How the Entrypoint Works

The entrypoint script (docker-entrypoint.sh) operates as follows:

  1. Lines 17-19: Reads configuration from environment variables:

    MCP_MODE="${MCP_MODE:-stdio}"
    MCP_HOST="${MCP_HOST:-0.0.0.0}"
    MCP_PORT="${MCP_PORT:-8000}"
  2. Line 21: Constructs the Python command using these environment variables:

    set -- python -u -m purple_mcp.cli --mode "$MCP_MODE" --host "$MCP_HOST" --port "$MCP_PORT"

    The set -- command replaces the positional arguments ($@), discarding any arguments passed to docker run.

  3. Line 58: Executes the constructed command:

    exec "$@"

Why CLI Arguments Don't Work

When you run:

docker run purple-mcp:latest --mode streamable-http

The --mode streamable-http argument is passed to the entrypoint script but never parsed. The entrypoint reads MCP_MODE from the environment (which defaults to stdio), then uses set -- to replace all arguments with the newly constructed command. The original --mode streamable-http is discarded.

Result: The server starts in stdio mode despite the --mode streamable-http flag.

Affected Documentation

README.md (Line 54-58)

Current (INCORRECT):

docker run -p 8000:8000 \
  -e PURPLEMCP_CONSOLE_TOKEN \
  -e PURPLEMCP_CONSOLE_BASE_URL \
  purple-mcp:latest \
  --mode streamable-http

Should be:

docker run -p 8000:8000 \
  -e PURPLEMCP_CONSOLE_TOKEN \
  -e PURPLEMCP_CONSOLE_BASE_URL \
  -e MCP_MODE=streamable-http \
  purple-mcp:latest

DOCKER.md (Multiple Locations)

Lines 62-67 (Streamable-HTTP section):

# INCORRECT
docker run -p 8000:8000 \
  -e PURPLEMCP_CONSOLE_TOKEN \
  -e PURPLEMCP_CONSOLE_BASE_URL \
  purple-mcp:latest \
  --mode streamable-http

Lines 72-77 (SSE Mode section):

# INCORRECT
docker run -p 8000:8000 \
  -e PURPLEMCP_CONSOLE_TOKEN \
  -e PURPLEMCP_CONSOLE_BASE_URL \
  purple-mcp:latest \
  --mode sse

Lines 82-87 (STDIO Mode section):

# INCORRECT
docker run -it \
  -e PURPLEMCP_CONSOLE_TOKEN \
  -e PURPLEMCP_CONSOLE_BASE_URL \
  purple-mcp:latest \
  --mode stdio

Lines 211-216 (Troubleshooting - Verbose output):

# INCORRECT
docker run -it \
  -e PURPLEMCP_CONSOLE_TOKEN \
  -e PURPLEMCP_CONSOLE_BASE_URL \
  purple-mcp:latest \
  --mode streamable-http --verbose

Line 228 (Port troubleshooting):

# INCORRECT
docker run -p 8001:8000 purple-mcp:latest --mode streamable-http

Correct Usage

Environment Variables (Docker Way)

All Docker configuration must use environment variables:

# Streamable-HTTP mode
docker run -p 8000:8000 \
  -e PURPLEMCP_CONSOLE_TOKEN \
  -e PURPLEMCP_CONSOLE_BASE_URL \
  -e MCP_MODE=streamable-http \
  purple-mcp:latest

# SSE mode
docker run -p 8000:8000 \
  -e PURPLEMCP_CONSOLE_TOKEN \
  -e PURPLEMCP_CONSOLE_BASE_URL \
  -e MCP_MODE=sse \
  purple-mcp:latest

# STDIO mode (default, explicit)
docker run -it \
  -e PURPLEMCP_CONSOLE_TOKEN \
  -e PURPLEMCP_CONSOLE_BASE_URL \
  -e MCP_MODE=stdio \
  purple-mcp:latest

# With custom host/port
docker run -p 8001:8000 \
  -e PURPLEMCP_CONSOLE_TOKEN \
  -e PURPLEMCP_CONSOLE_BASE_URL \
  -e MCP_MODE=streamable-http \
  -e MCP_HOST=0.0.0.0 \
  -e MCP_PORT=8000 \
  purple-mcp:latest

Available Docker-Specific Environment Variables

Variable Default Description
MCP_MODE stdio Transport mode: stdio, sse, or streamable-http
MCP_HOST 0.0.0.0 Host to bind to (for SSE/HTTP modes)
MCP_PORT 8000 Port to bind to (for SSE/HTTP modes)

Note: These are in addition to the application environment variables (PURPLEMCP_CONSOLE_TOKEN, PURPLEMCP_CONSOLE_BASE_URL, etc.).

CLI Arguments Still Work Outside Docker

When running Purple MCP directly (not in Docker), CLI arguments work as expected:

# This works (running directly via uv/python)
uvx --from git+https://github.com/Sentinel-One/purple-mcp.git purple-mcp --mode streamable-http

# This works (running from source)
uv run python -m purple_mcp.cli --mode streamable-http --host localhost --port 8000

The issue is Docker-specific due to how the entrypoint script is designed.

Verification

You can verify the current behavior:

# Build the image
docker build -t purple-mcp:latest .

# Try with CLI argument (WILL NOT WORK - starts in stdio mode)
docker run -p 8000:8000 \
  -e PURPLEMCP_CONSOLE_TOKEN="test" \
  -e PURPLEMCP_CONSOLE_BASE_URL="https://test.sentinelone.net" \
  purple-mcp:latest \
  --mode streamable-http

# Server starts in stdio mode (default), not streamable-http mode

# Correct approach using environment variable (WORKS)
docker run -p 8000:8000 \
  -e PURPLEMCP_CONSOLE_TOKEN="test" \
  -e PURPLEMCP_CONSOLE_BASE_URL="https://test.sentinelone.net" \
  -e MCP_MODE=streamable-http \
  purple-mcp:latest

# Server starts in streamable-http mode as intended

Root Cause Analysis

This design choice (using environment variables in the entrypoint) is intentional and follows Docker best practices:

  1. Docker convention: Configuration via environment variables is the standard Docker approach
  2. docker-compose compatibility: Makes it easy to use with docker-compose.yml
  3. Kubernetes compatibility: Aligns with how K8s ConfigMaps and environment variables work
  4. Consistency: All configuration uses the same pattern (environment variables)

However, the documentation was written assuming CLI arguments would work, which they don't when using the Docker entrypoint.

Recommended Fix

  1. Update README.md (line 54-58): Change Quick Start Docker example to use -e MCP_MODE=streamable-http

  2. Update DOCKER.md (lines 62-67, 72-77, 82-87, 211-216, 228): Change all docker run examples to use environment variables

  3. Add clarification in DOCKER.md explaining:

    • Docker deployments must use MCP_MODE, MCP_HOST, MCP_PORT environment variables
    • CLI arguments like --mode, --host, --port are not supported in Docker (they are ignored)
    • CLI arguments work fine when running outside Docker (uvx, direct Python execution)
  4. Optional enhancement: Consider adding a note in docker-entrypoint.sh that detects if arguments are passed and warns the user:

    # After line 21, before line 22
    if [ $# -gt 0 ] && [ "$1" != "python" ]; then
        echo "WARNING: Command-line arguments are ignored by Docker entrypoint" >&2
        echo "Use MCP_MODE, MCP_HOST, MCP_PORT environment variables instead" >&2
    fi

Additional Context

  • The Kubernetes example in DOCKER.md (lines 266-267) correctly uses the MCP_MODE environment variable
  • The docker-compose.yml file correctly uses environment variables throughout
  • Only the standalone docker run examples are incorrect

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions