MCP-Server self-hosted.
Multi-Tenant. Field-Whitelist. Audit-Spur.
Architektur-Patterns und Capabilities. Multi-Tenant via
tenant_id,
Field-Whitelist auf DB-Spalten-Ebene für DSGVO,
Approval-State-Machine, Heartbeats als DB-Polling,
anbieter-agnostisches LLM-Routing. Open-Core mit
MCP-Schicht als MIT-Lizenz in Vorbereitung.
Neun Schichten, was sie können.
Konkrete Tool-Wahl behalte ich für mich, was zählt sind die Eigenschaften: Type-Safety End-to-End, anbieter-agnostischer LLM-Layer, Field-Whitelist als Default-Pflicht statt opt-in-Feature.
stdio + HTTP/SSE · OpenAI-/Google-kompatibel Bundle < 200 kB · ~10k req/s pro Core Schema → Query → Response, ein Typecheck Flexible Tool-Configs · gute Concurrency Claude Default · OpenAI / Ollama optional Tool-Registry pro Tenant · Session HttpOnly + SameSite Type-safe Schemas für Beacon, Tools, Config CI < 2 min · EU-Hosting · Rolling-Update GoBD/DSGVO-konform · optional Hash-Chain Drei Layer im offiziellen Protokoll.
Jeder MCP-Server hat drei klare Schichten. Das Modell ruft Werkzeuge auf, liest Daten, nutzt vordefinierte Prompts, alles deterministisch, alles mit Berechtigungen, alles loggbar.
Tool-Layer
Konkrete Werkzeuge die das Modell aufrufen darf, listInvoices, createBooking, queryProducts. Jedes Werkzeug deterministisch, mit JSON-Schema, Rückgabe-Typ und Berechtigungs-Check pro Aufruf.
Resource-Layer
Daten die das Modell lesen darf. Dokumente, DB-Snapshots, API-Responses. Der Server entscheidet was rausgeht, nicht das Modell. Field-Whitelist auf Spalten-Ebene per Default.
Prompt-Layer
Wiederverwendbare Prompts mit Parametern, die im UI angeboten werden. „Kontierung-Vorschlag erstellen", „Kunden-Brief verfassen", „Report Q4". Strukturiert, versioniert, testbar.
Sieben Standard-Tools je MCP-Server.
Default-Tool-Set für jeden MCP-Server. Custom-Tools je
Mandanten-Use-Case oben drauf, werden via
ToolDefinitionBuilder aus
DG-Schema generiert (Auto-Tool-Generation aus Datenmodell).
list_records (scope, filter?) → Record[] Liest Records aus DG-Scope mit Field-Whitelist. ScopeDataLoader prüft tenant_id und Berechtigung pro Spalte.
create_record (scope, data) → Record Schreibt mit Validation (Schema aus DG-Definition). Audit-Log-Entry wird automatisch erzeugt.
update_record (scope, id, patch) → Record Patch nur auf whitelisted Felder. revisionNote in audit_log.data.
invoke_connector (connector, action, params) → Result Generischer Konnektor-Aufruf. Credentials aus connectors.credentialsEncrypted (AES-256-GCM mit per-Tenant-Salt).
request_approval (question, context, amount?) → ApprovalId Pausiert Run, schreibt Approval-Entry. Worker pollt status, setzt Run fort bei approved.
handoff_to_agent (targetEmployee, context) → RunId Live-Konversations-Routing zwischen Agents (OpenAI-Swarm-Pattern). Bernd reicht komplexen Case an Max weiter.
schedule_heartbeat (schedule, contextTemplate) → HeartbeatId Cron-Trigger für 24/7-Agent-Aktivität. Default Polling alle 60 Sek.
Sechs Pattern, in jedem Build umgesetzt.
Pattern-Library aus produktiven MCP-Builds. Adaptiert wo sinnvoll von Paperclip (MIT-Lizenz) und OpenAI Swarm (handoff_to_agent).
Multi-Tenant via tenant_id
tenant_id Foreign-Key auf jeder Business-Tabelle. ScopeDataLoader filtert auf Service-Layer (kein DB Row-Level-Security, zu fragil bei Schema-Migrations). Pattern bewährt in analytics.thconsulting.dev und EDUSyn-Akademie. tenant_users-Junction für N:N (User kann mehrere Tenants administrieren).
Field-Whitelist auf Spalten-Ebene
Pro Scope (= DB-View) eine strErlaubteFelder-Konfiguration. Tools lesen nur was whitelisted ist, schreiben nur was whitelisted ist. Wenn DSGVO-Auskunft kommt: SELECT field, value FROM audit_log WHERE tenant_id=X AND containsPii=true → fertig.
Approval-Lifecycle als State-Machine
pending → approved | rejected | revision_requested | expired. expiresAt für Soft-Expiry (default 48h). Worker re-prüft pending Approvals, setzt Run fort oder marked als expired. State-Diff im audit_log nachvollziehbar.
Heartbeats als DB-Polling
heartbeats-Tabelle mit nextRunAt-Index. Worker-Process pollt jede Minute SELECT * FROM heartbeats WHERE next_run_at <= NOW() AND is_active = true. Triggert runs, setzt nextRunAt = NOW() + INTERVAL. Reicht bis ~10K aktive Heartbeats, danach Migration auf Queue-Backend.
Konnektor-Credentials verschlüsselt
AES-256-GCM mit Master-Key (env) plus per-Tenant-Salt. Verschlüsselte Credentials in connectors.credentialsEncrypted (text). Decrypt nur in Service-Layer für aktive Tool-Calls, niemals im API-Response. Master-Key-Rotation als geplantes Feature.
Anbieter-agnostisches LLM-Routing
LLMProvider-Interface mit Implementierungen für Claude, OpenAI, Ollama. Pro Tenant konfigurierbar. Datenschutz-paranoide Kunden bekommen Ollama-Endpoint mit lokalem Llama 3.3, kein Daten-Egress. costMicroEur pro Run für Cost-Pass-Through.
Container-Cluster mit Auto-TLS.
Default-Deploy-Pattern. Pipeline:
git push →
CI → Container-Registry → SSH-Stack-Deploy → Auto-TLS
via Reverse-Proxy. Migrations als one-shot-Service.
# docker-compose.yaml (Auszug, generalisiert)
services:
mcp-server:
image: registry.kunde.de/mcp-server:${VERSION}
networks: [proxy-net, internal]
environment:
DATABASE_URL: ${DATABASE_URL}
MASTER_ENCRYPTION_KEY: ${MASTER_ENCRYPTION_KEY}
LLM_API_KEY: ${LLM_API_KEY}
deploy:
labels:
- proxy.enable=true
- proxy.host=mcp.kunde.de
- proxy.tls.cert=letsencrypt
- proxy.port=3000
restart_policy:
condition: any
delay: 10s
mcp-worker:
image: registry.kunde.de/mcp-worker:${VERSION}
networks: [internal]
environment:
DATABASE_URL: ${DATABASE_URL}
WORKER_POLL_INTERVAL_MS: 60000
command: # Worker-Process (Heartbeat-Polling)
deploy:
replicas: 1
restart_policy:
condition: any
networks:
proxy-net: { external: true }
internal: { driver: overlay } Code zu lesen statt nur Specs.
Drei produktive Stacks die dem MCP-Pattern folgen. Repos sind privat, aber Pattern erklärbar im Sparring oder per Code-Walkthrough.
CLI mit über 30 Modulen
OAuth-Workaround, AI-Reasoning-Layer, modulare Analyzer-Architektur. Kein MCP-Server, aber gleiche Stack-Patterns.
Privacy-First Beacon-Server
Multi-Tenant via tenant_id, INP-p75-Tracking, Goal/Journey-State-Machine, Container-Deploy.
Webshop + LMS
Live in Production, EU-Hosting, Container-Cluster, CI-Pipeline mit Zero-Downtime.
Tech-Fragen.
Welcher MCP-Transport, stdio oder HTTP?
Wie funktioniert Multi-Tenant-Isolation?
Wie wird der Server deployed?
Welche Konnektoren sind Standard?
Wie funktioniert das Approval-System?
Gibt es Heartbeats / Cron-Trigger?
Welcher LLM-Provider. Anthropic, OpenAI, Ollama?
Open-Source oder proprietär?
Wie passt MCP zu Webanwendung?
Was kostet ein MCP-Build?
Tech-Sparring oder Code-Walkthrough?
30 Min Erstgespräch, kostenlos. Patterns besprechen, Use-Case prüfen, Architektur-Entscheidungen klären. Wenn passt, Code-Walkthrough an einer Reference-Implementierung.
Erstgespräch buchen