feat: lokaler MCP-Server, Phase 2 (Write-Tools + Bestätigungsdialog + Lesson-Plans)

Neue Write-Tools create_time_entry, create_grade_entry und
update_student_group_assignment schreiben nie direkt: jeder Aufruf zeigt
zuerst einen menschenlesbaren Bestätigungsdialog (bestehender
ConfirmDialog, über Dispatcher.UIThread aus dem Pipe-Session-Thread
angezeigt) und schreibt erst nach Bestätigung, mit 2-Minuten-Timeout
gegen eine hängende Session. Zusätzliches Read-Tool get_lesson_plans.

create_note bewusst nicht umgesetzt (kollidiert mit dem bestehenden
Dokumentations-Ausschluss aus Phase 1), create_lesson_plan/
update_lesson_plan wegen der Modellkomplexität von Lesson zurückgestellt
(siehe TODO.md 4.5.26).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-11 20:14:51 +02:00
co-authored by Claude Sonnet 5
parent 98f5573999
commit 9567d8d616
13 changed files with 529 additions and 30 deletions
+41 -5
View File
@@ -2493,13 +2493,49 @@ folgenden Punkte gehören direkt in `LehrerApp.Desktop`:
`tools/list``tools/call get_students` über die reale Named Pipe) bestätigt die volle
Kette; 9 Unit-Tests für Tool-Filterlogik und die Scope-Allowlist in
[McpToolsTests.cs](LehrerApp.Desktop.Tests/McpToolsTests.cs).
- **Bewusst zurückgestellt (spätere Phasen):** Write-Tools samt Bestätigungsdialog-UI,
`get_lesson_plans`, Worksheets-Tools (`list_worksheets`/`download_worksheet`/...),
macOS-Bundle-Signierung der Bridge-Binary, Named-Pipe-basierte
Einzelinstanz-Absicherung (die Spec-Idee dazu funktioniert nicht, da die Pipe nur bei
aktiviertem Opt-in existiert — LehrerApp hat ohnehin noch keinen
- **Bewusst zurückgestellt (spätere Phasen):** Write-Tools samt Bestätigungsdialog-UI
(folgt in 4.5.26), `get_lesson_plans` (folgt in 4.5.26), Worksheets-Tools
(`list_worksheets`/`download_worksheet`/...), macOS-Bundle-Signierung der Bridge-Binary,
Named-Pipe-basierte Einzelinstanz-Absicherung (die Spec-Idee dazu funktioniert nicht, da
die Pipe nur bei aktiviertem Opt-in existiert — LehrerApp hat ohnehin noch keinen
Single-Instance-Mechanismus, unabhängig von MCP).
- [x] **4.5.26** Lokaler MCP-Server, Phase 2 (Write-Tools + Bestätigungsdialog + Lesson-Plans),
2026-09-11, direkte Fortsetzung von 4.5.25.
- **Bestätigungsdialog:** `IMcpConfirmationService`/`AvaloniaMcpConfirmationService`
([Services/Mcp/AvaloniaMcpConfirmationService.cs](LehrerApp.Desktop/Services/Mcp/AvaloniaMcpConfirmationService.cs))
zeigt den bereits vorhandenen `ConfirmDialog` (Views/Shared, bisher nur intern genutzt) über
`Dispatcher.UIThread.InvokeAsync` an, obwohl der aufrufende Tool-Handler auf dem
Pipe-Session-Hintergrund-Thread läuft — "kein silent write": ein Write-Tool schreibt nie,
ohne dass der Nutzer den konkreten (menschenlesbaren, nicht bloß JSON/GUIDs) Vorschlag
gesehen und bestätigt hat. 2 Minuten Timeout (schließt den Dialog automatisch und wertet als
abgelehnt), damit eine hängende Pipe-Session nicht unbegrenzt den wartenden KI-Client blockiert.
Interface gehalten, damit Write-Tool-Tests ohne echtes UI laufen (`FakeMcpConfirmation` in
[Fakes.cs](LehrerApp.Desktop.Tests/Fakes.cs)).
- **Neue Tools:** `create_time_entry`, `create_grade_entry` (beide Write, mit Bestätigung),
`update_student_group_assignment` (Write; legt `GroupMembership` an oder ändert nur
Niveau/Zeitraum/Beitritt/Austritt — bei bereits identischem Stand keine erneute Nachfrage),
`get_lesson_plans` (Read; `Unit`+`Lesson` einer Gruppe im Zeitraum). `McpToolScope` um
`AllowedWriteTools` erweitert, `McpServerHostedService` prüft per `Debug.Assert` weiterhin,
dass die tatsächlich registrierten Tools exakt der Allowlist entsprechen.
- **Bewusste Abweichung von der Spec:** `create_note` (Spec: "nur für nicht-sensible
Notiztypen") wird **nicht** umgesetzt — das einzige existierende Notiz-Modell
(`Documentation`, Gesprächsnotizen/Vorfälle/Förderpläne) ist bereits vollständig
MCP-ausgeschlossen (4.5.25), ein separates "nicht-sensibles" Notiz-Konzept existiert im
Datenmodell nicht und würde eine neue Entität erfinden, nur um die Spec-Zeile zu erfüllen.
- **`create_lesson_plan`/`update_lesson_plan`** bewusst weiter zurückgestellt: `Lesson` ist
das mit Abstand komplexeste Modell (verschachtelte `Phases`, Anhänge) und verdient einen
eigenen Schritt statt in Phase 2 mit reinzurutschen.
- **Verifiziert:** End-to-End-Smoke-Test wie in 4.5.25, erweitert um einen echten
`create_time_entry`-Aufruf über Bridge → Pipe → `McpServer` → Confirmation-Callback →
Repository-Save (mit automatisch bestätigender Test-`IMcpConfirmationService`-Instanz statt
echtem Dialog) — bestätigt, dass async Write-Tool-Handler mit `CancellationToken`-Bindung
durch das SDK korrekt funktionieren. 18 Unit-Tests in
[McpToolsTests.cs](LehrerApp.Desktop.Tests/McpToolsTests.cs) (vorher 9), decken u.a. ab:
Bestätigung/Ablehnung je Write-Tool, dass die Bestätigungsnachricht den Schülernamen statt
einer rohen GUID enthält, und dass eine unveränderte Gruppenmitgliedschaft keine erneute
Nachfrage auslöst.
**Wichtige Abweichung von der ursprünglichen Planung (5.2):** Vor der Umsetzung zeigte sich,
dass 5.2 wie ursprünglich beschrieben eine zweite, parallele Fehlzeiten-Erfassung neben dem
bereits bestehenden Anwesenheits-Tracking aus Kapitel 3 (`ParticipationEntry.Attendance`,