{
"tool_response": [
{
"type": "text",
"text": "{\n \"success\": true,\n \"doc\": {\n \"id\": 156,\n \"parent_id\": null,\n \"slug\": \"mcp-server-refactoring-plan\",\n \"path\": \"\/mcp-server-refactoring-plan\",\n \"title\": \"MCP Server Refactoring Plan\",\n \"description\": \"Vollständiger Refactoring-Plan für alle 5 MCP-Server nach DRY, SRP, SOLID, Clean Architecture\",\n \"content\": \"# MCP Server Refactoring Plan\\n\\n**Version:** 1.0 \\n**Erstellt:** 2025-12-28 \\n**Status:** Zur Supervision \\n**Task:** #507\\n\\n---\\n\\n## 1. Executive Summary\\n\\n### Ist-Zustand\\n- **5 MCP-Server**: mcp-db, mcp-tasks, mcp-contracts, mcp-docs, mcp-code\\n- **91 Python-Dateien** (ohne venv)\\n- **9.248 LOC** gesamt\\n- **Signifikante Code-Duplikation** (~25% redundanter Code)\\n- **Inkonsistente Patterns** zwischen Servern\\n\\n### Ziel\\nKonsolidierung zu einer modularen, wartbaren Architektur unter Einhaltung von:\\n- **DRY** (Don't Repeat Yourself)\\n- **SRP** (Single Responsibility Principle)\\n- **SOLID** Principles\\n- **Clean Architecture**\\n- **KISS** (Keep It Simple, Stupid)\\n- **YAGNI** (You Aren't Gonna Need It)\\n\\n### Erwartete Verbesserungen\\n- **~35% weniger Code** durch Elimination von Duplikaten\\n- **Einheitliche Patterns** für alle Server\\n- **Verbesserte Wartbarkeit** durch Modularisierung\\n- **Schnellere Feature-Entwicklung** durch shared Components\\n\\n---\\n\\n## 2. Analyse der Code-Duplikation\\n\\n### 2.1 Kritische Duplikate (Sofort beheben)\\n\\n#### db_connection.py (4 Dateien, ~240 LOC dupliziert)\\n\\n| Server | Zeilen | Bibliothek | Methoden |\\n|--------|--------|------------|----------|\\n| mcp-db | 59 | mysql.connector + pooling | get_pool(), get_connection(db) |\\n| mcp-tasks | 62 | pymysql | get_connection(), get_log_connection() |\\n| mcp-contracts | 60 | pymysql | get_connection(), get_log_connection() |\\n| mcp-docs | 60 | pymysql | get_connection(), get_log_connection() |\\n\\n**Problem:** 3 von 4 Dateien sind nahezu identisch (mcp-tasks, mcp-contracts, mcp-docs).\\n\\n**Lösung:** Zentralisieren in `shared\/infrastructure\/db_connection.py`\\n\\n```python\\n# shared\/infrastructure\/db_connection.py\\nclass DatabaseConnection:\\n \\\"\\\"\\\"Unified DB Connection Manager\\\"\\\"\\\"\\n \\n @classmethod\\n @contextmanager\\n def get_connection(cls, config: \\\"ServerConfig\\\") -> Generator[Connection, None, None]:\\n \\\"\\\"\\\"Standard connection with transaction handling\\\"\\\"\\\"\\n \\n @classmethod\\n @contextmanager \\n def get_log_connection(cls, config: \\\"ServerConfig\\\") -> Generator[Connection, None, None]:\\n \\\"\\\"\\\"Logging connection (autocommit)\\\"\\\"\\\"\\n```\\n\\n#### protokoll_logger.py (4 Dateien, ~240 LOC dupliziert)\\n\\n| Server | Zeilen | Unterschied |\\n|--------|--------|-------------|\\n| mcp-db | 60 | Eigenes Pooling, LogEntry aus domain |\\n| mcp-tasks | 62 | Extra: task_id Handling |\\n| mcp-contracts | 60 | Standard Pattern |\\n| mcp-docs | 59 | Standard Pattern |\\n\\n**Problem:** mcp-contracts und mcp-docs sind identisch bis auf Log-Message.\\n\\n**Lösung:** Zentralisieren in `shared\/infrastructure\/protokoll_logger.py`\\n\\n```python\\n# shared\/infrastructure\/protokoll_logger.py\\nclass ProtokollLogger:\\n def __init__(self, client_name: str):\\n self.client_name = client_name # z.B. \\\"MCP-Tasks\\\"\\n \\n def log(self, entry: LogEntry) -> None:\\n \\\"\\\"\\\"Unified logging with optional context fields\\\"\\\"\\\"\\n```\\n\\n#### config.py (5 Dateien, ~300 LOC mit Overlap)\\n\\n**Gemeinsame Felder in allen Servern:**\\n- DB_HOST, DB_PORT, DB_USER, DB_PASSWORD\\n- LOG_DB_HOST, LOG_DB_NAME, LOG_DB_USER, LOG_DB_PASSWORD\\n\\n**Lösung:** Base Config in shared\/\\n\\n```python\\n# shared\/config_base.py\\nclass BaseConfig:\\n \\\"\\\"\\\"Gemeinsame Konfiguration für alle MCP-Server\\\"\\\"\\\"\\n DB_HOST: str = os.getenv(\\\"DB_HOST\\\", \\\"localhost\\\")\\n DB_PORT: int = int(os.getenv(\\\"DB_PORT\\\", \\\"3306\\\"))\\n # ... alle gemeinsamen Felder\\n\\n# mcp-tasks\/config.py\\nfrom shared.config_base import BaseConfig\\n\\nclass Config(BaseConfig):\\n \\\"\\\"\\\"Task-spezifische Konfiguration\\\"\\\"\\\"\\n OLLAMA_HOST: str = ...\\n VALID_STATUSES: List[str] = ...\\n```\\n\\n### 2.2 Server-Struktur Duplikation\\n\\n#### server.py (5 Dateien, ~250 LOC)\\n\\nAlle Server folgen dem gleichen Pattern:\\n1. Logging Setup\\n2. dotenv laden\\n3. FastMCP initialisieren\\n4. Tools importieren\\n5. Tools registrieren\\n6. main() mit mcp.run()\\n\\n**Lösung:** Factory Pattern\\n\\n```python\\n# shared\/server_factory.py\\ndef create_mcp_server(\\n name: str,\\n instructions: str,\\n tool_registrars: List[Callable[[FastMCP], None]]\\n) -> FastMCP:\\n \\\"\\\"\\\"Creates configured MCP server with standard setup\\\"\\\"\\\"\\n \\n # Unified logging setup\\n logging.basicConfig(...)\\n \\n # Load environment\\n load_dotenv(Path(__file__).parent \/ \\\".env\\\")\\n \\n # Create server\\n mcp = FastMCP(name, instructions=instructions)\\n \\n # Register tools\\n for registrar in tool_registrars:\\n registrar(mcp)\\n \\n return mcp\\n```\\n\\n---\\n\\n## 3. SRP-Verletzungen\\n\\n### 3.1 ContractValidator (409 Zeilen) - KRITISCH\\n\\n**Aktuelle Verantwortlichkeiten:**\\n1. Pfad-Auflösung aus Scope\\n2. Glob-Pattern Matching\\n3. Datei-Lesen\\n4. Regel-Parsing\\n5. Pattern-Validierung (forbidden\/required)\\n6. Line-Count Check\\n7. Dependency Check\\n8. Outcome Determination\\n\\n**Refactoring-Vorschlag:**\\n\\n```\\nvalidators\/\\n├── contract_validator.py # Orchestrierung (< 100 Zeilen)\\n├── scope_resolver.py # Pfad-Auflösung aus YAML\\n├── pattern_matcher.py # Glob\/Regex Matching\\n├── rules\/\\n│ ├── base_rule.py # Abstract Rule\\n│ ├── line_count_rule.py\\n│ ├── forbidden_pattern_rule.py\\n│ ├── required_pattern_rule.py\\n│ └── dependency_rule.py\\n└── result_builder.py # ContractValidationResult erstellen\\n```\\n\\n### 3.2 Repository-Klassen (331-393 Zeilen)\\n\\n**TaskRepository Verantwortlichkeiten:**\\n1. Task CRUD\\n2. Assignment CRUD\\n3. Result CRUD\\n4. Statistics\\n\\n**Refactoring-Vorschlag:**\\n\\n```\\nrepositories\/\\n├── task_repository.py # Nur Task CRUD (< 150 Zeilen)\\n├── assignment_repository.py # Assignment CRUD\\n├── result_repository.py # Result CRUD\\n└── statistics_repository.py # Statistics Queries\\n```\\n\\n### 3.3 Tool-Dateien (400+ Zeilen)\\n\\n**contract_tools.py (406 Zeilen)** - Bereits gut strukturiert mit Helper-Klassen\\n\\n**Empfehlung:** Behalten, da die Aufteilung in contract_tools\/ bereits erfolgt ist.\\n\\n---\\n\\n## 4. Inkonsistenzen\\n\\n### 4.1 Datenbank-Bibliotheken\\n\\n| Server | Bibliothek | Problem |\\n|--------|------------|---------|\\n| mcp-db | mysql.connector | Anderes Cursor-Handling, kein DictCursor default |\\n| mcp-tasks | pymysql | Standard Pattern |\\n| mcp-contracts | pymysql | Standard Pattern |\\n| mcp-docs | pymysql | Standard Pattern |\\n| mcp-code | Direktes mysql.connector | Kein Context Manager |\\n\\n**Empfehlung:** \\n- **Standardisieren auf pymysql** (4 von 5 Servern nutzen es bereits)\\n- mcp-db auf pymysql migrieren (Breaking Change minimieren durch Wrapper)\\n\\n### 4.2 Singleton Patterns\\n\\n| Server | Pattern |\\n|--------|---------|\\n| mcp-tasks | `_logger_instance` + `get_logger()` |\\n| mcp-contracts | `_logger_instance` + `get_logger()` |\\n| mcp-docs | `_repository_instance` + `get_repository()` |\\n| mcp-db | Keine Singletons |\\n| mcp-code | Keine Singletons |\\n\\n**Empfehlung:** Einheitliches Pattern etablieren\\n\\n```python\\n# shared\/patterns.py\\nfrom functools import lru_cache\\n\\n@lru_cache(maxsize=1)\\ndef get_logger(client_name: str) -> ProtokollLogger:\\n return ProtokollLogger(client_name)\\n```\\n\\n### 4.3 Hardcoded Pfade\\n\\n**Problem:** Überall `sys.path.insert(0, \\\"\/opt\/mcp-servers\/...\\\")`\\n\\n**Lösung:** Relative Imports + pyproject.toml für Package-Struktur\\n\\n```toml\\n# \/var\/www\/mcp-servers\/pyproject.toml\\n[project]\\nname = \\\"mcp-servers\\\"\\npackages = [\\\"shared\\\", \\\"mcp_db\\\", \\\"mcp_tasks\\\", \\\"mcp_contracts\\\", \\\"mcp_docs\\\", \\\"mcp_code\\\"]\\n```\\n\\n---\\n\\n## 5. Ziel-Architektur\\n\\n### 5.1 Verzeichnisstruktur\\n\\n```\\n\/var\/www\/mcp-servers\/\\n├── shared\/ # Gemeinsame Komponenten\\n│ ├── __init__.py\\n│ ├── config_base.py # BaseConfig für alle Server\\n│ ├── constants.py # ✓ Existiert bereits\\n│ ├── server_factory.py # Server Creation Factory\\n│ ├── infrastructure\/\\n│ │ ├── __init__.py\\n│ │ ├── db_connection.py # Unified DB Connection\\n│ │ └── protokoll_logger.py # Unified Logger\\n│ ├── domain\/\\n│ │ ├── __init__.py\\n│ │ └── log_entry.py # Shared LogEntry Dataclass\\n│ └── patterns\/\\n│ ├── __init__.py\\n│ ├── repository_base.py # Base Repository Pattern\\n│ └── singleton.py # Singleton Utilities\\n│\\n├── mcp-db\/ # Bestehendes Layout\\n│ ├── server.py # Nutzt shared\/server_factory\\n│ ├── config.py # Erbt von shared\/config_base\\n│ ├── tools\/ # Unverändert\\n│ └── validators\/ # Unverändert\\n│\\n├── mcp-tasks\/\\n│ ├── server.py\\n│ ├── config.py\\n│ ├── domain\/ # Unverändert\\n│ ├── infrastructure\/\\n│ │ ├── __init__.py\\n│ │ ├── task_repository.py # Nutzt shared\/db_connection\\n│ │ └── [protokoll_logger.py] # ENTFERNT - nutzt shared\/\\n│ └── tools\/\\n│\\n├── mcp-contracts\/\\n│ ├── server.py\\n│ ├── config.py\\n│ ├── domain\/\\n│ ├── infrastructure\/\\n│ │ ├── contract_repository.py\\n│ │ └── [protokoll_logger.py] # ENTFERNT\\n│ ├── validators\/\\n│ │ ├── contract_validator.py # Refactored (< 100 Zeilen)\\n│ │ ├── scope_resolver.py # NEU\\n│ │ ├── pattern_matcher.py # NEU\\n│ │ └── rules\/ # NEU\\n│ └── tools\/\\n│\\n├── mcp-docs\/\\n│ └── ...\\n│\\n└── mcp-code\/\\n └── ...\\n```\\n\\n### 5.2 Abhängigkeiten (Clean Architecture)\\n\\n```\\n┌─────────────────────────────────────────────────────────┐\\n│ SHARED │\\n│ ┌───────────────────────────────────────────────────... [TRUNCATED-7ba37dac0f7584a6]"
}
]
}