MCP-Hosting-Pipeline auf AWS

Vision

Wiederverwendbare Pipeline „Spec → Hosted MCP auf AWS” — am gsuite-Beispiel gebaut, parallel als Pattern extrahiert. Endzustand: Marvin sagt „Bau MCP für Software X”, schrittweise Pipeline läuft mit Decision-Points, 2-3 Tage später ist hosted MCP auf AWS produktiv.

Stack-Entscheidungen (final, NICHT mehr diskutieren)

SchichtWahlWarum
ComputeECS Express Mode in eu-central-1App Runner ist seit April 2026 closed for new customers. Express Mode = Single-CLI-Deploy auf Fargate-Underbau
Mono-MCP-FrameworkFastMCP v2 (Prefect’s fastmcp)bewährt in mcp-vf-hosted, ScalekitProvider offiziell
Edge-AuthScalekit (EU-Region, bestehender Account)bereits produktiv für VF-MCP, Migrations-Aufwand niedrig
Token-Storage (Phase 2)DynamoDB + Customer-Managed-KMS-Key + Client-Side-Encryption (AWS Encryption SDK)Pattern: ABAC-Tag aws:PrincipalTag/TenantId, ein KMS-Key für alle Tenants. Quelle: AWS Security Blog
AWS-Accountav-production (425924867359)Per _index der vorgesehene Workload-Account
Domaingmail.agenticventures.deDNS via Strato, Cloudflare davor (TLS, WAF)
Container-RegistryECR im av-production-AccountEU-Region, IAM-integriert
IaCAWS CDK (TypeScript)bessere DX als Terraform für ECS-Setups, AWS-native
Phase 3 OAuth-StrategieComposio/Pipedream-Hybrid (verified Google-App von dort), NICHT Self-Verificationspart 5-15k$/Jahr Audit + 6 Wochen Verification-Wartezeit

Was schon existiert (NICHT doppelt bauen)

  • mcp-vf-hosted~/source/mcps/mcp-vf-hosted/ — Template-Basis. Kopieren, Sub-MCP-Liste tauschen
  • mcp-gsuite~/source/mcps/mcp-gsuite/ — der Sub-MCP der gehosted wird (Marvin’s Fork mit Bulk/Unsubscribe/YouTube)
  • mcp-eigenbau — Skill für lokalen Sub-MCP-Bau
  • mcp-cloud-bereitstellung — Skill für Mono-MCP-Hosting auf Railway (wird Phase 4 um AWS-Variante erweitert)
  • _index — AWS Org + Accounts dokumentiert
  • OAuth-Tokens lokal: ~/.config/mcp-gsuite/.oauth2.{hello,marvinkuehlmann}@*.json
  • Anthropic-Skill mcp-builder (Plugin-Cache) — Tool-Design-Patterns als Referenz
  • Compound-Engineering-Skill agent-native-architecture — Design-Prinzipien (Tools = Primitives, CRUD-Vollständigkeit)

Phasen + Steps mit Status

Phase 1A: gsuite Single-User auf AWS (für Marvin allein, Pattern-Etablierung)

Ziel: gsuite-MCP läuft hosted in av-production, Marvin erreicht ihn von claude.ai Pro / iPhone. Erstanwendung des ECS-Express-Patterns — Lessons-Learned wandern in mcp-hosting-aws-ecs-express.

