Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 76 additions & 7 deletions docs/MCP.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# ThreadDesk MCP

Lokaler stdio-Server. Stellt Thread-Kontext bereit. Startet keine Agenten.
Lokaler stdio-Server mit dynamischen Fachwerkzeugen aus der gemeinsamen
CommandRegistry. Bestehende Werkzeugnamen bleiben erhalten. ThreadDesk bleibt
eigenständig; KiraBridge führt seine eigene Autorisierung vor dem Aufruf durch.

```bash
td mcp
Expand All @@ -14,18 +16,85 @@ Beispiel für einen MCP-Client:
{
"mcpServers": {
"threaddesk": {
"command": "/Users/landjunge/threaddesk/.venv/bin/threaddesk-mcp"
"command": "/Applications/ThreadDesk.app/Contents/Resources/bin/ThreadDeskServer",
"args": ["--mcp"],
"env": {
"THREADDESK_HOME": "/absoluter/autorisierter/workspace",
"THREADDESK_STORAGE": "json"
}
}
}
}
```

Tools: `thread_manage`, `thread_operation_status`, `list_threads`, `get_thread`, `current_thread`, `switch_thread`, `add_note`, `save_snapshot`, `list_snapshots`, `restore_snapshot`, `generate_prompt`, `export_handoff`, `export_grok`, `export_gnom`, `check_gate`, `dashboard`.
## Dynamische Fachwerkzeuge

`tools/list` erzeugt zusätzlich für jeden aktuell autorisierten, auf dem aktiven
Backend über MCP verfügbaren Registrybefehl ein eigenes Werkzeug. Beispielsweise
wird `whiteboard.create` zu `td_whiteboard__create`; Punkte werden `__`, vorhandene
Unterstriche `_u`. Namen haben höchstens 64 Zeichen und verwenden bei überlangen
Identitäten einen stabilen SHA256-Suffix. Die vollständige Command-ID steht in
`_meta.threaddesk.id`. Keine zweite manuell zu pflegende Funktionsliste.

Jedes Werkzeug veröffentlicht sein konkretes Fachschema unter `arguments` und
den öffentlichen Berechtigungsvertrag einschließlich Scope, Wirkung, Revision,
Backends und Modulfreigaben in `_meta.threaddesk`. Der dort mitgelieferte
`workspace_id` muss beim Aufruf unverändert mitgesendet werden. Mutationen
benötigen `operation_id` sowie die im Schema geforderte `expected_revision`.
Registrierte Modulbefehle erscheinen nach Freigabe ohne Neustart; Schemaänderung,
Deaktivierung, Rechteentzug und Deinstallation wirken unmittelbar auf Discovery
und auf schon bekannte Werkzeugnamen. Der stdio-Server meldet Änderungen auch
bei ruhender Eingabe mit `notifications/tools/list_changed`.

Archivieren und explizites Löschen sind über `thread_manage` möglich; es gibt
kein allgemeines Datei- oder Agenten-Ausführungstool. Der ältere Werkzeugkatalog
bleibt kompatibel. Für neue schreibende Gesprächsabläufe `thread_manage` verwenden,
da nur dieser Verwaltungsweg persistente Operationsbelege anbietet.
```json
{
"name": "td_whiteboard__create",
"arguments": {
"workspace_id": "ws-WERT_AUS_TOOLS_LIST",
"operation_id": "whiteboard-create-1",
"expected_revision": 0,
"arguments": {"title": "Besprechung"}
}
}
```

Das Resultat ist der vorhandene SHA256-gebundene Commandbeleg, einschließlich
Operationsidentität, Wiederholung/Konflikt und begrenztem Readback. Lesende
Aufrufe bauen keinen Index neu. `command_catalog`, `command_query` und
`command_invoke` bleiben als kompatible Zugänge erhalten. Owner-only `search.*`
und `server_sync.owner_reference` werden über MCP weiterhin gesperrt; ein
Requestfeld kann keine Rechte erteilen. Endgültiges Löschen bleibt an den
bestehenden Papierkorb-, Ampel-, Vorschau- und Bestätigungsvertrag gebunden.
Details: [dynamischer MCP-Vertrag](contracts/mcp-dynamic-v1.md).

Die aktuelle paketierte Serverdatei stellt denselben Endpunkt bereit:

