Selbst gehostete MCP-Server vermehren sich. Erst gibt es einen für die interne Dokumentation, dann einen für die Datenbank, dann schreibt jemand einen kleinen für die Deploy-Pipeline. Jeder bekommt seinen eigenen Port, seine eigene URL und sein eigenes Geheimnis, und jede Person im Team trägt alle drei in ihre Client-Konfiguration ein. Ein Token zu rotieren heißt, allen Bescheid zu sagen.
Ein Gateway macht daraus eine Adresse und ein Token. Clients verbinden sich mit https://mcp.example.com/docs/mcp, .../db/mcp und so weiter. Das Gateway prüft das Token, schickt jeden Pfad an den richtigen Server auf localhost, und die Server selbst sind nie offen. Dafür braucht es sehr wenig: einen kleinen VPS mit eigener IPv4 und Caddy.
Das folgende Setup haben wir auf einem Testserver gebaut und mit echten Clients geprüft, bevor wir es aufgeschrieben haben.
Was Sie brauchen
- Einen VPS mit öffentlicher IPv4, damit Clients Port 443 erreichen. Nano-IP reicht, solange Ihre MCP-Server selbst keine schwere Arbeit leisten.
- Eine Domain mit einem A-Record auf den Server, hier
mcp.example.com. - Ubuntu 24.04 oder Debian 12/13. Caddy ist in den Standard-Repositorys beider Systeme.
1. MCP-Server auf localhost betreiben
Jeder Server läuft als systemd-Dienst. Hier nutzen wir den Referenzserver server-everything zweimal, damit das Beispiel in sich geschlossen ist; setzen Sie Ihre eigenen ein. Er braucht Node.js 20 oder neuer:
mkdir -p /opt/mcp && cd /opt/mcp
npm install @modelcontextprotocol/server-everything
# /etc/systemd/system/mcp-everything-1.service
[Unit]
Description=MCP server everything #1
After=network.target
[Service]
WorkingDirectory=/opt/mcp
Environment=PORT=3101
ExecStart=/opt/mcp/node_modules/.bin/mcp-server-everything streamableHttp
Restart=always
User=nobody
[Install]
WantedBy=multi-user.target
Eine zweite Kopie nutzt Port 3102. Dann:
systemctl daemon-reload
systemctl enable --now mcp-everything-1 mcp-everything-2
Beim Testen ist uns aufgefallen: Dieser Server lauscht auf allen Interfaces, nicht nur auf 127.0.0.1, und viele andere tun das auch. Schritt 3 kümmert sich darum.
2. Caddy: erst das Token prüfen, dann nach Pfad routen
Erzeugen Sie ein Token und geben Sie es Caddy über eine Umgebungsdatei:
apt install -y caddy
echo "MCP_GATEWAY_TOKEN=$(openssl rand -hex 32)" > /etc/caddy/gateway.env
chmod 600 /etc/caddy/gateway.env
mkdir -p /etc/systemd/system/caddy.service.d
printf '[Service]\nEnvironmentFile=/etc/caddy/gateway.env\n' > /etc/systemd/system/caddy.service.d/env.conf
systemctl daemon-reload
Die Caddyfile:
mcp.example.com {
route {
@unauthorized not header Authorization "Bearer {$MCP_GATEWAY_TOKEN}"
respond @unauthorized 401
handle_path /everything/* {
reverse_proxy 127.0.0.1:3101 {
flush_interval -1
}
}
handle_path /tools2/* {
reverse_proxy 127.0.0.1:3102 {
flush_interval -1
}
}
respond 404
}
}
caddy validate --config /etc/caddy/Caddyfile && systemctl restart caddy
Das Zertifikat für mcp.example.com holt sich Caddy selbst.
Der route-Block ist keine Dekoration. Unsere erste Version hatte die Token-Prüfung und die handle_path-Blöcke nebeneinander auf oberster Ebene, und Anfragen ohne Token gingen mit 200 durch. Caddy sortiert Direktiven in seiner eigenen Reihenfolge, und handle_path läuft vor respond. Innerhalb von route laufen sie in der geschriebenen Reihenfolge. Wenn Sie diese Konfiguration anpassen, testen Sie zuerst den Fall „ohne Token“.
handle_path entfernt das Präfix, /everything/mcp kommt beim Server also als /mcp an. flush_interval -1 reicht gestreamte Events sofort durch.
3. Alles schließen außer SSH und HTTPS
apt install -y ufw
ufw default deny incoming
ufw allow OpenSSH
ufw allow 80,443/tcp
ufw enable
Danach waren die Ports 3101 und 3102 in unserem Test von außerhalb des Servers nicht erreichbar, während 22 und 443 antworteten. Port 80 bleibt nur offen, damit Caddy Zertifikate holen und erneuern und auf HTTPS umleiten kann.
4. Prüfen
TOKEN=$(cut -d= -f2 /etc/caddy/gateway.env)
INIT='{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"check","version":"1"}}}'
curl -s -o /dev/null -w '%{http_code}\n' -X POST https://mcp.example.com/everything/mcp \
-H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream' -d "$INIT"
curl -s -o /dev/null -w '%{http_code}\n' -X POST https://mcp.example.com/everything/mcp \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream' -d "$INIT"
Die erste Anfrage sollte 401 ausgeben, die zweite 200. In unserem Durchlauf bekamen ein falsches und ein abgeschnittenes Token beide 401, und ein unbekannter Pfad bekam selbst mit richtigem Token 404.
Dann von einem Client aus, zum Beispiel Claude Code:
claude mcp add --transport http everything https://mcp.example.com/everything/mcp \
--header "Authorization: Bearer $TOKEN"
claude mcp list
Beide Server zeigten ✔ Connected. Derselbe Client mit falschem Token zeigte ✘ Failed to connect. Mehr zur Client-Einrichtung in EQVPS MCP mit Claude Code und Codex verbinden.
Den nächsten Server hinzufügen
Starten Sie ihn auf einem neuen localhost-Port, fügen Sie einen handle_path-Block hinzu, laden Sie Caddy neu. Bei niemandem ändert sich die Konfiguration, außer um eine neue URL unter demselben Host mit demselben Token.
Grenzen, die man kennen sollte
- Ein Token für alle ist einfach, und es zu rotieren ist eine Datei. Sie können aber niemandem einzeln den Zugang entziehen, ohne ihn für alle zu ändern. Für Zugriff pro Nutzer setzen Sie einen Auth-Proxy davor oder geben jeder Person eine eigene Route und ein eigenes Token.
- Das Gateway macht einen Server nicht sicher. Ein MCP-Server, der Shell-Befehle ausführt, ist für jeden mit dem Token weiterhin eine Shell. Halten Sie Tokens aus geteilten Konfigurationen und aus git heraus.
- Dimensionieren Sie nach den Servern, nicht nach dem Gateway. Caddy selbst braucht ein paar Dutzend Megabyte. Wenn einer Ihrer Server ein lokales Modell betreibt oder ein großes Repository indiziert, bestimmt er den Tarif, nicht der Proxy.
Nur ein MCP-Server? VPS für MCP-Server behandelt diesen einfacheren Fall. Sollen Ihre Agenten auch den Server verwalten, auf dem sie leben? Das kann der EQVPS MCP-Server (oder die REST API, wenn Sie lieber skripten), und die Tarife mit eigener IPv4 beginnen bei $8 im Monat.
Kommentare
Noch keine Kommentare. Sei der Erste.