Prerequisites

  • Docker 20.10+ installed and running
  • A terminal / command prompt

Option 1 — Single Container (docker run)

The fastest way to get started. One command, one container, no compose file needed. Your settings are persisted in a host directory so they survive container restarts and upgrades.

FlagPurpose
--rm -itAutomatically remove the container when it stops; attach an interactive terminal
-p 8091:8080Expose the app on host port 8091 (container listens on 8080)
-v <dataRoot>:/root/.local/share/McpExplorerPersist connections and settings across restarts
-v ~/.azure:/root/.azureMount your host Azure CLI config so AzureCliCredential can authenticate
-e AZURE_CONFIG_DIR=/root/.azureTell the Azure SDK where to find the CLI config inside the container
-e HOST_AZURE_CONFIG_DIR=...Used by docker-compose to conditionally mount your .azure directory
-e PREFERENCES__StoragePath=/data/settings.jsonOverride the settings path to match the /data volume mount
-e ASPNETCORE_ENVIRONMENT=ProductionSet the runtime environment (controls logging verbosity and error detail)

Option 2 — Docker Compose (separate services)

Better for long-running or team environments. Runs the API and frontend as separate services on an internal Docker network. All configuration is driven by a .env file.

1. Grab the compose file and env template:

2. Edit .env — set your data path and any overrides:

  # Point to your existing McpExplorer settings folder (optional — persists connections)
# macOS:   MCP_DATA_PATH=/Users/<you>/Library/Application Support/McpExplorerX
# Linux:   MCP_DATA_PATH=/home/<you>/.config/McpExplorerX
# Windows: MCP_DATA_PATH=C:\Users\<you>\AppData\Local\McpExplorerX
MCP_DATA_PATH=

# Host port the app is exposed on (default: 8090)
GATEWAY_PORT=8090

# Optional: reuse your host devtunnel login so the container skips device-code auth
# macOS:   HOST_DEVTUNNELS_DIR=/Users/<you>/Library/Application Support/DevTunnels
# Linux:   HOST_DEVTUNNELS_DIR=/home/<you>/.devtunnels
# Windows: HOST_DEVTUNNELS_DIR=C:\Users\<you>\AppData\Local\DevTunnels
HOST_DEVTUNNELS_DIR=
  

See the Environment Variables reference for the full list.

3. Start the services:

  docker compose up -d
  

Open http://localhost:8090 in your browser (or whichever port you set for GATEWAY_PORT).


docker-compose.yml

  name: mcp-explorer

# ─── Separate-services deployment ─────────────────────────────────────────────
# Usage:
#   cp .env.example .env        # fill in your values
#   docker compose up -d
#
# Single-container alternative:
#   docker build -t mcp-explorer .
#   docker run -p 8090:8080 -v mcp-data:/root/.local/share/McpExplorer mcp-explorer
# ──────────────────────────────────────────────────────────────────────────────

services:

  api:
    build:
      context: .
      dockerfile: Dockerfile.api
    restart: unless-stopped
    env_file: .env
    environment:
      - ASPNETCORE_URLS=http://+:5000
      - ASPNETCORE_ENVIRONMENT=${ASPNETCORE_ENVIRONMENT:-Production}
      - AppMetadata__Version=${AppMetadata__Version:-0.5.0}
      - LlmService__OpenAiBaseUrl=${LlmService__OpenAiBaseUrl:-https://api.openai.com/v1}
      - LlmService__MaxRetryAttempts=${LlmService__MaxRetryAttempts:-3}
      - LlmService__TimeoutSeconds=${LlmService__TimeoutSeconds:-30}
      - ToolInvoke__TimeoutSeconds=${ToolInvoke__TimeoutSeconds:-300}
      - ToolInvoke__MaxRetryAttempts=${ToolInvoke__MaxRetryAttempts:-2}
      - Elicitation__TimeoutSeconds=${Elicitation__TimeoutSeconds:-0}
      - MCP_CLIENT_NAME=${MCP_CLIENT_NAME:-mcp-explorer}
      - PREFERENCES__StoragePath=${PREFERENCES__StoragePath:-/data/settings.json}
      # Fixed inside the container — do not override
      - AZURE_CONFIG_DIR=/root/.azure
    volumes:
      - ${MCP_DATA_PATH:-mcp-data}:/data
      # Persist devtunnel CLI login across restarts. Mount your host credentials
      # dir via HOST_DEVTUNNELS_DIR in .env to skip device-code auth entirely.
      - ${HOST_DEVTUNNELS_DIR:-devtunnels-cli}:/root/.local/share/DevTunnels
      # Optional: mount your host ~/.azure so Azure Key Vault & app-registration
      # lookups work inside the container. Set HOST_AZURE_CONFIG_DIR in .env:
      #   macOS/Linux: HOST_AZURE_CONFIG_DIR=~/.azure
      #   Windows:     HOST_AZURE_CONFIG_DIR=%USERPROFILE%\.azure
      - ${HOST_AZURE_CONFIG_DIR:-azure-config-empty}:/root/.azure
    healthcheck:
      test: ["CMD", "curl", "-sf", "http://localhost:5000/healthz"]
      interval: 10s
      timeout: 5s
      retries: 5
      start_period: 30s
    extra_hosts:
      - "host.docker.internal:host-gateway"
    networks:
      - internal

  frontend:
    build:
      context: .
      dockerfile: Dockerfile.frontend
    restart: unless-stopped
    ports:
      - "${GATEWAY_PORT:-8090}:8080"
    depends_on:
      api:
        condition: service_healthy
    networks:
      - internal

volumes:
  mcp-data:
    driver: local
  # Persists devtunnel login state across restarts (used when HOST_DEVTUNNELS_DIR is not set)
  devtunnels-cli:
    driver: local
  # Empty fallback — used when HOST_AZURE_CONFIG_DIR is not set in .env
  azure-config-empty:
    driver: local

networks:
  internal:
    driver: bridge
  

Option 3 — Single Container with All Variables (docker run -e)

Same single container as Option 1 but with every environment variable passed explicitly via -e flags. Useful when you cannot use a .env file or a volume mount — for example, in CI pipelines, cloud container services (Azure Container Instances, AWS ECS, etc.), or when scripting a fully-reproducible deployment.

Note: VITE_API_BASE_URL and VITE_APP_VERSION are build-time variables baked into the image — they cannot be changed via -e at runtime. The published image uses VITE_API_BASE_URL= (empty = same-origin, correct for the single-container setup).

See the Environment Variables reference for the full list.


Verify It’s Running

You should see the Connections page — MCP Explorer’s home screen.

The Connections page is shown on startup. It lists all your saved MCP server connections.


Next Steps