Deploy a Remote MCP Server with Docker, TLS & Streamable HTTP

Updated on Aug 24, 2026
Mila H
6 MINS READ
Table of Contents
Deploy a Remote MCP Server with Docker

Most Model Context Protocol (MCP) environments stop at localhost. But to integrate AI agents across distributed and scalable infrastructure, you must deploy a remote MCP server with Docker. This establishes an internet-accessible endpoint secured by TLS, allowing external agents to query your internal tools reliably.

To successfully deploy a remote MCP server with Docker, follow this guide covering Ubuntu setup, container orchestration, reverse proxy configuration, and post-deployment validation.

Understanding Local Stdio vs. Remote HTTP (SSE)

By default, the Model Context Protocol uses a communication method called stdio (Standard Input/Output). Think of stdio like a hardwired, physical cable connecting two programs on the same computer. If you run an AI assistant on your local machine, it uses stdio to securely read files or execute scripts on that very same machine. It is fast and highly secure, but your tools are entirely trapped on that single piece of hardware.

To break out of this limitation and allow external AI agents to interact with your production infrastructure, you need an internet-accessible connection. This is why you must deploy a remote MCP server with Docker.

When you transition from a local script to a remote server, the communication method changes from local stdio to HTTP with SSE (Server-Sent Events).

Here is how that works in practice:

  • Client to Server (HTTP POST): When the external AI agent wants to execute one of your tools, it sends a standard HTTP POST request. This is the same standard protocol your browser uses to submit a login form.
  • Server to Client (SSE): Because AI tasks and infrastructure queries can take time to process, standard HTTP responses often time out. To solve this, the MCP server opens a continuous, one-way stream back to the AI client using SSE. Think of SSE like a live radio broadcast; the connection stays open permanently, allowing the server to push real-time event updates and data back to the AI the exact moment they are ready.

By wrapping your tools in this HTTP/SSE architecture, you safely convert a localized desktop script into a distributed, internet-ready API.

Prerequisites to Deploy a Remote MCP Server with Docker

Before you deploy a remote MCP server with Docker, ensure you have:

  • A fresh Ubuntu 22.04, 24.04, or newer with root or sudo privileges. We recommend using a robust Linux VPS for optimal container network performance.
  • A domain name with an A-record pointing to your server's public IPv4 address.

Step 1. Ubuntu OS and Engine Setup

The first step to deploy a remote MCP server with Docker involves installing the container engine itself and securing the OS.

Connect to your server via SSH and run the following commands to update packages and configure the firewall:

Bash
sudo apt update && sudo apt upgrade -ysudo apt install ufw -ysudo ufw allow OpenSSHsudo ufw enable

Next, add the official repository and install the Docker engine and Compose plugin:

Bash
sudo apt install ca-certificates curl -ysudo install -m 0755 -d /etc/apt/keyringssudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.ascsudo chmod a+r /etc/apt/keyrings/docker.asc echo \  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt updatesudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y

Step 2. Create Project Directory and Application Files

As we deploy a remote MCP server with Docker, the application code requires a framework capable of handling asynchronous HTTP streams. We will use the official Model Context Protocol SDK via the FastMCP wrapper.

Run the following commands to seamlessly deploy a remote MCP server with Docker in your target directory. We will create the workspace in /opt/mcp-server:

Bash
sudo mkdir -p /opt/mcp-servercd /opt/mcp-server

Create the main Python application file directly from your terminal:

Bash
sudo nano /opt/mcp-server/server.py

Add:

Python
from mcp.server.fastmcp import FastMCP # Initialize the server and bind host/port HERE to bypass the strict DNS rebinding lockmcp = FastMCP("ProductionRemoteServer", host="0.0.0.0", port=8000) @mcp.tool()def check_system_health() -> str:    """Returns the remote system health status."""    return "All remote systems are operational and secure." if __name__ == "__main__":    # Run the transport    mcp.run(transport="sse")

Save and close the file. Create the dependency file:

Bash
sudo cat << 'EOF' > requirements.txtmcpfastmcpuvicornEOF

Step 3. Containerize the Infrastructure

We containerize the application to deploy a remote MCP server with Docker reliably. Create the Dockerfile in the same directory:

Bash
sudo cat << 'EOF' > DockerfileFROM python:3.11-slimWORKDIR /appCOPY requirements.txt .RUN pip install --no-cache-dir -r requirements.txtCOPY server.py .EXPOSE 8000CMD ["python", "server.py"]EOF

