mcp-cloud-bereitstellung — Cloud-MCP fuer Kunden

End-to-End-Workflow um den VF-Pattern (Vibe Factory, erstmals 2026-05-02 ausgerollt) auf einen neuen Kunden zu replizieren. Lessons Learned + Realitaets-Korrekturen sind hier eingefangen — die erste VF-Iteration hat ~6 Std gebraucht, mit diesem Skill und dem Repo-Template sollte ein Kunde in ~3 Std live sein (plus 1-2 Tage AVV-Wartezeit fuer Scalekit).

Source of Truth: mcp-vf-hosted — vollstaendiges Cookbook + Architektur. Plan + Threat-Model: alter Pfad ~/source/agent-agentur/runs/2026-05-02-vf-mcp-hosting-plan/plan.md (noch nicht migriert).

Wann triggert dieser Skill

  • Kunde will MCP-Tools in claude.ai (nicht Claude Desktop)
  • Kunde ist Single-Tenant (eine Person oder eine Org wo alle Tool-Calls als ein User laufen)
  • Mehrere unserer Sub-MCPs sollen kombiniert werden (z.B. Buchhaltung + CRM + File-Storage)
  • Sub-MCPs existieren schon in ~/source/mcps/ (sonst zuerst mcp-eigenbau)

NICHT triggern wenn:

  • Nur ein Sub-MCP + lokaler Use-Case → Claude Desktop reicht
  • Multi-User mit Pro-User-Permission-Isolation noetig → Phase-6-Plan, separate Architektur (Delegated Auth)
  • Ad-hoc / Workshop-Demo → Cloudflare-Tunnel auf Marvins lokalem MCP, siehe claude-custom-connector

Voraussetzungen (vom Kunden)

WasWo
API-Tokens fuer alle Sub-MCPs (Papierkram, TicketPAY, M365, …)Kunde generiert in seinen Tool-Backends, schickt per Signal/Threema
M365-Tenant-Admin-Zugrifffalls m365 dabei ist — Kunde oder sein Admin
Domain wo Subdomain hinkommtDefault mcp-<kunde>.agenticventures.de (unsere Zone)

Vor-Entscheidungen (bevor Code-Touch)

EntscheidungDefault
Subdomain-Namemcp-<kunde>.agenticventures.de (<kunde> = kurzer Name, kein Bindestrich falls vermeidbar)
Welche Sub-MCPs?Liste auf einer Zeile mit Kunde abstimmen — bestimmt was im Mono gemountet wird
M365-App: neu oder bestehend reusen?Default: NEU — independent revocation + Audit-Trail-Trennung. Marvin gegen Bequemlichkeit
Mail-Permissions im M365Default: NICHT mit reinnehmen ausser Kunde hat klaren Use-Case. Wenn ja: ApplicationAccessPolicy ist Pflicht (Mailbox-Whitelist)
Production-Scalekit-Tenant?Test-Tenant (.scalekit.dev) reicht fuer Dev-Tests. Fuer echten Kunden-Live: Production-Tenant (.scalekit.com) anlegen

Step-by-Step

0. Vor-Klaerung mit Kunde (~30 Min Call)

  • Welche Tools sollen verbunden werden?
  • Welcher User ist der Connector-Nutzer? (eine Person, ihre Email)
  • Bei M365: welche SharePoint-Site fuer Site-Grant? Welche Mailbox fuer Mail-Tools?
  • AVV-Status: braucht der Kunde formellen AVV mit AV (wir) + Scalekit? Bei VF-grossen Kunden ja.

1. Repo-Setup (~15 Min)

# Template kopieren — mcp-vf-hosted ist Referenz
cp -r ~/source/mcps/mcp-vf-hosted ~/source/mcps/mcp-<kunde>-hosted
cd ~/source/mcps/mcp-<kunde>-hosted
 
# Anpassen:
# - pyproject.toml: name, description
# - src/mcp_<kunde>_hosted/main.py: _SUB_MCP_COMMANDS Dict (welche Sub-MCPs)
# - src/mcp_<kunde>_hosted/main.py: _SUB_MCP_ENV (welche ENV-Vars zu welchem Sub-MCP)
# - .env.example: alle ENV-Keys aktualisieren
# - README.md: Kunden-Name anpassen
# - Modul-Pfad: src/mcp_vf_hosted/ -> src/mcp_<kunde>_hosted/
 
uv sync --all-extras
uv run pytest  # alle 19+ Tests muessen gruen sein

2. Scalekit (~15 Min Browser + 1-2 Tage AVV parallel)

  1. https://app.scalekit.com → Sign up oder existierender Workspace → EU-Region
  2. Organisation anlegen mit Kunden-Name (z.B. “Vibe Factory”) — User werden in dieser Org verwaltet
  3. MCP Server anlegen (Dashboard → MCP Servers → New)
    • Resource Identifier = die spaetere MCP-URL exakt: https://mcp-<kunde>.agenticventures.de/mcp
  4. Resource ID notieren (res_...), Environment URL notieren
  5. User fuer Kunde anlegen in der Org: per Email-Invitation. User bekommt Scalekit-Mail mit Magic-Link, setzt Passwort selbst.
  6. AVV anfordern bei Scalekit Sales/Legal — Email an support@scalekit.com mit Workspace-Name
  7. Optional: Production-Tenant .scalekit.com anlegen wenn aus Test-Phase raus (Procedure wiederholbar)