StepWasAktive BauzeitStatus
1A.1Repo mcp-gsuite-hosted aus mcp-vf-hosted-Pattern, FastMCP+ScalekitProvider, Dockerfile (Multi-Stage, Non-Root, Healthcheck)60-90 Min
1A.2CDK-Stack: ECS Express Mode (AWS-managed ALB) + ECR + IAM (Exec/Infra/Task) + Secrets-Manager60-90 Min
1A.3Lokal Container bauen (linux/amd64) + Smoke-Test /health + Boot-Logs verifizieren30 Min
1A.4Deploy in av-production via SSO (Marvin: aws sso login --profile av-prod), Health-URL prüfen60 Min + 5-30 Min DNS/Cert-Wartezeit
1A.5Cloudflare-DNS auf gmail.agenticventures.de (Marvin in Strato + Cloudflare-UI)15 Min Marvin + 5-15 Min Wartezeit
1A.6Scalekit-Resource konfigurieren (Resource Identifier = exakt https://gmail.agenticventures.de/mcp) + claude.ai Custom-Connector einrichten + Smoke-Test mit 3 Prompts30 Min Marvin

Wall-Clock: 1-2 Tage (bottleneck: Marvin-Reviews + DNS/TLS-Wartezeiten)

Phase 1B: VF-Migration auf AWS (papierkram + ticketpay, M365 deferred)

Ziel: Bestehender Mono-MCP mcp-vf-hosted (heute auf Railway, mcp-vf-hosted) wandert nach av-production. Cloudflare-Origin schaltet von Railway auf AWS um, Domain mcp-vf.agenticventures.de bleibt, claude.ai-Connector bei André unverändert. Railway-Instanz bleibt 1-2 Wochen parallel als Rollback-Sicherung. M365 ist bewusst draussen bis Compliance-Review (Mail-Zugriff, Drive-Files, Tenant-Isolation, AVV-Klauseln) abgeschlossen ist — Code im Repo auskommentiert, Re-Enable ist 6-Stellen-Patch.

StepWasAktive BauzeitStatus
1B.1Repo-Trim: mcp-m365-Dependency raus, _SUB_MCP_COMMANDS/_SUB_MCP_ENV/Settings/Dockerfile/.env.example/README anpassen, .dockerignore neu, Tests grün60 Min
1B.2CDK-Stack infra/ analog gsuite-hosted (ECR + Secrets-Manager + 3 IAM-Rollen + ExpressGatewayService), ENV-Vars für Scalekit + Sub-MCP-Tokens als secrets:-Mapping60-90 Min✅ deprecated (Pivot zu Fargate-Tunnel, siehe 1B.8)
1B.3Container lokal bauen (linux/amd64) + /health-Smoke gegen lokalen Container30 Min
1B.4Production-Tokens aus Railway holen (Marvin via railway variables) → Secrets Manager (Marvin gibt Wert, Claude pusht via aws CLI) → cdk deploy + ECR-Push + ECS-Force-Deploy → Service ACTIVE, /health 200 auf AWS-Endpoint60 Min + 5-30 Min Wartezeit✅ deprecated (siehe 1B.8)
1B.5Cloudflare-DNS-Origin-Switch von Railway auf <service>.ecs.eu-central-1.on.aws. Blockiert auf Domain-Migration (cloudflare-migration-guide) — Strato-Direct-CNAME geht wegen TLS-Cert-Mismatch nicht. Scalekit-Resource bleibt — Identifier https://mcp-vf.agenticventures.de/mcp ist unverändert15 Min Marvin + Wartezeit❌ aufgegeben (ALB-Custom-Domain-Issue, Pivot zu Tunnel)
1B.6Smoke-Test mit Andrés bestehendem claude.ai-Connector (papierkram + ticketpay-Tools rufen, kurz mit André koordinieren), AWS-Logs auf Tool-Calls beobachten30 Min Marvin + Andre☐ blocked auf 1B.9
1B.7Nach ≥ 24h stabilem AWS-Lauf: Railway-Service stoppen, Backup der Railway-ENVs15 Min Marvin☐ blocked auf 1B.6
1B.8Fargate-Tunnel-Pivot (mcp-hosting-fargate-tunnel): alten McpVfHosted-Stack (ECS Express) loeschen mit DeletionPolicy-Patch fuer Secrets, neuer CDK-Stack (klassisches Fargate + cloudflared-Sidecar + egress-only SG, kein ALB), beide Secrets per fromSecretCompleteArn importieren (Wildcard-Suffix-Bug umgehen), Python-stdlib statt curl im Health-Check (Image hat kein curl). Stack CREATE_COMPLETE, Service ACTIVE 1/1/0, Tunnel 4 Connections registered, Health intern 20060-90 Min✅ 2026-05-11
1B.9DNS-Cutover in Cloudflare: CNAME mcp-vfce6dd7c0-d31c-456c-be8a-8705c079982d.cfargotunnel.com, proxied=true, TTL=Auto. Aktueller Record zeigt noch auf alten ECS-Express-Endpoint (mc-1a56ed08...on.aws) und gibt 530 (Origin DNS Error)5 Min Marvin (UI) oder Claude (wenn CF_API_TOKEN + CF_ZONE_ID exportiert)☐ blocked auf Marvin
1B.10End-to-End Smoke: curl https://mcp-vf.agenticventures.de/health ohne Host-Override → 200 mit submcps_active: [papierkram, ticketpay, m365], cf-ray-Header sichtbar5 Min☐ blocked auf 1B.9

Aktueller Stand 2026-05-11 (Architektur-Pivot durchgezogen): ECS-Express-Cutover-Versuch gescheitert wegen Custom-Domain-Issue (AWS-managed ALB akzeptiert nur eigenen Hostname → 404). Plus: ECS Express unterstuetzt nur 1 primary Container, kein Cloudflare-Tunnel-Sidecar moeglich. Pivot auf klassisches ECS Fargate + Cloudflare-Tunnel-Sidecar erfolgreich deployed (1B.8 ✅). Pattern-File: mcp-hosting-fargate-tunnel. Decision: hosted-mcp-architektur-2026. Tunnel ce6dd7c0-d31c-456c-be8a-8705c079982d mit 4 Connections nach Frankfurt registered. M365 ist wieder aktiv im Stack (3 Sub-MCPs proxied — papierkram + ticketpay + m365). Production-Risiko bleibt 0 — Andre nutzt noch nicht aktiv. Naechster Schritt: 1B.9 DNS-Cutover.

Repo-Stand seit 2026-05-10 (lokal, AWS-Deploy gebuendelt mit Cloudflare-Cutover): Drei Workflow-Prompts in prompts.py registriert (/offene_posten, /event_bilanz(event_id), /monatsabschluss(monat)) — André bekommt Slash-Commands die Sub-MCP-Tools choreografieren. /health erweitert auf Diagnostic-JSON (version + submcps_active + uptime). Test-Suite 27/27 grün (5 neue für Prompts, 3 neue fuer Health). Container lokal gebaut + gesmoked. ECR-Push + ECS-Force-Deploy faellt zusammen mit Cloudflare-Cutover an, damit nur ein Deploy-Event statt zwei.

Wall-Clock: 1-2 Tage aktiv + 1-2 Wochen Parallel-Lauf bevor Railway abgeschaltet wird

Compliance-Folge-Schritt (separat, nicht hier): M365 Re-Enable — eigenes Mini-Projekt mit AVV-Klauseln, Tenant-Isolation-Test, Audit-Plan. Kommt nach VF-Migration stabil + Compliance-Review-OK.

Phase 2: Multi-Tenant-Architektur (DynamoDB Operational + S3-Vault Knowledge)

Ziel: Multi-Tenant-Foundation des Produkt-Bundles (produkt-bundle). Pro Kunde: eigener Vault (S3) fuer Knowledge + eigene DynamoDB-Items fuer Operational, beide KMS-encrypted und ABAC-isoliert. Andre (oder beliebiger User) klickt „Connect Gmail” → autorisiert mit seinem Gmail → sieht seine Mails. Strikte User-Isolation. Architektur: markdown-und-db-trennung.

StepWasAktive BauzeitStatus
2.1DynamoDB-Table gsuite-user-tokens (PK=subject, KMS-Encryption, ABAC-Tag) via CDK60 Min
2.2OAuth-Consent-Endpoint /auth/google/callback im Container, Refresh-Token-Persist90 Min
2.3Token-Refresh-Logik mit ABAC-IAM (Container kann nur eigene Tenant-Items lesen)90 Min
2.4User-Isolation-Tests: kann ich mit fremdem JWT auf andere Mailboxen? Sollte NEIN60 Min
2.5Andre als Test-User einladen (Marvin koordiniert), Onboarding-Doku30 Min Marvin + Wartezeit
2.6Audit-Log-Layer (CloudWatch Logs strukturiert, pro Tool-Call: subject, tool, timestamp, success)60 Min

Wall-Clock: 2-3 Tage (bottleneck: Andre-Test koordinieren)

Phase 3: Production-Ready für externe Nutzer (Composio-Hybrid)

StepWasStatus
3.1Composio-Account anlegen, Gmail-Toolkit verbinden, eigenen MCP-Endpoint dahinter schalten
3.2Onboarding-Page gmail.agenticventures.de/connect (statisch, Cloudflare Pages)
3.3AVV-Template + Datenschutzerklärung (rechtlich review lassen)
3.4Per-User Rate-Limiting in GuardMiddleware (existiert in vf-hosted, anpassen)
3.5Cost-Alarme: 50€-Schwelle für gsuite-hosted Service in av-production

Wall-Clock: 1-2 Wochen aktiv + AVV-Wartezeiten

Phase 4: Pipeline als Skills (parallel zu Phase 2/3)

StepWasStatus
4.1Templates extrahieren: ~/source/mcps/_templates/single-aws-hosted/ (Dockerfile, CDK-Stack, FastMCP-Skeleton)
4.2Neuer Skill mcp-aws-deploy — nimmt lokalen MCP, deployed nach AWS
4.3Update mcp-cloud-bereitstellung mit AWS-Variante (statt nur Railway)
4.4Master-Skill mcp-pipeline der orchestriert (Spec → Local → Container → AWS → Auth → Doku)
4.5Test mit zweitem MCP-Bedarf — messen ob es wirklich 2-3 Tage statt 5-7 ist

Wall-Clock: 2-3 Tage (parallel)

Decision-Points (wo Marvin im Loop bleibt)

PunktWas Marvin entscheidetWann
Nach 1A.1gsuite-Repo-Skeleton OK?nach 60-90 Min Bau
Nach 1A.2CDK-Plan OK? Welche Resource-Sizes?nach Skeleton
Nach 1A.3Smoke-Test grün? Tools liefern plausibel?nach lokalem Container
Vor 1A.4SSO-Login aws sso login --profile av-prod ausführenbevor Deploy
Vor 1A.5DNS-Eintrag in Strato + Cloudflare-Routing setzennach AWS-Deploy
Vor 1A.6claude.ai Custom-Connector einrichtennach DNS-Setup
Nach 1B.1Repo-Trim sauber? Tests grün?nach Repo-Edits
Nach 1B.2CDK-Stack OK? Sizing identisch zu gsuite (1 vCPU/2 GB)?nach Skeleton
Nach 1B.3Container baut + /health lokal grün?nach Container-Build
Vor 1B.4Railway-Production-Tokens exportieren (railway variables --kv) — Marvin gibt Werte, Claude pusht ins Secrets Managerbevor Deploy
Vor 1B.5DNS-Origin-Switch im Cloudflare-UI — Marvin klickt mit Anleitungnach AWS-Deploy stabil
Vor 1B.6André kurz pingen für Connector-Smoke-Testnach DNS-Switch
Vor 1B.7≥ 24h grüne AWS-Logs ohne Tool-Errors? Dann erst Railway abschaltennach Smoke
Nach 2.4User-Isolation-Tests grün? KEIN Datenleak möglich?bevor 2.5
Nach 2.5Andre als Test-User OK mit Setup? Sein Gmail erfolgreich verbunden?nach Test-Run
Phase 3 StartComposio-Hybrid bestätigt vs Self-Verification?vor Phase 3
M365-Re-EnableCompliance-Review (Mail/Drive/Tenant/AVV) abgeschlossen?separates Mini-Projekt nach VF-Stabilität

Was Claude (Agent) NICHT kann

  • AWS Console-Klicks (nur via CLI)
  • OAuth-Browser-Consent-Flow durchklicken
  • DNS-Records in Strato setzen
  • claude.ai Custom-Connector einrichten (Marvins Account)
  • Composio/Scalekit Production-Account anlegen
  • Echte User-Tests mit Andre koordinieren

→ Bei diesen Punkten stoppt Claude und gibt Marvin konkrete Anleitung mit Deep-Links.

Risiken & Mitigationen

RisikoMitigation
ECS Express Mode neu in 2026 — Doku-Lücken möglichFallback zu klassischem ECS Fargate wenn Express-Mode-Quirks auftreten (gleicher Underbau, mehr Boilerplate)
Token-Isolation-Bug → Datenleakstrikte Test-Battery in Phase 2.4, kein Go-Live für Externe ohne grüne Tests
ECS Cold-Starts → langsame erste Tool-CallsMin-Tasks=1 (~5-10$/Monat), Cost-Alarm bei 50€
Pattern-Extraktion fällt unter den TischEigene Sub-Tasks in Phase 4, nicht „mach ich später”
AWS-CDK-Bootstrap noch nicht in av-production gemachtStep 1.4 enthält cdk bootstrap falls noch nötig

Cross-Refs

Verlauf

  • 2026-05-09: Projekt angelegt. Plan finalisiert nach Recherche (App Runner ist tot → ECS Express Mode; Restricted-Scope-Verification ist 5-15k$/Jahr → Composio-Hybrid für Phase 3). Stack-Entscheidungen final.
  • 2026-05-10 (Hebel 2/3/4 — UX/Diagnostic-Polish): Drei Workflow-Prompts (offene_posten, event_bilanz, monatsabschluss) in mcp-vf-hosted/src/mcp_vf_hosted/prompts.py via @mcp.prompt-Decorator registriert. Erweiterter /health mit version/submcps_active/uptime_seconds. Sub-MCP-Tool-Descriptions geprueft — schon deutsch und prägnant, keine Aktion noetig (= Hebel 3 stiller Skip). Tests +8 (27/27 grün). Container lokal gesmoked. AWS-Deploy mit Cloudflare-Cutover gebuendelt.
  • 2026-05-11 (Fargate-Tunnel-Pivot 1B.8 durchgezogen): Alter McpVfHosted-Stack abgerissen (vorher DeletionPolicy DeleteRetain auf mcp-vf-hosted/upstream-tokens gepatcht via update-stack — sonst waeren die 6 Sub-MCP-Tokens beim Delete weg gewesen). Neuer Stack komplett umgeschrieben (mcp-vf-hosted-stack.ts.ecs-express-backup als Backup behalten): FargateService + FargateTaskDefinition mit 2 Containern (vf-mono + cloudflared/cloudflared:latest-Sidecar), egress-only SG, kein ALB, Cluster default und Default-VPC importiert. 3 Versuche bis CREATE_COMPLETE: (1) fromSecretNameV2 generiert Wildcard-ARN -?????? in IAM-Policy, aber ECS ValueFrom ruft Name-only-ARN → AccessDenied. Fix: fromSecretCompleteArn mit echtem ARN inkl. -AHEi6G/-q5MEkS. (2) Health-Check curl -f localhost:8080/health schlaegt fehl weil python:3.12-slim kein curl hat. Fix: python -c "import urllib.request,sys; sys.exit(0 if urllib.request.urlopen(\"http://localhost:8080/health\", timeout=3).status==200 else 1)". (3) Deploy CREATE_COMPLETE in 149s, Service ACTIVE 1/1/0, Tunnel registered (4 QUIC-Connections nach fra16/03/20/08), interner Health-Check alle 30s 200. M365 wieder aktiv mitsamt papierkram + ticketpay — alle 3 Sub-MCPs proxied. Offen: 1B.9 DNS-Cutover — Marvin muss CNAME mcp-vf in CF auf ce6dd7c0...cfargotunnel.com aendern (UI oder API mit CF_API_TOKEN/CF_ZONE_ID).
  • 2026-05-10: Phase 1 in 1A (gsuite, Pattern-Etablierung, 1A.1-1A.3 ✅) und 1B (VF-Migration, papierkram + ticketpay, M365 deferred) gesplittet. 1B.1 ✅ — mcp-vf-hosted repo getrimmt: M365-Dependency + Code-Pfade in-place auskommentiert mit konsistentem Re-Enable-Marker, boto3 für Bootstrap-Optionalität dazu, .dockerignore neu gegen .env-Leak, README auf AWS-ECS-Express umgeschrieben, 19/19 Tests grün. 1B.2 ✅ — CDK-Stack infra/ analog gsuite-hosted angelegt, Sub-MCP-Tokens via ECS-secrets:-Mapping (<arn>:KEY::-Syntax) statt File-Bootstrap (kein entrypoint.sh nötig). cdk diff grün gegen av-production: 7 Resources + 1 IAM-Policy, Trust-Principals korrekt (ExecRole/TaskRole = ecs-tasks, InfraRole = ecs.amazonaws.com). 1B.3 ✅ — docker buildx build --platform linux/amd64 durch (430 MB Build-Context, Sub-MCP-venvs ziehen mit — Tweak vor Push siehe Status). Container startet, beide Sub-MCP-Subprozesse submcp_proxied (papierkram + ticketpay, kein m365), /health → 200 {"ok":true}. Architektur-Doc neu unter ~/source/mcps/mcp-vf-hosted/docs/architecture.md mit Mermaid-Diagrammen für Trust-Boundaries, Sub-MCP-Komposition und Tool-Call-Sequenz. 1B.4 ✅ — Production-Tokens via railway variables --service vf-mcp --kv lokal gezogen, 3 Sub-MCP-Tokens (PAPIERKRAM_TOKEN/SUBDOMAIN, TICKETPAY_API_KEY) als JSON ins Secrets Manager mcp-vf-hosted/upstream-tokens gepusht (Python-Pipe, nie in Bash-Stdout). 2 Scalekit-Werte hardcoded im Stack (nicht-secret). cdk deploy brauchte 3 Anläufe (5 Lessons-Learned ins Pattern-File geschrieben): IAM-Description darf nur ASCII enthalten (Em-Dash failed), CPU/Memory braucht Fargate-MiB-Format '1024'/'2048' nicht '1'/'2', retained ECR-Repo nach Failed-Stack-Rollback via Repository.fromRepositoryName umgehen. Stack CREATE_COMPLETE nach 380s, ServiceEndpoint mc-1a56ed08537b4f9fae11028fe698af47.ecs.eu-central-1.on.aws, /health HTTP 200 {"ok":true} mit Security-Headern. Railway-Token-File geshredded.