ScreenshotNeo

BlogHow-to

How to Run an MCP Router on Linux

Install Docker's MCP Gateway on Linux, connect multiple servers, compare HTTP routing, and troubleshoot transports, security, and persistence.

By the ScreenshotNeo team1 October 20267 min read

Short answer: On Linux without Docker Desktop, install Docker’s MCP Gateway CLI plugin at ~/.docker/cli-plugins/docker-mcp, make it executable, add MCP servers to a profile, and run docker mcp gateway run --profile PROFILE. MCP clients that support stdio can launch that command directly. If you need an HTTP router with per-server endpoints and a web UI, evaluate the separate cubicecho/mcp-router project instead.

What an MCP router does

An MCP router sits between an MCP client and one or more MCP servers. The client sees a managed connection while the router handles server selection, process or container startup, credentials, and transport details. Docker describes its MCP Gateway as “a centralized proxy between clients and servers, managing configuration, credentials, and access control.” See the Docker MCP Gateway documentation for version-specific commands.

There are two Linux approaches covered here:

Approach Use it when Connection model
Docker MCP Gateway You want Docker-managed servers, profiles, and a CLI gateway. stdio by default; Docker also documents SSE and streaming transports.
cubicecho/mcp-router You need a standalone HTTP router, per-server URLs, and a web UI. /mcp/<name> for one server and /mcp for an aggregate endpoint.

Before you install

  • Use a Linux host where Docker Engine is installed and usable by your account.
  • Confirm which MCP transport your client accepts: stdio, SSE, or streaming.
  • Identify the MCP servers you need and read each server’s credential and configuration requirements.
  • Decide whether the router should be local-only or reachable by other machines.

Run Docker MCP Gateway on Linux

1. Install the CLI plugin

Docker Engine users without Docker Desktop must install the gateway separately. Download the current Linux release binary from the project’s release page, place it at the Docker CLI plugin path, and make it executable:

mkdir -p ~/.docker/cli-plugins
# Place the downloaded Linux release binary at:
# ~/.docker/cli-plugins/docker-mcp
chmod +x ~/.docker/cli-plugins/docker-mcp
docker mcp --help

The commands above show the documented destination and permission step. Select the release asset that matches your Linux architecture and check the current release instructions before installing.

2. Inspect available catalogs and servers

docker mcp catalog server ls mcp/docker-mcp-catalog

The catalog example is illustrative. Choose server IDs that match your task and follow each server’s documentation for required environment variables, tokens, OAuth setup, or mounted files.

3. Create a profile and add servers

docker mcp profile server add my-profile \
  --server catalog://mcp/docker-mcp-catalog/github-official

A Docker MCP profile is the collection of servers that the gateway exposes. Add every server the client should be allowed to use, and configure any required settings before starting the gateway.

4. Start the gateway

docker mcp gateway run --profile my-profile

stdio is the default gateway transport. Docker also documents sse and streaming; inspect the installed command’s help and your client documentation before selecting another value.

5. Connect an MCP client over stdio

For a client without a dedicated Docker integration, create an MCP server entry that launches:

{
  "mcpServers": {
    "linux-gateway": {
      "command": "docker",
      "args": ["mcp", "gateway", "run", "--profile", "my-profile"]
    }
  }
}

Each client uses its own configuration file and schema. Keep the command and arguments equivalent, but follow the target client’s exact placement, naming, and environment-variable rules.

6. Verify the connection

  1. Open the client’s MCP or integrations status view.
  2. Confirm that linux-gateway is connected.
  3. Invoke one tool from one selected server.
  4. Check the server’s response and the gateway’s logs for startup or credential errors.

Verification commands differ across clients. Do not assume the gateway is working until a real tool call succeeds in the client and on the target Linux host.

Use cubicecho/mcp-router as an HTTP alternative

cubicecho/mcp-router is a separate third-party implementation, not Docker’s gateway. Its documentation describes a Docker Compose quickstart and a bare Node deployment requiring Node >= 22.18. It exposes individual servers under /mcp/<name>, an aggregate endpoint under /mcp, and a web UI for configuration. Read its project documentation for the current configuration format and release instructions.

Choose this option when

  • Your client requires an HTTP endpoint instead of a child process over stdio.
  • You want separate URLs for individual MCP servers.
  • You need the project’s web UI for managing server configuration.
  • You can operate a Node or Docker Compose service and protect its network endpoint.

Network binding

The project documentation says it binds all interfaces by default. Set HOST=127.0.0.1 when the router should only be reachable from the local machine. If remote access is required, place it behind your normal TLS, firewall, and authentication controls.

