docs: MCP beschreiben, Fahrplan abschliessen

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Florian Wilde
2026-09-13 15:19:30 +02:00
co-authored by Claude Opus 5
parent bdc4260d59
commit 0ccb21303d
6 changed files with 141 additions and 20 deletions
+23
View File
@@ -6,6 +6,29 @@ die Versionierung [Semantic Versioning](https://semver.org/lang/de/).
## [Unveröffentlicht]
### Hinzugefügt
- **MCP-Server** unter `/api/mcp` mit sechs Werkzeugen: Aufgaben suchen,
Woche ansehen, Kalender auflisten, Aufgabe anlegen, abhaken und einplanen.
Beschreibung in [docs/MCP.md](docs/MCP.md).
- Die Werkzeugliste richtet sich nach den Rechten des Tokens — was ein Token
nicht darf, sieht das Modell gar nicht erst.
### Geändert
- Das Einplanen liegt jetzt an einer Stelle, die sowohl die Oberfläche als
auch der MCP-Server benutzen. Ein über MCP angelegter Zeitblock verhält
sich damit genau wie ein von Hand gezogener.
### Sicherheit
- MCP benutzt dieselben Tokens und dieselben Rechte wie die Schnittstelle.
Ein Sprachmodell bekommt keinen eigenen Zugang.
- Jede schreibende Nutzung steht im Protokoll, mit dem Vermerk, dass sie
über MCP kam.
- Der Server kann weder löschen noch Bereiche, Projekte, Kalenderkonten,
Einstellungen oder Tokens anfassen.
## [0.7.0] – 2026-09-13
### Hinzugefügt
+5 -2
View File
@@ -43,6 +43,8 @@ wird.
Planer lässt sich als App auf dem Startbildschirm ablegen
- **Öffentliche Schnittstelle** mit Tokens je Anwendung, Rechten je Token und
jeder schreibenden Nutzung im Protokoll ([Beschreibung](docs/API.md))
- **MCP-Server** für Sprachmodelle — dieselben Tokens, dieselben Rechte
([Beschreibung](docs/MCP.md))
- Anmeldung über einen OIDC-Anbieter, über Passkeys oder mit E-Mail und
Passwort — je Instanz einzeln zuschaltbar
- Rollen `Benutzer` und `Verwaltung`; jede schreibende Aktion wird
@@ -51,9 +53,10 @@ wird.
- Hell und Dunkel, Oberfläche durchgehend auf Deutsch
- Betrieb über Docker Compose, mit Sicherung, Aktualisierung und Healthcheck
### Geplant
### Was noch kommen könnte
Ein MCP-Server. Siehe [ROADMAP.md](ROADMAP.md).
Der [Fahrplan](ROADMAP.md) ist abgearbeitet. Was danach denkbar wäre, steht
dort unter „Ideen für später" — und was bewusst nicht kommt, gleich darunter.
## Bildergalerie
+14 -4
View File
@@ -12,7 +12,7 @@ grünen Prüfungen, aktueller Dokumentation und einem Eintrag im DEVLOG.
| [M5](#m5--benachrichtigungen) | Benachrichtigungen | erledigt |
| [M6](#m6--integrationen) | Integrationen | erledigt |
| [M7](#m7--schnellerfassung-und-api) | Schnellerfassung und API | erledigt |
| [M8](#m8--mcp) | MCP | geplant |
| [M8](#m8--mcp) | MCP | erledigt |
---
@@ -156,9 +156,19 @@ Zeremonie als Schutz.
## M8 – MCP
- [ ] MCP-Server über `@modelcontextprotocol/sdk`
- [ ] Lesen und Anlegen von Aufgaben und Zeitblöcken
- [ ] Rechte wie bei der API, jede Nutzung im Protokoll
**Erledigt am 13.09.2026 mit Version 0.8.0.**
**Ziel:** Ein Sprachmodell soll den Alltag erleichtern können — ohne einen
eigenen, weicheren Zugang zu bekommen als jede andere fremde Anwendung.
- [x] MCP-Server über `@modelcontextprotocol/sdk`
- [x] Lesen und Anlegen von Aufgaben und Zeitblöcken
- [x] Rechte wie bei der API, jede schreibende Nutzung im Protokoll
- [x] Werkzeugliste richtet sich nach den Rechten des Tokens
**Bewusst offen gelassen:** Der Server kann nichts löschen, keine Bereiche
oder Projekte anlegen und keine Einstellungen anfassen. Ein Modell soll den
Alltag erleichtern, nicht die Ordnung umbauen.
---
+83
View File
@@ -0,0 +1,83 @@
# MCP-Server
Der Planer spricht das Model Context Protocol. Damit kann ein Sprachmodell
Aufgaben suchen, anlegen, abhaken und einplanen — mit denselben Tokens und
denselben Rechten wie die [Schnittstelle](API.md).
Adresse: `<APP_URL>/api/mcp`
## Einrichten
1. In der Anwendung unter **API** einen Token anlegen. Gib ihm nur, was das
Modell wirklich braucht.
2. Den Client auf die Adresse zeigen lassen, mit dem Token als Bearer.
Für Claude Code:
```bash
claude mcp add planer --transport http https://planer.example.de/api/mcp \
--header "Authorization: Bearer planer_…"
```
Für Clients, die nur stdio können, dazwischen `mcp-remote` setzen:
```json
{
"mcpServers": {
"planer": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://planer.example.de/api/mcp",
"--header",
"Authorization: Bearer planer_…"
]
}
}
}
```
## Werkzeuge
Welche ein Modell zu sehen bekommt, hängt am Token. Was nicht erlaubt ist,
taucht gar nicht erst in der Liste auf — ein Modell soll nicht gegen eine Tür
laufen, die für es verschlossen ist.
| Werkzeug | Recht | Was es tut |
| -------------------- | ----------- | ----------------------------------------------- |
| `aufgaben_suchen` | `lesen` | Aufgaben auflisten, optional gefiltert |
| `woche_ansehen` | `lesen` | Zeitblöcke einer Woche mit Summe |
| `kalender_auflisten` | `lesen` | Verbundene Kalender samt Kennung |
| `aufgabe_anlegen` | `erfassen` | Neue Aufgabe in der Inbox |
| `aufgabe_abhaken` | `schreiben` | Aufgabe auf erledigt setzen |
| `zeitblock_anlegen` | `schreiben` | Aufgabe einplanen und in den Kalender schreiben |
Zum Einplanen braucht es die Kennung eines Kalenderkontos — daher erst
`kalender_auflisten`, dann `zeitblock_anlegen`.
`zeitblock_anlegen` geht durch dieselbe Stelle wie das Ziehen in der
Wochenansicht: Rasterprüfung, Kalenderschreibweg, Schleifenschutz, Protokoll.
Ein über MCP angelegter Zeitblock verhält sich also genau wie ein von Hand
gezogener.
## Was der Server bewusst **nicht** kann
- **Löschen.** Weder Aufgaben noch Zeitblöcke. Abhaken ja, wegräumen nein.
- **Bereich oder Projekt setzen.** Was hier entsteht, landet in der Inbox.
- **Bereiche, Projekte oder Kalenderkonten anlegen und ändern.**
- **Einstellungen oder Tokens anfassen.**
Ein Modell soll den Alltag erleichtern, nicht die Ordnung umbauen.
## Protokoll
Jede schreibende Nutzung landet im Protokoll — mit dem Vermerk, dass sie über
MCP kam, und mit dem Token. Ein Modell, das Aufgaben anlegt, muss genauso
nachvollziehbar sein wie ein Mensch. Eher noch mehr.
## Ohne Sitzungen
Der Server ist zustandslos: Jede Anfrage steht für sich. Der Planer hat keine
langlaufenden Vorgänge, und eine Sitzungsverwaltung wäre Zustand, den mehrere
Container nicht teilen könnten.
+1 -10
View File
@@ -31,18 +31,9 @@ Anleitung für den Alltag mit dem Planer. Eine Seite je Thema.
11. **[Protokoll](protokoll.md)** – nachsehen, wer wann was geändert hat
## Was noch kommt
Diese Seiten entstehen mit den nächsten Meilensteinen:
| Thema | Meilenstein |
| ----- | ----------- |
| MCP | M8 |
Der [Fahrplan](../../ROADMAP.md) sagt, was in welchem Meilenstein steckt.
---
Für fremde Anwendungen und Skripte: [Schnittstelle](../API.md).
Für Sprachmodelle: [MCP-Server](../MCP.md).
Zur Einrichtung einer neuen Instanz: [Schnellstart](../SCHNELLSTART.md).
Für Betrieb, Sicherung und alle Umgebungsvariablen: [README](../../README.md).
+15 -4
View File
@@ -70,10 +70,10 @@ export async function zeitblockAnlegen(daten: FormData): Promise<Rueckmeldung> {
const ergebnis = await zeitblockAnlegenFuer(
{ id: akteur.id, email: akteur.email },
{
aufgabeId: String(daten.get('aufgabeId') ?? ''),
kalenderkontoId: String(daten.get('kalenderkontoId') ?? ''),
beginn: new Date(String(daten.get('beginn') ?? '')),
ende: new Date(String(daten.get('ende') ?? '')),
aufgabeId: feld(daten, 'aufgabeId'),
kalenderkontoId: feld(daten, 'kalenderkontoId'),
beginn: new Date(feld(daten, 'beginn')),
ende: new Date(feld(daten, 'ende')),
},
)
@@ -91,6 +91,17 @@ export async function zeitblockAnlegen(daten: FormData): Promise<Rueckmeldung> {
}
}
/**
* Ein Textfeld aus dem Formular.
*
* FormData kann auch Dateien liefern; die haetten hier nichts zu suchen und
* wuerden beim Stringify zu "[object Object]".
*/
function feld(daten: FormData, name: string): string {
const wert = daten.get(name)
return typeof wert === 'string' ? wert : ''
}
// --- Verschieben -----------------------------------------------------------
const verschieben = z.object({