```bash
THREADDESK_HOME=/absoluter/autorisierter/workspace THREADDESK_STORAGE=sqlite \
/Applications/ThreadDesk.app/Contents/Resources/bin/ThreadDeskServer --mcp
```

Alternativ ist `THREADDESK_STORAGE=json` möglich. Ein vorhandenes
`active-profile.json` wählt weiterhin das effektive Profil. Dieser Startweg
gilt für ein aus dem aktuellen Quellstand gebautes Paket; ein älteres
installiertes Paket erhält dadurch keine neue Fähigkeit. KiraBridge-App,
Terminalsteuerung und Prozesskonfiguration werden von ThreadDesk nicht verändert.
Ob ein bestehender KiraBridge-Prozess diesen neuen Endpunkt bereits verwendet,
muss separat mit dessen tatsächlichem Quellpin und einem Aufruf geprüft werden.

Eine laufende MCP-Sitzung bleibt an den beim Start ausgewählten Workspace
gebunden. `profiles.activate` oder `backup.restore` ändern die Profilauswahl für
neue Verbindungen; sie lenken bestehende Operationsbelege und Revisionen nicht
still auf andere Daten um. Nach einem Profilwechsel neu verbinden und die neue
Workspace-ID aus frischer Discovery lesen.

## Bestehende Zugänge

Der statische Katalog bleibt kompatibel. Neue Gesprächsabläufe können die
dynamischen Fachwerkzeuge mit dauerhaften Operationsbelegen verwenden.
Legacy `thread_manage`-Aktion `delete` ist gesperrt; Verschieben in den
Papierkorb, Wiederherstellen und explizites endgültiges Löschen verwenden den
jeweiligen Fachvertrag.

Notizen und Beschreibungen kommen als `<untrusted source="threaddesk.notes">` — das sind Daten, keine Anweisungen.

