Zum Inhalt springen

Docker-Stack-Bereitstellung

Single-Port-Modell: Eine Express-Anwendung im mcp-server-Container lauscht auf :3847 und bedient /mcp, /admin, /artifacts, /health, /instances. Die TLS-Terminierung wird vom Reverse-Proxy des Hosts (Caddy oder Nginx) übernommen.

+-------------------------------------------------------------+
| Docker Compose Stack |
+-------------------------------------------------------------+
| +------------------+ +------------------+ +-------------+ |
| | MCP Server | | OnlyOffice | | Artifact | |
| | Port: 3847 |--| Port: 9980 | | Cleanup | |
| | /mcp /admin | | (Document | | (Cron) | |
| | /artifacts | | Builder) | | | |
| | /health | | | | | |
| +--------+---------+ +------------------+ +------+------+
| | | |
| +----------- /var/artifacts ----------+ |
+-------------------------------------------------------------+
Dienst Basis-Image Port Zweck
mcp-server node:25-slim (mehrstufig) 3847 MCP-Server + Admin-UI + Artefakt-Downloads
onlyoffice onlyoffice/documentserver 9980 (intern) Engine zur Dokumenterstellung
artifact-cleanup alpine:3.20 + supercronic - Entfernt abgelaufene Artefakte (konfigurierbare TTL)

Optionale Dienste über Docker-Compose-Profile: minio (--profile s3), samba (--profile smb).

  1. Repository klonen

    Terminal window
    git clone https://gitlab.satware.com/satware/mcp/onlyoffice.git
    cd onlyoffice
  2. Umgebung konfigurieren

    Terminal window
    cp docker/.env.example docker/.env
    # Bearbeiten Sie docker/.env mit Ihren Produktionswerten

    Wichtige zu setzende Variablen:

    Variable Beschreibung Beispiel
    JWT_SECRET OnlyOffice JWT-Secret openssl rand -hex 32
    ADMIN_PASSWORD Passwort für die Admin-UI (erforderlich) sicheres Passwort
    CORS_ORIGINS Erlaubte Origins für /mcp https://your-domain.com
    ARTIFACT_BASE_URL Basis-URL für Artefakt-Downloads https://your-domain.com/artifacts
    CREDENTIAL_MASTER_PASSWORD Aktiviert die Anmeldeinformation-Tools (optional) sicheres Passwort
  3. Dienste erstellen und starten

    Terminal window
    docker compose -f docker/docker-compose.yml build
    docker compose -f docker/docker-compose.yml up -d
  4. Bereitstellung verifizieren

    Terminal window
    # Health-Check
    curl -f http://localhost:3847/health
    # Erwartet: {"status":"healthy","version":"1.3.0",...}
    # Admin-Login
    curl -c /tmp/cookies.txt -X POST http://localhost:3847/admin/login \
    -H "Content-Type: application/json" \
    -d '{"password":"<your-password>"}'
    # Erwartet: {"success":true,"authenticated":true}
    # Vorlagen auflisten
    curl -b /tmp/cookies.txt http://localhost:3847/admin/templates | jq '.templates | length'
    # Erwartet: 5
Variable Beschreibung
JWT_SECRET JWT-Secret für die Authentifizierung am OnlyOffice Document Server
ADMIN_PASSWORD Passwort für die /admin-UI. Falls nicht gesetzt, gibt /admin 503 zurück
CORS_ORIGINS Kommaseparierte erlaubte Origins (Produktion: einschränken, nicht * verwenden)
Variable Standard Beschreibung
ARTIFACT_BASE_URL (nicht gesetzt) Basis-URL für Downloads. Nicht gesetzt = Base64-Auslieferung
ARTIFACT_STORAGE_DIR /var/artifacts Verzeichnis für gespeicherte Artefakte
ARTIFACT_EXPIRY_MS 86400000 (24 h) Millisekunden bis zum Ablaufen von Artefakten
ARTIFACT_CLEANUP_INTERVAL_MS 3600000 (1 h) Intervall der Aufräum-Sweeping-Läufe
Variable Beschreibung
CREDENTIAL_MASTER_PASSWORD Aktiviert 5 Tools zur Verwaltung von Anmeldeinformationen
CREDENTIAL_STORE_PATH Pfad zum verschlüsselten Anmeldeinformation-Speicher
DOCKER_GID Host-Docker-GID für Socket-Zugriff
HOST_UID / HOST_GID UID/GID für Bind-Mount-Berechtigungen
Port Dienst Zugriff
3847 MCP-Server (alle Endpunkte) Eingehend – AI-Clients, Bediener
9980 OnlyOffice Nur intern (Docker-backend-Netzwerk)
Terminal window
# MCP-Server-Zugriff aus dem internen Netzwerk erlauben
ufw allow from 10.0.0.0/8 to any port 3847
# Externen Zugriff auf OnlyOffice blockieren
ufw deny 9980

