MCP-DB Architektur

Aufbau und Struktur des MCP-DB Servers nach OOP, SRP, KISS, YAGNI Prinzipien.

Verzeichnisstruktur

/opt/mcp-servers/mcp-db/
├── server.py              # MCP Server Entrypoint
├── config.py              # Zentrale Konfiguration
├── .env                   # Credentials (chmod 600)
├── .env.example           # Template
├── requirements.txt       # Dependencies
│
├── domain/                # Contracts (Interfaces)
│   ├── __init__.py
│   ├── query_contract.py  # QueryRequest, QueryResponse
│   └── log_contract.py    # LogEntry
│
├── validators/            # SRP: Separate Validierung
│   ├── __init__.py
│   └── query_validator.py # SQL Validierung
│
├── infrastructure/        # Implementierungen
│   ├── __init__.py
│   ├── db_connection.py   # MariaDB Connection Pool
│   └── protokoll_logger.py # Logging nach ki_protokoll
│
└── tools/                 # MCP Tools
    ├── __init__.py
    ├── select_tool.py     # db_select
    ├── schema_tool.py     # db_schema
    └── stats_tool.py      # db_stats

Komponenten-Diagramm

┌─────────────────────────────────────────────────────────────┐
│                     Claude Code                              │
│                         │                                    │
│                    MCP Protocol                              │
│                         │                                    │
│                         ▼                                    │
│  ┌──────────────────────────────────────────────────────┐   │
│  │                   server.py                           │   │
│  │                 (Entrypoint)                          │   │
│  └──────────────────────┬───────────────────────────────┘   │
│                         │                                    │
│           ┌─────────────┼─────────────┐                      │
│           ▼             ▼             ▼                      │
│  ┌────────────┐ ┌────────────┐ ┌────────────┐               │
│  │ db_select  │ │ db_schema  │ │ db_stats   │               │
│  │   Tool     │ │   Tool     │ │   Tool     │               │
│  └─────┬──────┘ └─────┬──────┘ └─────┬──────┘               │
│        │              │              │                       │
│        └──────────────┼──────────────┘                       │
│                       ▼                                      │
│  ┌──────────────────────────────────────────────────────┐   │
│  │              QueryValidator                           │   │
│  │   (Blocklist, Allowlist, Limits)                     │   │
│  └──────────────────────┬───────────────────────────────┘   │
│                         │                                    │
│           ┌─────────────┴─────────────┐                      │
│           ▼                           ▼                      │
│  ┌────────────────────┐    ┌────────────────────┐           │
│  │  DatabaseConnection │    │  ProtokollLogger   │           │
│  │   (Connection Pool) │    │   (mcp_log)        │           │
│  └─────────┬──────────┘    └─────────┬──────────┘           │
│            │                         │                       │
│            ▼                         ▼                       │
│  ┌──────────────┐           ┌──────────────┐                │
│  │   MariaDB    │           │ ki_protokoll │                │
│  │ (ki_system)  │           │  (mcp_log)   │                │
│  └──────────────┘           └──────────────┘                │
└─────────────────────────────────────────────────────────────┘

Design-Prinzipien

PrinzipUmsetzung
SRP Jede Klasse hat eine Verantwortung: Validator validiert, Executor führt aus, Logger loggt
OOP Klassen mit klarer Kapselung, keine globalen Funktionen
KISS Minimale Komplexität, kein Over-Engineering
YAGNI Nur SELECT implementiert, keine CRUD-Operationen
Immutability QueryRequest ist frozen (unveränderlich)
Fail-Safe Exceptions statt silent failures

Datenfluss

1. Claude Code ruft db_select(query, database, max_rows, params)
2. Tool empfängt Request
3. QueryValidator.validate_query() prüft:
   - SELECT-Only
   - Keyword-Blocklist
   - Database-Allowlist
   - Table-Allowlist
   - Query-Länge
   - Max-Rows
4. Bei Fehler: DENIED Response + Log
5. Bei Erfolg: SelectExecutor.execute()
   - Connection aus Pool
   - SET max_statement_time (MariaDB)
   - cursor.execute(query, params)
   - fetchmany(max_rows)
6. ProtokollLogger.log() schreibt nach mcp_log
7. Response zurück an Claude Code

Verwandte Kapitel