Per API geht alles ausser Account-Anlage — Resource konfigurieren, User anlegen, etc. via REST mit Client-Credentials. Beispiel-Sequenzen in mcp-vf-hosted.

3. M365-App-Registration (wenn m365 dabei, ~30 Min)

Bei Kunden-Tenant einloggen, neue App anlegen:

  • Name: mcp-<kunde>-cloud (Agentic Ventures)
  • Permissions: Sites.Selected, optional Files.ReadWrite.All, optional Mail.ReadWrite + Mail.Send
  • Admin-Consent klicken
  • Client Secret erstellen, sofort speichern

Site-Grant fuer SharePoint-Site (PowerShell mit Microsoft Graph + Sites.FullControl.All Scope, Snippet in Setup-Doku §1).

ApplicationAccessPolicy wenn Mail-Permissions dabei sind (Exchange Online PowerShell, Mailbox-Whitelist — sonst hat App tenant-weit Zugriff auf alle Mailboxen, gefaehrlich). Snippet in Setup-Doku §1.

4. Mono-Repo + GitHub-Push

# Wenn nicht schon: ~/source/mcps/ ist git-init
cd ~/source/mcps
git add -A && git commit -m "Add mcp-<kunde>-hosted"
git push

5. Railway-Deploy (~30 Min)

cd ~/source/mcps/mcp-<kunde>-hosted
 
# Project anlegen
railway init --name <kunde>-mcp-hosting
 
# Service mit ENV-Vars (non-secrets gehen via --variables)
railway add --service <kunde>-mcp \
  --variables "SCALEKIT_ENV_URL=https://<tenant>.eu.scalekit.dev" \
  --variables "SCALEKIT_RESOURCE_ID=res_..." \
  --variables "PUBLIC_BASE_URL=https://mcp-<kunde>.agenticventures.de" \
  --variables "LOG_LEVEL=INFO" \
  --variables "RATE_LIMIT_PER_MINUTE=60" \
  --variables "RATE_LIMIT_PER_HOUR=1000" \
  --variables "HOST=0.0.0.0" \
  --variables "PORT=8080"
 
# Secrets via stdin (nicht im Bash-Echo, nicht im Log)
echo "$PAPIERKRAM_TOKEN" | railway variables --set-from-stdin "PAPIERKRAM_TOKEN" --skip-deploys
echo "$TICKETPAY_API_KEY" | railway variables --set-from-stdin "TICKETPAY_API_KEY" --skip-deploys
echo "$M365_CLIENT_SECRET" | railway variables --set-from-stdin "M365_CLIENT_SECRET" --skip-deploys
# ... weitere Secrets
echo "$M365_TENANT_ID" | railway variables --set-from-stdin "M365_TENANT_ID" --skip-deploys
echo "$M365_CLIENT_ID" | railway variables --set-from-stdin "M365_CLIENT_ID" --skip-deploys
 
# Deploy aus lokalem Mono-Repo (Build-Context = ~/source/mcps/)
cd ~/source/mcps && railway up --ci --detach
 
# Custom Domain
railway domain mcp-<kunde>.agenticventures.de --port 8080
# Output enthaelt CNAME-Target — bei Domain-Hoster (Strato/INWX/...) eintragen

6. DNS

Im Domain-Hoster (Strato fuer agenticventures.de):

  • Type: CNAME, Name: mcp-<kunde>, Target: <railway-cname>.up.railway.app
  • Propagation: meist 5 Min, manchmal 1-15 Min
  • TLS-Cert via Railway/Cloudflare automatisch (kann 5-30 Min dauern, manchmal laenger)

7. Pen-Test-Checkliste (~15 Min)

Volle Liste im VF-Plan §7 (Pfad: ~/source/agent-agentur/runs/2026-05-02-vf-mcp-hosting-plan/plan.md — nicht migriert) und in mcp-vf-hosted. Quick-Checks:

URL=https://mcp-<kunde>.agenticventures.de
curl -sI $URL/health  # 200
curl -sI $URL/mcp  # 401 + WWW-Authenticate mit PRM-Pointer
curl $URL/.well-known/oauth-protected-resource/mcp  # JSON mit Scalekit-AS
echo | openssl s_client -servername mcp-<kunde>.agenticventures.de -connect mcp-<kunde>.agenticventures.de:443 2>/dev/null | openssl x509 -noout -subject  # CN matched Domain
curl -sI $URL/health | grep -i strict-transport  # HSTS header da

8. Kunde-Onboarding (~10 Min, davon 3 Min Kunde)