Der MCP-Server verwendet das Streamable-HTTP-Transport mit SSE (Server-Sent Events) für Server-zu-Client-Benachrichtigungen. Reverse-Proxys dürfen diese Antworten nicht puffern.

https://mcp.example.com {
reverse_proxy localhost:3847 {
flush_interval -1
stream_timeout 24h
}
}

Caddy erkennt Content-Type: text/event-stream automatisch und leert sofort den Puffer (Flush). Die Direktiven flush_interval -1 und stream_timeout 24h bieten zusätzlichen Schutz für langlebige Streaming-Verbindungen.

Caddy stellt TLS-Zertifikate automatisch über Let’s Encrypt aus.

upstream mcp_server {
server localhost:3847;
}
server {
listen 443 ssl;
server_name mcp.example.com;
ssl_certificate /etc/ssl/certs/mcp.crt;
ssl_certificate_key /etc/ssl/private/mcp.key;
location / {
proxy_pass http://mcp_server;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_buffering off;
proxy_read_timeout 3600s;
}
}

Die Direktive proxy_buffering off deaktiviert das Antwort-Puffern für SSE-Streaming. proxy_read_timeout 3600s verhindert, dass nginx inaktive SSE-Verbindungen nach dem Standard-Timeout von 60 Sekunden schließt.

Synology-NAS-Geräte mit DSM 7.x enthalten einen integrierten Reverse-Proxy auf Basis von nginx. Konfigurieren Sie ihn über Systemsteuerung > Anmeldeportal > Erweitert > Reverse-Proxy.

Erstellen Sie eine neue Reverse-Proxy-Regel:

Einstellung Wert
Quell-Protokoll HTTPS
Quell-Hostname mcp.example.com
Quell-Port 443
Ziel-Protokoll HTTP
Ziel-Hostname localhost
Ziel-Port 3847

Keine manuelle Konfiguration erforderlich. Der MCP-Server sendet den Antwort-Header X-Accel-Buffering: no auf allen /mcp-Antworten. DSMs nginx berücksichtigt diesen Header und deaktiviert das Puffern pro Antwort automatisch.

DSMs Standard-proxy_read_timeout beträgt 60 Sekunden. Nach 60 Sekunden ohne Daten im SSE-Stream schließt nginx die Verbindung und der MCP-Client verbindet sich automatisch neu. Dies ist normales SSE-Verhalten und beeinträchtigt Tool-Aufrufe nicht (diese verwenden kurze POST-Anfragen).

Falls längere Inaktivitätsphasen gewünscht sind, erstellen Sie ein Aufgabenplaner-Skript (Systemsteuerung > Aufgabenplaner > Erstellen > Ausgelöste Aufgabe > Benutzerdefiniertes Skript), das beim Start ausgeführt wird:

#!/bin/bash
# proxy_read_timeout in die DSM-Reverse-Proxy-Konfiguration injizieren
# Läuft beim Start, um zu verhindern, dass DSM die nginx-Konfigurationen neu schreibt
CONF=$(grep -rl "proxy_pass.*:3847" /etc/nginx/app.d/ 2>/dev/null)
if [ -n "$CONF" ] && ! grep -q "proxy_read_timeout 3600s" "$CONF"; then
sed -i '/proxy_pass.*:3847/a\ proxy_read_timeout 3600s;' "$CONF"
nginx -s reload
fi

Aktivieren Sie die WebSocket-Unterstützung in den Reverse-Proxy- Einstellungen. Für SSE nicht erforderlich, jedoch benötigt, wenn die Admin-UI über denselben Proxy bereitgestellt wird.

Endpunkt Methode Erwartet
/health GET {"status":"healthy"}
/instances GET Instanzliste mit Health-Status
/artifacts GET Artefaktliste
Terminal window
# Cron-Health-Check (alle 5 Min)
*/5 * * * * curl -sf http://localhost:3847/health > /dev/null || echo "MCP DOWN" | logger -t onlyoffice-mcp
Terminal window
cd /opt/onlyoffice-mcp
git pull origin main
docker compose -f docker/docker-compose.yml build
docker compose -f docker/docker-compose.yml up -d