Expand Down
2 changes: 1 addition & 1 deletion docs/contracts/commands-v1.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Mutation: eine eindeutige `operation_id` und die laut Katalog erforderliche `exp

## Antworten, Konflikte und Wiederaufnahme

Erfolg: `threaddesk.command-result.v1` mit Workspace, Katalogrevision, Command, SHA256-Ergebnisdigest und `result`. CLI ergänzt `ok`; Exitcode 0 bedeutet Erfolg, Exitcode 2 einen strukturierten Fehler. HTTP `/api/commands` verwendet dieselben Eingaben, Konflikte ergeben 409. MCP bietet `command_catalog`, `command_query` (ausschließlich Reads) und `command_invoke`; alte Toolnamen bleiben erhalten.
Erfolg: `threaddesk.command-result.v1` mit Workspace, Katalogrevision, Command, SHA256-Ergebnisdigest und `result`. CLI ergänzt `ok`; Exitcode 0 bedeutet Erfolg, Exitcode 2 einen strukturierten Fehler. HTTP `/api/commands` verwendet dieselben Eingaben, Konflikte ergeben 409. MCP bietet neben `command_catalog`, `command_query` (ausschließlich Reads) und `command_invoke` automatisch ein konkretes Einzelwerkzeug für jeden verfügbaren registrierten Fachbefehl; alte Toolnamen bleiben erhalten. Schemas, Live-Discovery, Berechtigungen und Änderungsmeldungen beschreibt der [dynamische MCP-Vertrag](mcp-dynamic-v1.md).

CLI-/MCP-Resultate werden auf 24.000 Bytes begrenzt. Große Ergebnisse erscheinen als JSON-Textseiten: `result_page`, `encoding=json-text-codepoint-pages`, `offset`, `next_offset`, `total`. Beim Weiterlesen ursprünglichen Request plus `result_digest` und `result_offset` verwenden; alle Seiten in Reihenfolge verbinden und erst danach als JSON parsen. Bei zeitabhängigen Reads außerdem das zurückgegebene `snapshot_at` weitergeben. Ein geändertes Ergebnis führt zu `result_changed`; nie Seiten verschiedener Versionen vermischen. Große Exporte/Backups sind SHA256-gebundene Artefakte mit geschütztem Download, kein unbeschränkter Terminaltext.

Expand Down
119 changes: 119 additions & 0 deletions docs/contracts/mcp-dynamic-v1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# Dynamische MCP-Fachwerkzeuge v1

Die vorhandene `CommandRegistry` ist die einzige Quelle der fachlichen
Werkzeugdefinitionen. `McpCommands` projiziert sie auf MCP und ruft die bestehende
`CommandApplication` auf. Kein Reflection-Export beliebiger Pythonmethoden,
zusätzlicher Dispatcher, Datenspeicher oder KiraBridge-Code wird eingeführt.
Neue registrierte Quellbefehle werden beim nächsten Discovery automatisch
berücksichtigt; neue Modulbefehle verwenden den bestehenden deklarativen
[Modulvertrag](module-commands-v1.md).

## Namen und Discovery

Einzelwerkzeuge beginnen mit `td_`. In der Command-ID werden `.` durch `__` und
`_` durch `_u` ersetzt; ASCII-Buchstaben, Zahlen und Bindestriche bleiben erhalten.
Andere Zeichen werden hexadezimal maskiert. Überlange Namen werden auf ein
lesbares Präfix und 40 SHA256-Hexzeichen gekürzt. Alle Namen erfüllen den
bestehenden KiraBridge-Namenvertrag `[A-Za-z][A-Za-z0-9_-]{0,63}`; insbesondere
bleiben `a.b` und `a_b` verschieden. Ein tatsächlicher Namenskonflikt wird
abgewiesen. Die vollständige Command-ID steht in `_meta.threaddesk.id`.

`tools/list` ist eine aktuelle, deterministisch geordnete Projektion. Es liefert
Einzelwerkzeuge ausschließlich für `availability=available` im MCP-Transport.
Scope, aktives Speicherbackend, Modulaktivierung, deklarierte Fähigkeiten und
tatsächlich gewährte Modulfreigaben werden berücksichtigt. Die bestehenden
Legacywerkzeuge und drei Commandgateways bleiben kompatibel. Ein durch den
vertrauenswürdigen Serverkontext eingeschränkter `McpBridge(allowed_scopes=...)`
filtert auch Legacywerkzeuge und verhindert deren direkten Aufruf als Umgehung.
Ohne solche Einschränkung gilt der bestehende lokale Operator-/Workspacekontext;
dadurch wird keine zusätzliche Principalidentität behauptet.

Der stdio-Server kündigt `tools.listChanged=true` an. Nach
`notifications/initialized` prüft sein Hauptthread die Katalogrevision bei
Requests und etwa einmal pro Sekunde bei ruhender Eingabe. Änderungen durch
einen anderen ThreadDesk-Prozess führen zu `notifications/tools/list_changed`.
Ein begrenzter Eingabethread liest nur stdin; SQLite wird ausschließlich im
Hauptthread benutzt. Jede `tools/list`-Anfrage prüft erneut. Eine nicht lesbare
Discovery führt zum protokollierten Requestfehler statt zu einer behaupteten
aktuellen Werkzeugliste. Ein Client muss die Liste nach einer Änderungsmeldung
neu lesen; ThreadDesk kann dessen Cacheverhalten nicht erzwingen.

Die Transportmechanismen folgen den offiziellen MCP-Verträgen für
[Werkzeuge und Änderungsmeldungen](https://modelcontextprotocol.io/specification/2025-11-25/server/tools).
Die vorhandene Protokollversion des stdio-Handshakes bleibt kompatibel.

## Konkretes Eingabeschema und Rechte

Jedes Einzelwerkzeug veröffentlicht:

- `workspace_id`: Pflichtbindung an den aktuell ausgewählten Workspace.
- `arguments`: das konkrete, quellverantwortete JSON-Schema des Fachbefehls.
- `operation_id`: Pflicht für jede Mutation.
- `expected_revision`: Pflicht gemäß Revisionsziel beziehungsweise nativem Vertrag.
- Optionale `catalog_revision`, `result_offset`, `result_digest`, `snapshot_at`
aus dem gemeinsamen [Commandvertrag](commands-v1.md).

Bei nativen Verträgen injiziert `CommandApplication` Operation und Revision aus
dem Envelope vor der Fachvalidierung. Diese beiden Pflichtfelder werden deshalb
im veröffentlichten Fachschema nur aus dessen oberster `required`-Liste entfernt
und ins äußere Schema übernommen. Optionale Kopien im Fachobjekt bleiben erlaubt;
abweichende Werte werden durch die bestehende Anwendung abgewiesen. Die übrigen
Fachbedingungen bleiben bestehen, auch bedingte Regeln und Modulschemaeinschränkungen.

Das eingebettete Fachschema bleibt eine eigene JSON-Schema-Ressource, damit
lokale `$ref`-Fragmente, Rootrekursion, Anker und dynamische Anker weiterhin auf
seine ursprüngliche Wurzel zeigen. Eine vorhandene ressourcenbenennende `$id`
bleibt erhalten. Für anonyme Schemas einschließlich leerer `$id` oder `#` erhält
die veröffentlichte Kopie eine stabile synthetische URN; Quellschema und
Quellmetadaten bleiben unverändert. Ins Envelope gehobene native Feldschemas
referenzieren dieselbe Fachressource. Die bestehende Validierung bleibt ohne
externen Schemaabruf; eine externe Referenz erteilt keinen Netzwerkzugriff.

