Running Docker MCP Gateway on Linux (Without Docker…
    Neura MarketNeura Market/Stable Diffusion
    ChatGPTChatGPTClaudeClaudeGeminiGeminiCursorCursorGrokGrokPerplexityPerplexityStable DiffusionStable Diffusion
    DeepSeekDeepSeekCoPilotCoPilotMidjourneyMidjourney
    View All Directories
    OverviewPromptsBlogVideosGuidesCoursesCommunityModelsLoRAsComfyUI WorkflowsTrending
    Stable DiffusionBlogRunning Docker MCP Gateway on Linux (Without Docker Desktop)
    Back to Blog
    Running Docker MCP Gateway on Linux (Without Docker Desktop)
    docker

    Running Docker MCP Gateway on Linux (Without Docker Desktop)

    Daniel Schroeder April 9, 2026
    0 views

    Docker's MCP Toolkit is a great way to expose Model Context Protocol servers to AI clients like...

    Docker's MCP Toolkit is a great way to expose Model Context Protocol servers to AI clients like Claude, n8n, or Cursor. Out of the box it's designed for Docker Desktop on macOS and Windows — but what if you want to run it on a headless Linux server? A Raspberry Pi, a VPS, a home lab box?

    This guide walks through setting it up from scratch on Linux (Debian/Ubuntu, arm64 or amd64), including secrets management, custom MCP server images, and a systemd service that starts automatically on boot.

    This guide is based on getting it actually working on a Raspberry Pi 5 running Debian 13. Several things that look like they should work on Linux don't — I'll call those out explicitly so you don't waste time on the same dead ends.


    What We're Building

    A self-hosted MCP gateway that:

    • Runs any MCP server as a Docker container
    • Exposes them all behind a single HTTP endpoint with Bearer token auth
    • Starts automatically on boot via systemd
    AI Client  →  http://your-server:8811/sse  →  docker-mcp gateway  →  MCP containers
    

    Prerequisites

    • Linux host with Docker installed (Docker Engine, not Docker Desktop)
    • Your user in the docker group (sudo usermod -aG docker $USER)
    • SSH access if setting up remotely

    Step 1 — Install the docker-mcp Binary

    The docker mcp command is a Docker CLI plugin. On Linux you install it directly from the GitHub releases — no Docker Desktop needed.

    # Create the CLI plugins directory
    sudo mkdir -p /usr/local/lib/docker/cli-plugins
    
    # Download the binary for your architecture
    # arm64 (Raspberry Pi 4/5, Apple Silicon VMs):
    sudo curl -fsSL \
      https://github.com/docker/mcp-gateway/releases/download/v0.41.0/docker-mcp-linux-arm64.tar.gz \
      | sudo tar -xz -C /usr/local/lib/docker/cli-plugins/
    
    # amd64 (regular x86 server):
    sudo curl -fsSL \
      https://github.com/docker/mcp-gateway/releases/download/v0.41.0/docker-mcp-linux-amd64.tar.gz \
      | sudo tar -xz -C /usr/local/lib/docker/cli-plugins/
    
    sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-mcp
    
    # Verify
    docker mcp --version
    

    Check the releases page for the latest version.


    Step 2 — The docker-pass Workaround

    This is the first Linux-specific gotcha. docker mcp CLI commands (like docker mcp server ls) expect a Docker CLI plugin named docker-pass. This binary ships with Docker Desktop on macOS but not on Linux, causing this error:

    docker pass has not been installed
    

    The fix: a small wrapper script that satisfies the Docker CLI plugin protocol and delegates to docker-credential-pass.

    First, install docker-credential-pass:

    # arm64:
    sudo curl -fsSL \
      https://github.com/docker/docker-credential-helpers/releases/download/v0.9.5/docker-credential-pass-v0.9.5.linux-arm64 \
      -o /usr/local/bin/docker-credential-pass
    
    # amd64:
    sudo curl -fsSL \
      https://github.com/docker/docker-credential-helpers/releases/download/v0.9.5/docker-credential-pass-v0.9.5.linux-amd64 \
      -o /usr/local/bin/docker-credential-pass
    
    sudo chmod +x /usr/local/bin/docker-credential-pass
    

    Then create the wrapper plugin:

    sudo tee /usr/local/lib/docker/cli-plugins/docker-pass > /dev/null << 'EOF'
    #!/bin/bash
    if [[ "$1" == "docker-cli-plugin-metadata" ]]; then
      echo '{"SchemaVersion":"0.1.0","Vendor":"Docker","Version":"v1.0.0","ShortDescription":"Docker Pass secrets helper"}'
      exit 0
    fi
    exec docker-credential-pass "$@"
    EOF
    
    sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-pass
    

    Verify Docker recognizes it:

    docker info --format '{{.ClientInfo.Plugins}}' | tr ',' '\n' | grep pass
    # Should show: ...pass /usr/local/lib/docker/cli-plugins/docker-pass...
    

    Note: This wrapper is only needed for docker mcp CLI commands. The gateway itself uses a different mechanism for secrets — covered in Step 5.


    Step 3 — Pull or Load Your MCP Images

    Any Docker image that implements the MCP stdio protocol can be used as an MCP server.

    Option A: Images from the official Docker MCP catalog

    docker pull mcp/playwright:latest
    

    Option B: Custom/private images

    Transfer from another machine:

    # On the source machine:
    docker save mcp/my-server:latest | ssh your-linux-host "docker load"
    

    Step 4 — Configure the Gateway

    Create the config directory:

    mkdir -p ~/.docker/mcp/catalogs
    

    registry.yaml — which servers to enable

    cat > ~/.docker/mcp/registry.yaml << 'EOF'
    registry:
      playwright:
        ref: ""
      my-server:
        ref: ""
    EOF
    

    catalog.json — where to find catalog definitions

    The gateway needs to know where your catalog files live. By default it only reads the official Docker MCP catalog. Register additional catalogs here:

    cat > ~/.docker/mcp/catalog.json << 'EOF'
    {
      "catalogs": {
        "docker-mcp": {
          "displayName": "Docker MCP Catalog",
          "url": "https://desktop.docker.com/mcp/catalog/v2/catalog.yaml"
        },
        "my-catalog": {
          "displayName": "My Custom Servers",
          "url": "/home/youruser/.docker/mcp/catalogs/my-catalog.yaml"
        }
      }
    }
    EOF
    

    A catalog YAML for a custom server

    The catalog defines how a server runs and which env vars it needs. List all env vars under secrets: — including non-sensitive ones like usernames.

    Linux gotcha: The config: field in catalog YAMLs is not used for env var injection on Linux. Everything must be in secrets: to be passed to containers.

    registry:
      my-server:
        title: My MCP Server
        description: Does something useful
        image: mcp/my-server:latest
        type: server
        tools: []
        secrets:
          - name: my-server.api_key
            env: API_KEY
            description: API key for the service
          - name: my-server.username
            env: USERNAME
            description: Your username
    name: my-catalog
    displayName: My Catalog
    

    Step 5 — Secrets

    This is the second major Linux gotcha. docker mcp uses a secrets engine (se:// URIs) that is Docker Desktop-only and doesn't work on Linux. The docker mcp secret set command will fail with docker pass has not been installed even after you install the wrapper from Step 2.

    The solution is the --secrets flag, which points the gateway at a plain env file:

    # Create the secrets file
    cat > ~/.docker/mcp/secrets.env << 'EOF'
    my-server.api_key=your-api-key-here
    my-server.username=your-username
    EOF
    
    # Restrict permissions — only your user can read it
    chmod 600 ~/.docker/mcp/secrets.env
    

    The key names map to the name field in the catalog's secrets: list.

    Is this secure? The file is chmod 600 — readable only by your user, same as ~/.ssh/id_rsa. Anyone who can read it already has root or is you. If you want GPG encryption at rest, you can store sensitive values in pass and populate the file from it — but for an unattended service the threat model is the same either way.

    Are secrets isolated between MCP servers? Yes, completely. The secrets file is never passed to or mounted into any container. The gateway reads it internally and uses it purely as a lookup table. When spawning each container it passes only the specific -e VAR=value flags declared in that server's catalog secrets: list. You can verify this with --dry-run --verbose — the docker run command for each server is logged in full, and you'll see that playwright gets zero secret env vars, while my-server only gets USERNAME and API_KEY. There is no way for one MCP server to access another's credentials.


    Step 6 — Test the Gateway

    Do a dry run first:

    docker mcp gateway run \
      --dry-run \
      --verbose \
      --secrets ~/.docker/mcp/secrets.env \
      2>&1
    

    You should see all your configured servers listed and their tools counted, with no Warning: Secret '...' not found lines. If warnings appear, check that the key names in secrets.env exactly match the name fields in your catalog YAML.

    If everything looks good, start it live:

    docker mcp gateway run \
      --transport sse \
      --port 8811 \
      --secrets ~/.docker/mcp/secrets.env
    

    Step 7 — systemd Service

    Create the service file:

    sudo tee /etc/systemd/system/mcp-gateway.service > /dev/null << EOF
    [Unit]
    Description=Docker MCP Gateway
    Requires=docker.service
    After=docker.service network-online.target
    Wants=network-online.target
    
    [Service]
    Type=simple
    User=$(whoami)
    Environment=HOME=$HOME
    ExecStart=/usr/local/lib/docker/cli-plugins/docker-mcp gateway run \\
      --transport sse \\
      --port 8811 \\
      --secrets $HOME/.docker/mcp/secrets.env
    Restart=on-failure
    RestartSec=10
    
    [Install]
    WantedBy=multi-user.target
    EOF
    

    Set a stable Bearer token that survives restarts:

    sudo mkdir -p /etc/systemd/system/mcp-gateway.service.d
    
    TOKEN=$(openssl rand -hex 32)
    echo "Save this token: $TOKEN"
    
    sudo tee /etc/systemd/system/mcp-gateway.service.d/token.conf > /dev/null << EOF
    [Service]
    Environment=MCP_GATEWAY_AUTH_TOKEN=$TOKEN
    EOF
    

    Without this, the gateway generates a new random token on every start — which means reconfiguring every client after each restart.

    Enable and start:

    sudo systemctl daemon-reload
    sudo systemctl enable mcp-gateway.service
    sudo systemctl start mcp-gateway.service
    

    Check it's running:

    sudo systemctl status mcp-gateway.service
    journalctl -u mcp-gateway.service -f
    

    Connecting a Client

    The gateway runs on port 8811 with SSE transport:

    URL:   http://your-server:8811/sse
    Auth:  Authorization: Bearer <your-token>
    

    Claude Desktop

    Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or the equivalent on your OS:

    {
      "mcpServers": {
        "my-gateway": {
          "command": "npx",
          "args": [
            "mcp-remote",
            "http://your-server:8811/sse",
            "--header",
            "Authorization: Bearer <your-token>",
            "--allow-http",
            "--transport",
            "sse-only"
          ]
        }
      }
    }
    

    Two flags are required here that aren't obvious:

    • --allow-http — mcp-remote blocks non-HTTPS URLs by default
    • --transport sse-only — the default http-first strategy sends a POST that the gateway rejects with sessionid must be provided

    Troubleshooting

    docker pass has not been installed

    The docker-pass CLI plugin wrapper is missing or not executable. Re-check Step 2.

    Warning: Secret '...' not found

    The key name in secrets.env doesn't match the name field in the catalog YAML, or you forgot to pass --secrets to the gateway. Check with:

    docker mcp gateway run --dry-run --verbose --secrets ~/.docker/mcp/secrets.env 2>&1 | grep Warning
    

    Server shows 0 tools in dry-run but works live

    Some servers need the actual secrets present to respond to tool listing. This is normal — the gateway still starts them correctly at runtime.

    cannot use --port with --transport=stdio

    You must specify --transport sse when using --port. The default transport is stdio (for direct client connections), not HTTP.

    sessionid must be provided in mcp-remote

    Add --transport sse-only to the mcp-remote args. The default transport strategy tries Streamable HTTP first, which the gateway doesn't support.


    Keeping Things Updated

    Upgrade docker-mcp

    VERSION=v0.41.0  # replace with latest
    ARCH=arm64       # or amd64
    
    sudo curl -fsSL \
      https://github.com/docker/mcp-gateway/releases/download/$VERSION/docker-mcp-linux-$ARCH.tar.gz \
      | sudo tar -xz -C /usr/local/lib/docker/cli-plugins/
    
    sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-mcp
    sudo systemctl restart mcp-gateway.service
    

    Update a custom MCP image

    docker save mcp/my-server:latest | ssh your-linux-host "docker load"
    ssh your-linux-host "sudo systemctl restart mcp-gateway.service"
    

    Summary

    The key differences from macOS Docker Desktop:

    ConcernmacOS (Docker Desktop)Linux (headless)
    docker-mcp binaryBundled with Docker DesktopDownloaded from GitHub releases
    docker-pass pluginProprietary binaryWrapper script → docker-credential-pass
    Secrets injectiondocker mcp secret set + keychain--secrets <env-file> (chmod 600)
    Auto-startDocker Desktopsystemd service
    Transportstdio or SSESSE with --transport sse
    mcp-remoteDefault settings workNeeds --allow-http --transport sse-only

    Everything else — catalog YAMLs, registry.yaml, the docker mcp CLI — works identically between macOS and Linux once the above pieces are in place.

    Tags

    dockerlinuxmcptutorial

    Comments

    More Blog

    View all
    Context bankruptcy: The case for strategic forgetting for AI Agentsai

    Context bankruptcy: The case for strategic forgetting for AI Agents

    Most of us have seen a coding agent fail to complete a task we know it can do. We just don't...

    J
    James O'Reilly
    Parallel Compliance Engine: Drive-to-Sheets Multi-Agent Orchestrationgooglecloud

    Parallel Compliance Engine: Drive-to-Sheets Multi-Agent Orchestration

    When building Generative AI applications, developers often encounter a massive bottleneck: sequential...

    A
    Aryan Irani
    Is It Ethical to Post and Ask About Circuits on Dev.to?discuss

    Is It Ethical to Post and Ask About Circuits on Dev.to?

    I’ve been thinking about sharing some electronic circuit posts on Dev.to — small circuits, DIY...

    C
    codebunny20
    The One-Click Exporter: AI Studio Antigravity, Probed to Its Limitsagents

    The One-Click Exporter: AI Studio Antigravity, Probed to Its Limits

    What nobody tells you about exporting your multi-agent prototype to a local workspace. Every...

    L
    leslysandra
    Guarding the till while autonomous data agents do the diggingagenticarchitect

    Guarding the till while autonomous data agents do the digging

    Autonomous agents are genuinely good at answering messy business questions. Give one an LLM and a set...

    S
    Sireesha Pulipati
    Return on Attention: Why AI Code Reviews Are Wearing Us Outai

    Return on Attention: Why AI Code Reviews Are Wearing Us Out

    PR volume went up, ticket quality didn't, and the gap got filled with LLMs on both sides of the review: bots reviewing, bots replying, bots occasionally arguing with bots about priorities that only existed in a teammate's head. Our CEO named the actual problem, and it's bigger than code review.

    C
    christine

    Stay up to date

    Get the latest Stable Diffusion prompts, rules, and resources delivered to your inbox weekly.

    Neura Market LogoNeura Market

    Discover the best AI prompts, plugins, and resources for Stable Diffusion and more.

    Content Types

    • Rules
    • Prompts
    • MCPs
    • Agents
    • Guides

    Platforms

    • ChatGPT Directory
    • Claude Directory
    • Gemini Directory
    • Cursor Directory
    • Grok Directory
    • Perplexity Directory
    • DeepSeek Directory
    • CoPilot Directory
    • Stable Diffusion Directory
    • Midjourney Directory
    • All Directories

    Resources

    • Blog
    • Documentation
    • Help Center
    • Marketplace

    Legal

    • Privacy Policy
    • Terms of Service

    © 2026 Neura Market. All rights reserved.

    |

    Not affiliated with any AI platform vendors.

    Ready-made automations for this

    Workflows from the Neura Market marketplace related to this Stable Diffusion resource

    • Context-Aware Google Calendar Management with MCP Protocoln8n · $24.99 · Related topic
    • 🛠️ State Management for Long-Running n8n Workflows with Wait Nodesn8n · $24.99 · Related topic
    • eBay Item Feed Service API Gateway for AI Agentsn8n · $24.99 · Related topic
    • CYBERPULSE AI RedOps: Validate Email Security Gateway Payloadsn8n · $24.99 · Related topic
    Browse all workflows