Protokoll #23880

ID23880
Zeitstempel2025-12-27 15:29:08.177886
Clientroot
IP
Warning: Undefined array key "request_ip" in /var/www/dev.campus.systemische-tools.de/src/View/protokoll/show.php on line 13

Deprecated: htmlspecialchars(): Passing null to parameter #1 ($string) of type string is deprecated in /var/www/dev.campus.systemische-tools.de/src/View/protokoll/show.php on line 13
Modellclaude-sonnet-4-20250514
Statuscompleted
Tokens2,695 (Input: 0, Output: 0)
Dauer103 ms
Request-Zeit
Warning: Undefined array key "request_timestamp" in /var/www/dev.campus.systemische-tools.de/src/View/protokoll/show.php on line 18
Response-Zeit-

Warning: Undefined array key "error_message" in /var/www/dev.campus.systemische-tools.de/src/View/protokoll/show.php on line 22

Request

{
    "event": "PreToolUse",
    "tool_name": "mcp__mcp-docs__docs_get",
    "tool_input": {
        "id": 141
    }
}

Response

{
    "tool_response": [
        {
            "type": "text",
            "text": "{\n  \"success\": true,\n  \"doc\": {\n    \"id\": 141,\n    \"parent_id\": 92,\n    \"slug\": \"task-completion-guard\",\n    \"path\": \"\/prozesse\/claude-hooks-prozess\/task-completion-guard\",\n    \"title\": \"Task-Completion Guard Hook\",\n    \"description\": \"Pre-Hook zur Validierung von Task-Completion - verhindert tasks_status(completed) ohne vorheriges tasks_result()\",\n    \"content\": \"<h2>Task-Completion Guard Hook<\/h2>\\n\\n<p>Pre-Hook der verhindert, dass Tasks als \\\"completed\\\" markiert werden, ohne dass vorher ein Ergebnis via <code>tasks_result()<\/code> geschrieben wurde.<\/p>\\n\\n<h3>Problem<\/h3>\\n<p>Claude ruft <code>tasks_status(id, \\\"completed\\\")<\/code> auf, ohne vorher <code>tasks_result()<\/code> zu rufen. Dies führt zu 77+ Fehlern pro Woche mit der Meldung:<\/p>\\n<pre><code>Task kann nicht abgeschlossen werden. Fehlend: Ergebnis (tasks_result)<\/code><\/pre>\\n\\n<h3>Lösung<\/h3>\\n<p>Ein PreToolUse-Hook der VOR dem MCP-Call prüft, ob ein Result existiert und bei Fehlen die Aktion blockiert.<\/p>\\n\\n<table>\\n    <tr><th>Datei<\/th><td><code>\/var\/www\/tools\/ki-protokoll\/claude-hook\/task_completion_guard.py<\/code><\/td><\/tr>\\n    <tr><th>Trigger<\/th><td><code>PreToolUse<\/code> mit Matcher <code>mcp__mcp-tasks__tasks_status<\/code><\/td><\/tr>\\n    <tr><th>Exit-Codes<\/th><td>0 = allow, 2 = block<\/td><\/tr>\\n<\/table>\\n\\n<h3>Technische Details<\/h3>\\n\\n<h4>1. Input-Format (stdin)<\/h4>\\n<pre><code>{\\n  \\\"tool_name\\\": \\\"mcp__mcp-tasks__tasks_status\\\",\\n  \\\"tool_input\\\": {\\n    \\\"id\\\": 425,\\n    \\\"status\\\": \\\"completed\\\"\\n  }\\n}<\/code><\/pre>\\n\\n<h4>2. Prüflogik<\/h4>\\n<ol>\\n    <li>Parse JSON von stdin<\/li>\\n    <li>Prüfe: <code>tool_name == \\\"mcp__mcp-tasks__tasks_status\\\"<\/code><\/li>\\n    <li>Prüfe: <code>status == \\\"completed\\\"<\/code><\/li>\\n    <li>Wenn ja: DB-Abfrage <code>SELECT COUNT(*) FROM task_results WHERE task_id = ?<\/code><\/li>\\n    <li>Wenn count == 0: Block mit Exit-Code 2 + stderr-Nachricht<\/li>\\n<\/ol>\\n\\n<h4>3. Block-Nachricht<\/h4>\\n<pre><code>BLOCKIERT: Task kann nicht als 'completed' markiert werden!\\n\\nGRUND: Kein Ergebnis vorhanden (tasks_result fehlt).\\n\\nLÖSUNG: Vor tasks_status(id, \\\"completed\\\") MUSS tasks_result() aufgerufen werden:\\n\\n    tasks_result(\\n        id=TASK_ID,\\n        response=\\\"Zusammenfassung der erledigten Arbeit...\\\",\\n        executor=\\\"claude\\\",\\n        executor_type=\\\"claude\\\"\\n    )\\n\\nErst danach: tasks_status(id, \\\"completed\\\")<\/code><\/pre>\\n\\n<h4>4. Konfiguration in settings.json<\/h4>\\n<pre><code>{\\n  \\\"PreToolUse\\\": [\\n    {\\n      \\\"matcher\\\": \\\"mcp__mcp-tasks__tasks_status\\\",\\n      \\\"hooks\\\": [\\n        {\\n          \\\"type\\\": \\\"command\\\",\\n          \\\"command\\\": \\\"\/var\/www\/tools\/ki-protokoll\/claude-hook\/task_completion_guard.py\\\",\\n          \\\"timeout\\\": 5\\n        }\\n      ]\\n    }\\n  ]\\n}<\/code><\/pre>\\n\\n<h3>Ablauf<\/h3>\\n<pre>\\n┌─────────────────────────────┐\\n│ Claude: tasks_status(       │\\n│   id=425, status=\\\"completed\\\"│\\n│ )                           │\\n└─────────────┬───────────────┘\\n              │\\n              ▼\\n┌─────────────────────────────┐\\n│ PreToolUse Hook auslösen    │\\n│ Matcher: mcp__mcp-tasks__   │\\n│          tasks_status       │\\n└─────────────┬───────────────┘\\n              │\\n              ▼\\n┌─────────────────────────────┐\\n│ task_completion_guard.py    │\\n│ - Parse Input               │\\n│ - Check: status==\\\"completed\\\"│\\n└─────────────┬───────────────┘\\n              │\\n       ┌──────┴──────┐\\n       │             │\\n       ▼             ▼\\n┌─────────────┐ ┌─────────────┐\\n│ status !=   │ │ status ==   │\\n│ \\\"completed\\\" │ │ \\\"completed\\\" │\\n└──────┬──────┘ └──────┬──────┘\\n       │               │\\n       ▼               ▼\\n┌─────────────┐ ┌─────────────────┐\\n│ exit(0)     │ │ DB-Check:       │\\n│ → Allow     │ │ task_results    │\\n└─────────────┘ │ WHERE task_id=? │\\n                └────────┬────────┘\\n                         │\\n                  ┌──────┴──────┐\\n                  │             │\\n                  ▼             ▼\\n           ┌──────────┐  ┌──────────┐\\n           │ count > 0│  │ count = 0│\\n           └────┬─────┘  └────┬─────┘\\n                │             │\\n                ▼             ▼\\n           ┌─────────┐  ┌─────────────┐\\n           │ exit(0) │  │ stderr:     │\\n           │ → Allow │  │ BLOCKIERT   │\\n           └─────────┘  │ exit(2)     │\\n                        │ → Block     │\\n                        └─────────────┘\\n<\/pre>\\n\\n<h3>Implementierungsplan<\/h3>\\n\\n<h4>Schritt 1: Hook-Script erstellen<\/h4>\\n<p>Datei: <code>\/var\/www\/tools\/ki-protokoll\/claude-hook\/task_completion_guard.py<\/code><\/p>\\n<pre><code>#!\/usr\/bin\/env python3\\n\\\"\\\"\\\"\\nTask Completion Guard Hook\\n\\nBlockiert tasks_status(completed) wenn kein Result existiert.\\nErzwingt korrekten Workflow: tasks_result() vor tasks_status(completed).\\n\\nTrigger: PreToolUse (mcp__mcp-tasks__tasks_status)\\n\\\"\\\"\\\"\\n\\nimport json\\nimport sys\\nimport os\\nfrom pathlib import Path\\nfrom dotenv import load_dotenv\\nimport pymysql\\n\\n# Lade Environment aus .env im Hook-Verzeichnis\\nload_dotenv(Path(__file__).parent \/ '.env')\\n\\nDB_CONFIG = {\\n    'host': os.environ.get('CLAUDE_DB_HOST', 'localhost'),\\n    'port': int(os.environ.get('CLAUDE_DB_PORT', '3306')),\\n    'user': os.environ.get('CLAUDE_DB_USER', 'root'),\\n    'password': os.environ.get('CLAUDE_DB_PASSWORD', ''),\\n    'database': 'ki_dev',\\n    'charset': 'utf8mb4'\\n}\\n\\nBLOCK_MESSAGE = \\\"\\\"\\\"BLOCKIERT: Task kann nicht als 'completed' markiert werden!\\n\\nGRUND: Kein Ergebnis vorhanden (tasks_result fehlt).\\n\\nLÖSUNG: Vor tasks_status(id, \\\"completed\\\") MUSS tasks_result() aufgerufen werden:\\n\\n    tasks_result(\\n        id={task_id},\\n        response=\\\"Zusammenfassung der erledigten Arbeit...\\\",\\n        executor=\\\"claude\\\",\\n        executor_type=\\\"claude\\\"\\n    )\\n\\nErst danach: tasks_status({task_id}, \\\"completed\\\")\\\"\\\"\\\"\\n\\n\\ndef check_result_exists(task_id: int) -> bool:\\n    \\\"\\\"\\\"Prüft ob ein Result für den Task existiert.\\\"\\\"\\\"\\n    try:\\n        conn = pymysql.connect(**DB_CONFIG)\\n        cursor = conn.cursor()\\n        cursor.execute(\\n            \\\"SELECT COUNT(*) FROM task_results WHERE task_id = %s\\\",\\n            (task_id,)\\n        )\\n        count = cursor.fetchone()[0]\\n        conn.close()\\n        return count > 0\\n    except Exception as e:\\n        # Bei DB-Fehler durchlassen (fail-open)\\n        print(f\\\"DB-Check fehlgeschlagen: {e}\\\", file=sys.stderr)\\n        return True\\n\\n\\ndef main():\\n    try:\\n        input_data = json.load(sys.stdin)\\n    except json.JSONDecodeError:\\n        sys.exit(0)\\n    \\n    # Nur mcp__mcp-tasks__tasks_status prüfen\\n    tool_name = input_data.get(\\\"tool_name\\\", \\\"\\\")\\n    if tool_name != \\\"mcp__mcp-tasks__tasks_status\\\":\\n        sys.exit(0)\\n    \\n    # Prüfe ob Status auf \\\"completed\\\" gesetzt wird\\n    tool_input = input_data.get(\\\"tool_input\\\", {})\\n    status = tool_input.get(\\\"status\\\", \\\"\\\")\\n    task_id = tool_input.get(\\\"id\\\")\\n    \\n    if status.lower() != \\\"completed\\\":\\n        sys.exit(0)\\n    \\n    if not task_id:\\n        sys.exit(0)\\n    \\n    # Prüfe ob Result existiert\\n    if not check_result_exists(task_id):\\n        print(BLOCK_MESSAGE.format(task_id=task_id), file=sys.stderr)\\n        sys.exit(2)\\n    \\n    sys.exit(0)\\n\\n\\nif __name__ == \\\"__main__\\\":\\n    main()\\n<\/code><\/pre>\\n\\n<h4>Schritt 2: Script ausführbar machen<\/h4>\\n<pre><code>chmod +x \/var\/www\/tools\/ki-protokoll\/claude-hook\/task_completion_guard.py<\/code><\/pre>\\n\\n<h4>Schritt 3: settings.json erweitern<\/h4>\\n<p>Datei: <code>\/root\/.claude\/settings.json<\/code><\/p>\\n<p>Füge folgenden Eintrag in \\\"PreToolUse\\\" Array hinzu:<\/p>\\n<pre><code>{\\n  \\\"matcher\\\": \\\"mcp__mcp-tasks__tasks_status\\\",\\n  \\\"hooks\\\": [\\n    {\\n      \\\"type\\\": \\\"command\\\",\\n      \\\"command\\\": \\\"\/var\/www\/tools\/ki-protokoll\/claude-hook\/task_completion_guard.py\\\",\\n      \\\"timeout\\\": 5\\n    }\\n  ]\\n}<\/code><\/pre>\\n\\n<h4>Schritt 4: Testen<\/h4>\\n<pre><code># Test 1: Task ohne Result → sollte blockiert werden (Exit 2)\\necho '{\\\"tool_name\\\":\\\"mcp__mcp-tasks__tasks_status\\\",\\\"tool_input\\\":{\\\"id\\\":999,\\\"status\\\":\\\"completed\\\"}}' | \\\\\\n  \/var\/www\/tools\/ki-protokoll\/claude-hook\/task_completion_guard.py\\necho \\\"Exit code: $?\\\"\\n\\n# Test 2: Anderer Status → sollte durchgelassen werden (Exit 0)\\necho '{\\\"tool_name\\\":\\\"mcp__mcp-tasks__tasks_status\\\",\\\"tool_input\\\":{\\\"id\\\":999,\\\"status\\\":\\\"in_progress\\\"}}' | \\\\\\n  \/var\/www\/tools\/ki-protokoll\/claude-hook\/task_completion_guard.py\\necho \\\"Exit code: $?\\\"\\n\\n# Test 3: Anderes Tool → sollte durchgelassen werden (Exit 0)\\necho '{\\\"tool_name\\\":\\\"Bash\\\",\\\"tool_input\\\":{\\\"command\\\":\\\"ls\\\"}}' | \\\\\\n  \/var\/www\/tools\/ki-protokoll\/claude-hook\/task_completion_guard.py\\necho \\\"Exit code: $?\\\"\\n<\/code><\/pre>\\n\\n<h3>Voraussetzungen<\/h3>\\n<ul>\\n    <li>Python 3.x<\/li>\\n    <li>PyMySQL (bereits installiert: <code>pip3 install pymysql<\/code>)<\/li>\\n    <li>python-dotenv (bereits installiert)<\/li>\\n    <li>Zugriff auf ki_dev.task_results<\/li>\\n    <li>.env Datei im Hook-Verzeichnis mit DB-Credentials<\/li>\\n<\/ul>\\n\\n<h3>Fail-Safe Verhalten<\/h3>\\n<p>Bei DB-Verbindungsfehlern wird der Hook \\\"fail-open\\\" - d.h. die Aktion wird durchgelassen, um Claude nicht zu blockieren. Die Server-seitige Validierung in MCP-Tasks greift dann als zweite Verteidigung.<\/p>\\n\\n<h3>Validierung<\/h3>\\n<table>\\n    <tr><th>Prüfpunkt<\/th><th>Status<\/th><\/tr>\\n    <tr><td>PyMySQL verfügbar<\/td><td>✓ PyMySQL 1.1.2 installiert<\/td><\/tr>\\n    <tr><td>python-dotenv Pattern<\/td><td>✓ Konsistent mit log_storage.py<\/td><\/tr>\\n    <tr><td>DB_CONFIG Pattern<\/td><td>✓ Identisch zu bestehenden Hooks<\/td><\/tr>\\n    <tr><td>Exit-Code Pattern<\/td><td>✓ 0=allow, 2=block (wie block_direct_db.py)<\/td><\/tr>\\n    <tr><td>Matcher-Syntax<\/td><td>✓ Regex-kompatibel für MCP-Tools<\/td><\/tr>\\n    <tr><td>Fail-Open Design<\/td><td>✓ Bei Fehler durchlassen<\/td><\/tr>\\n<\/table>\\n\",\n    \"status\": \"published\",\n    \"sort_order\": 6,\n    \"depth\": 2,\n    \"created_at\": \"2025-12-27T10:08:47\",\n    \"updated_at\": \"2025-12-27T15:19:06\"\n  }\n}"
        }
    ]
}
← Vorheriger Zur Liste Nächster →