Security checklist

  • Limit enabled servers: expose only the servers required by the profile or workspace.
  • Protect credentials: use the gateway’s documented controls for secret transfer and server configuration; never commit tokens to client configuration files.
  • Review gateway controls: Docker’s command reference includes options for blocking network access, secret transfer, signature verification, enabled servers, and dry-run configuration. Run docker mcp gateway run --help on the installed version because flags can change.
  • Restrict HTTP routers: keep the bearer token private and bind to localhost unless remote access is deliberate.
  • Treat installed servers as code: the HTTP router runs server packages as child processes with configured environment variables.
  • Handle activity logs carefully: the third-party router documentation warns that recorded activity can retain proxied call bodies in process memory. Disable or restrict logging when payloads contain secrets or personal data.

Performance and reliability

  • Startup latency: container or child-process startup can make the first tool call slower. Keep the gateway process running when the client supports a long-lived connection.
  • Profile size: expose only needed servers so discovery and routing stay predictable.
  • Transport choice: stdio is usually simplest for a local client. Use SSE or streaming only when the client and network path support them.
  • Failure isolation: test each server independently. A broken credential, package, or container can prevent that server from being useful even when the router itself is healthy.
  • Operations: use your distribution’s service manager and the selected project’s release guidance for persistence. There is no single distro-independent systemd unit in the available documentation.
  • Version drift: release assets, CLI flags, catalog IDs, and client schemas change. Check the installed command’s help and current project documentation during upgrades.

Or skip the browser setup

If one of the MCP tools you need is website capture, ScreenshotNeo provides an MCP server with take_screenshot, get_page_info, and capture_pdf for Claude, Cursor, and other MCP clients. It can be added alongside your other servers, or called directly through its API. The API returns PNG, JPEG, WebP, or PDF from one GET request.

cURL (see the ScreenshotNeo API documentation):

curl -G "https://api.screenshotneo.com/v1/shot" \
  -d access_key=YOUR_API_KEY \
  --data-urlencode url=https://stripe.com \
  -o shot.webp

Python:

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)

Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const buffer = Buffer.from(await res.arrayBuffer());
require('fs').writeFileSync('shot.webp', buffer);

Cookie and consent banners, newsletter popups, and chat widgets are removed before the shot. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the result with X-Page-Verdict and X-Billed headers. An MCP server lets AI agents take screenshots. The Free plan includes 1,000 screenshots a month with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.

Troubleshooting

docker mcp is unknown

Cause: the plugin is missing, in the wrong directory, or not executable.

Fix: confirm the file is exactly ~/.docker/cli-plugins/docker-mcp, run chmod +x ~/.docker/cli-plugins/docker-mcp, and retry docker mcp --help. Confirm that the binary matches the host architecture.

The gateway starts but no tools appear

Cause: the profile has no servers, the server ID is wrong, or required settings are missing.

Fix: list catalog servers, add the exact server reference to the profile, then configure the server’s credentials and restart the gateway.

The client cannot launch the gateway

Cause: the client configuration uses the wrong command, argument order, working directory, or transport.

Fix: run docker mcp gateway run --profile my-profile manually first, then copy the same command and arguments into the client’s stdio entry using that client’s documented schema.

A server fails while other servers work

Cause: server-specific credentials, package dependencies, permissions, or network access.

Fix: test the failing server alone, inspect its logs, verify its required environment variables, and check gateway network or secret-transfer restrictions.

Remote HTTP clients cannot connect

Cause: the router is bound to localhost, a firewall blocks the port, or authentication is missing.

Fix: choose an intentional bind address, open only the required firewall path, use TLS and authentication at the network edge, and keep the bearer token private.

Requests expose sensitive data in logs

Cause: activity recording can retain proxied call bodies in process memory in the third-party router.

Fix: disable or limit activity logging, restrict access to the host, and avoid sending secrets in tool arguments.

FAQ

Can I run Docker’s gateway without Docker Desktop?

Yes. Install the Linux release binary as ~/.docker/cli-plugins/docker-mcp, make it executable, and run it through Docker Engine.

Does one profile have to contain every server?

No. Create profiles for different tasks or clients and add only the servers each profile should expose.

Is cubicecho/mcp-router the same as Docker MCP Gateway?

No. They are separate projects with different deployment models, endpoints, and configuration workflows.

Which transport should a local Linux client use?

Use stdio when the client can launch the gateway locally. Consider SSE or streaming only when both the client and the network deployment support them.

How do I keep the router running after logout?

Use the service manager and persistence instructions for your distribution and the selected router project. Validate the service under the same account and environment that owns the MCP credentials.