Email-Template: an Kunde mit Anleitung. Andre-Onboarding-Vorlage als Referenz: alter Pfad ~/source/agent-agentur/wiki/kunden/vibe-factory/artefakte/andre-onboarding-claude-ai-mcp.md (noch nicht nach extern/outbound/deliverables/vibe-factory/ migriert).

Wichtig in der Mail:

  • Hinweis dass Scalekit eine separate Invitation-Mail schickt (Spam-Folder pruefen)
  • Scalekit-Login muss VOR claude.ai-Connect gemacht werden (Passwort setzen)
  • 3 Beispiel-Prompts fuer Smoke-Test
  • Token-Verbrauchs-Hinweis: Mono-MCP laedt alle Tools, kann teurer werden — Tipp “spezifisch fragen”

Stolperer (Lessons aus VF-Erstausrollung)

  • Domain-Schreibweise: agenticventures.de ohne Bindestrich, nicht agentic-ventures.de. Hat bei VF Domain-Korrektur und Scalekit-Resource-PATCH gekostet.
  • claude.ai Custom-Connector hat kein Bearer-Header-Feld — nur OAuth-Discovery via PRM. Statisches Bearer ist Anti-Pattern, war frueher im Plan, wurde verworfen.
  • FastMCP v1 vs v2 API-Drift: Sub-MCPs sind v1 (mcp.server.fastmcp.FastMCP), Mono ist v2 (fastmcp package). Direkter Library-Mount bricht. Loesung: stdio-Subprozess + create_proxy() — bleibt unveraendert in main.py, einfach Liste in _SUB_MCP_COMMANDS anpassen.
  • TicketPAY-Tools sind fett: list_tickets(size=5) kann 2 MB JSON liefern → Anthropic Tool-Output-Limit gesprengt. Auto-Compact + count_only=True + fields=[...] sind eingebaut, vor dem Live-Gang testen ob alle Sub-MCPs aehnliche Patterns haben.
  • HSTS-Header brauchen ASGI-Middleware ueber app.http_app(middleware=[...]) + uvicorn-Run-Variant. FastMCP add_middleware ist MCP-protocol-Middleware, nicht HTTP.
  • Railway-Cert-Provisioning kann 5-30 Min dauern nach DNS-Propagation. Im Worst-Case 1-24h. Geduld oder Domain neu anlegen.
  • Strato (rzone.de) als DNS-Hoster funktioniert sauber, kein CAA-Problem. Andere deutsche Hoster ggf. CAA-Record pruefen ob Let’s Encrypt erlaubt ist.
  • PUBLIC_BASE_URL muss exakt der Domain entsprechen die im Scalekit-Resource-URI hinterlegt ist und die im claude.ai-Connector eingetragen wird. Sonst Audience-Mismatch in JWT.
  • Scalekit-Resource ist environment-weit, nicht org-spezifisch — Org “Kunde X” anzulegen ist nice fuer User-Grouping aber nicht zwingend. User in der Org koennen den Connector nutzen ohne Resource-Mapping.

Anti-Patterns

  • URL-Path-Token als Bearer-Replacement → Token landet in Cloudflare/Railway-Logs, Browser-History. Nicht.
  • Eigenbau-OAuth → Crypto-Risiko, lieber Scalekit/WorkOS/Auth0 nehmen.
  • Sub-MCPs modifizieren fuer den Cloud-Use-Case → kapselt schlecht. Stattdessen Proxy-Pattern.
  • Secrets im Bash-Echo oder im Chat → wenn Marvin per Signal Token schickt, NICHT in Bash-output rendern; via stdin pipen.
  • Cloudflare-Account davorschalten wenn Marvin keinen hat → Plan-§3-Layer-1 sieht das vor, aber pragmatisch reicht Railway-internes Cloudflare. Eigene Cloudflare-Zone als Phase-2-Erweiterung wenn echter WAF-Bedarf.

Roadmap-Hinweise

Wenn Kunde wachst (Multi-User, Pro-User-Permissions): Phase-6-Plan im VF-Plan §14 (alter Pfad ~/source/agent-agentur/runs/2026-05-02-vf-mcp-hosting-plan/plan.md). Erfordert Delegated-Auth-Umbau in mcp-m365 + Tool-Layer-Permissions in mcp-ticketpay + Identity-Mapping. ~1-1.5 Wochen Mehraufwand.

  • mcp-vf-hosted — vollstaendiges Cookbook + Architektur (Source of Truth)
  • claude-custom-connector — Constraints des UI
  • SKILL — wenn vorher noch ein neuer Sub-MCP gebaut werden muss
  • mcp-vf-hosted — Repo-Template
  • VF-Plan + Threat-Model + Pen-Test-Checkliste: ~/source/agent-agentur/runs/2026-05-02-vf-mcp-hosting-plan/plan.md (noch nicht migriert)
  • zugriffsmodell — Multi-User-Zugriffsmodell (Phase 6)