When you deploy a remote MCP server with Docker in production, use a docker-compose.yml to define network isolation. Notice how we bind port 8000 strictly to 127.0.0.1 so it is not exposed directly to the internet, bypassing UFW:

Bash
Learn to deploy a remote MCP Server with Dockersudo cat << 'EOF' > docker-compose.ymlservices:  mcp-backend:    build: .    ports:      - "127.0.0.1:8000:8000"    env_file:      - .env    volumes:      - ./data:/app/data    restart: unless-stopped    healthcheck:      test: ["CMD", "curl", "-f", "-H", "Accept: text/event-stream", "http://127.0.0.1:8000/sse"]      interval: 30s      timeout: 10s      retries: 3EOF

Create the persistent environment file and data directory required to safely deploy a remote MCP server with Docker:

Bash
sudo mkdir -p datasudo cat << 'EOF' > .env# Persistent Environment VariablesENVIRONMENT=productionMCP_LOG_LEVEL=infoEOF

Now start the stack with:

Bash
sudo docker compose up -d

Step 4. Configure Nginx and TLS

You cannot safely deploy a remote MCP server with Docker over the public internet without encrypted TLS. Install Nginx and Let's Encrypt Certbot:

Bash
sudo apt install nginx certbot python3-certbot-nginx -ysudo ufw allow 'Nginx Full'

A common mistake when teams deploy a remote MCP server with Docker is failing to disable proxy buffering. Standard reverse proxies buffer HTTP responses, which immediately stop continuous SSE streams.

Create the Nginx server block and remember to replace the domain name with your actual domain:

Bash
sudo cat << 'EOF' > /etc/nginx/sites-available/mcpserver {    listen 80;    server_name mcp.yourdomain.com;     location / {        proxy_pass http://127.0.0.1:8000;        proxy_http_version 1.1;        proxy_set_header Connection '';                # Crucial for Server-Sent Events (SSE)        proxy_buffering off;        proxy_cache off;        chunked_transfer_encoding on;        proxy_set_header Host $host;    }}EOF

Enable the site, restart Nginx, and request the TLS certificate:

Bash
sudo ln -s /etc/nginx/sites-available/mcp /etc/nginx/sites-enabled/sudo nginx -tsudo systemctl reload nginxsudo certbot --nginx -d mcp.yourdomain.com

Let's Encrypt certificates are only valid for 90 days. Fortunately, the Certbot installation automatically configures a systemd timer that runs twice a day to renew any certificate within 30 days of expiration.

Verify that the auto-renewal timer is loaded and active in the background:

Bash
sudo systemctl status certbot.timer

Then, execute a dry run with the following command:

Bash
sudo certbot renew --dry-run

Step 5. Post-Deployment Operational Checks

After you deploy a remote MCP server with Docker, you must verify that the SSE connection remains stable and successfully routes traffic.

Test the health of your SSE stream using curl:

Bash
curl -N -H "Accept: text/event-stream" https://mcp.yourdomain.com/sse

You should now receive an immediate HTTP 200 response followed by a clean, hanging connection pushing the endpoint event stream.

Now your remote AI agents can connect securely.

Production Architecture and Hardware Requirements

Planning to deploy a remote MCP server with Docker requires considering hardware latency, disk I/O, and isolation limits. Because MCP tools often interact with secure local file systems, shell environments, or internal databases, strict container isolation on bare-metal or dedicated virtualized infrastructure is better.

Deploy the MCP server on a PerLod Linux VPS and register a dedicated domain or subdomain for the endpoint. This ensures absolute root control over your AI agents' environment and maintains strict security boundaries separate from your primary application infrastructure.

Conclusion

It is a massive architectural upgrade to securely deploy a remote MCP server with Docker compared to standard local implementations. By provisioning a clean Ubuntu environment, establishing strict container networks, accommodating recent SDK API changes, and leveraging Nginx with properly configured SSE streaming rules, your AI agents can safely access robust external data endpoints.

We hope you enjoy this guide.

Yes. The container uses Uvicorn, which natively handles concurrent requests. Each AI client gets its own independent stream, allowing multiple agents to query your tools at the same time without blocking the server.

The server is stateless by default. If your tools need to save data, like caches or logs, you must mount a persistent Docker volume or connect to an external database.

MCP uses SSE because it runs over standard HTTP. This makes it naturally compatible with standard proxies like Nginx, load balancers, and firewalls without requiring complex configuration.

Yes. Add each server as a separate service in your docker-compose.yml with unique internal ports. Then, configure Nginx to route different subdomains to those specific ports.