`_meta.threaddesk` enthält den vollständigen öffentlichen Commandvertrag,
insbesondere unverändertes Quellschema, Command-ID, Scope, Wirkung,
Revisionsziel, erforderliche Operation, Backend-/Transportgrenzen,
`workspace_id` und gegebenenfalls den Modulberechtigungsvertrag. Metadaten und
MCP-Annotations sind Beschreibungen; sie erteilen keine Berechtigung.

Beim Aufruf werden Workspace, aktuelle Verfügbarkeit, Schema, Operation,
Revision und optionale Katalogbindung durch dieselbe `CommandApplication`
geprüft. Ein bekannter Werkzeugname bleibt nach Deaktivierung oder Rechteentzug
gesperrt. Requestfelder können weder Scopes noch Transport, Principal,
Workspaceprozess, Programmdatei oder Modulfreigaben auswählen. `search.*` und
`server_sync.owner_reference` behalten ihre Owner-/CLI-Grenze.

## Belege, Konflikte und Löschschutz

Ergebnisse verwenden `threaddesk.command-result.v1` mit Workspace,
Katalogrevision, fachlichem Resultat und `result_digest`. Mutationen liefern
zusätzlich ihre Operationsidentität und `duplicate`. Der stdio-Transport gibt
Objektergebnisse als `structuredContent` sowie denselben JSON-Inhalt als
Textblock zurück. Fehler behalten die vorhandenen Codes und `isError=true`.

Identische Wiederholung verwendet den dauerhaften Commandbeleg. Geänderte
Nutzlast unter derselben Operation führt zu `operation_conflict`, veraltete
Version zu `revision_conflict`. Nach unklarer Zustellung liest der Client
`command.operation`; OS-/Netzwerkeffekte werden nicht blind wiederholt.
Große Resultate verwenden die bestehenden digestgebundenen Readbackseiten.
Ein dynamischer Lesebefehl löst keinen zusätzlichen Indexrefresh aus.

Der Adapter schwächt keine Fachbestätigung: Papierkorb-Ampel,
objekt-/generations-/digestgebundene Löschvorschau und ausdrückliche
Bestätigung für endgültiges Löschen bleiben bei den bestehenden Services.
Das Veröffentlichen von `trash.purge` erteilt selbst keinen Löschauftrag.

## Nachweisgrenze

`tests/test_mcp_dynamic_commands.py` prüft JSON und SQLite, vollständige
autorisierte Registryabdeckung, Namensgrenzen, künftige Registrierung im
gleichen Bridgeobjekt, Fachschemas, Scope-/Backend-/Ownergrenzen,
Native-Operationen, Wiederholung, Konflikte, Readback sowie Modulinstallation,
Aktivierung, Schemaänderung, Rechteentzug und Deinstallation. Ein separater
echter stdio-Prozess belegt Discovery, Fachaufruf und eine Änderungsmeldung bei
ruhender Eingabe nach externer Modulaktivierung.

Diese Prüfungen belegen den ThreadDesk-Endpunkt. Sie beweisen weder, dass eine
vorhandene KiraBridge-Konfiguration auf diesen Quellstand zeigt, noch eine
bestimmte KiraBridge-Principalberechtigung. Eine konkrete Gegenstellenprüfung,
finaler Quellpin, Pflicht-CI und installierter Paketpin müssen im
auftragsbezogenen Ergebnisbeleg gesondert dokumentiert werden.
Loading
Loading