Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
508 lines
42 KiB
Markdown
508 lines
42 KiB
Markdown
# WP-LIT-MCP – Design-Spezifikation
|
||
|
||
- **Datum:** 2026-09-25
|
||
- **Status:** Entwurf zur Freigabe
|
||
- **Autor:** Jan-Niclas Loosen (Loosen-IT), erarbeitet mit Claude
|
||
|
||
## 1. Ziel und Kontext
|
||
|
||
### 1.1 Problem
|
||
|
||
Die Pflege von Kunden-Websites (WordPress + Divi 5 + Pods) kostet viel Handarbeit: Seiten anlegen, in Menüs hängen, Divi-Abschnitte bauen, Corporate Designs in Divi übertragen, Custom-Post-Type-Einträge befüllen. Bestehende WordPress-MCP-Plugins erzeugen nur rohes HTML, das im Divi-Builder nicht weiterbearbeitet werden kann. Der Divi AI Agent (Divi 5) arbeitet nur im Builder, läuft über das kostenpflichtige AI Wallet und bietet (Stand 2026-09) keine MCP-Schnittstelle.
|
||
|
||
### 1.2 Ziel
|
||
|
||
Ein WordPress-Plugin, das auf jeder Kundenseite einen MCP-Server bereitstellt, mit dem ein KI-Assistent (z. B. über den claude.ai-Connector) die Website pflegt – **so, dass alle Ergebnisse native Divi-Strukturen sind, die der Mensch im Divi Visual Builder weiter verfeinern kann.**
|
||
|
||
### 1.3 Erfolgskriterien
|
||
|
||
1. Ein claude.ai-Connector verbindet sich per OAuth mit einer Kundenseite; nur freigegebene Rollen können Tools nutzen.
|
||
2. Vom KI-Assistenten erzeugte oder geänderte Divi-Inhalte sind im Visual Builder vollständig bearbeitbar (manuell verifiziert pro Etappe).
|
||
3. Unangetastete Inhalte bleiben byte-identisch erhalten. Dokumentierte Ausnahme (Ruling S7): Divi selbst normalisiert Seiten mit eigenen HTML-/Attribut-Feldern beim Speichern (`AttributeSecurity`/`HtmlSecurity` auf `wp_insert_post_data`, laufen für jeden Benutzer und werden nie entfernt) – aber nur, wenn die Seite noch nicht in Divis `serialize_blocks()`-Form gespeichert war (z. B. Import, direkter DB-Schreibzugriff); über Builder oder LIT MCP gespeicherte Seiten bleiben unverändert (E2E Abschnitt 8a); die Antwort meldet das als Warnung „Inhalt beim Speichern verändert“ (`CHANGED_ON_SAVE`), die Seite bleibt gültig (E2E `divi-write-smoke.sh` Abschnitt 8).
|
||
4. Eine neue Website (Seitenstruktur, Menü, Einstellungen, Designsystem aus einem CD) lässt sich im Dialog aufsetzen.
|
||
5. Jede Änderung ist nachvollziehbar (Protokoll) und umkehrbar (Revision bzw. Snapshot).
|
||
|
||
### 1.4 Verifizierte Grundlagen
|
||
|
||
- Handgeschriebenes Divi-5-Block-Markup (`<!-- wp:divi/section … -->`) wird von Divi als native Module gerendert (`et_pb_section`, `et_pb_heading`, …) und ist im Visual Builder bearbeitbar (lokal getestet, 2026-09-25).
|
||
- Divi liefert serverseitig alle Modul-Metadaten: `ModuleRegistration::get_all_core_modules_metadata()` (100 Module mit Attribut-Schemata), Default-Attribute über `ModuleRegistration::get_default_attrs()`.
|
||
- WordPress 7.0 enthält die Abilities API im Kern.
|
||
|
||
## 2. Grundprinzipien
|
||
|
||
1. **Divi-nativ:** Es werden nur echte Divi-Blöcke erzeugt. Das Code-Modul ist erlaubt, wird aber nachrangig behandelt (Katalog-Hinweis „nur wenn kein natives Modul passt“, Warnung bei Verwendung). Jedes erzeugte Element erhält ein sprechendes Admin-Label.
|
||
2. **Designsystem an der Quelle:** Farben, Schriften, Variablen, Presets werden immer live aus Divi/WordPress gelesen; es gibt keine doppelte Pflege. Neue Inhalte nutzen Variablen und Presets statt fester Werte.
|
||
3. **Generisch vor fest verdrahtet:** Post-Typen, Taxonomien und Felder werden pro Installation erkannt. Spezifische Logik nur über generische Erweiterungspunkte.
|
||
4. **Integrationen nach Verfügbarkeit:** Jede Integration (Divi, Pods, …) registriert ihre Tools nur, wenn das Theme/Plugin aktiv ist.
|
||
5. **Status bleibt erhalten:** Schreib-Tools ändern nie den Veröffentlichungsstatus. Veröffentlichen/Zurückziehen/Planen sind eigene, explizite Tools. Veröffentlichte Inhalte werden live bearbeitet (mit Revision).
|
||
6. **Produktiv tauglich:** Jeder Aufruf läuft mit den Rechten des verbundenen WP-Benutzers; zusätzlich Rollen-Freigabe und Rechteprüfung pro Tool.
|
||
7. **Nichts geht verloren:** Revision oder Snapshot vor jeder Änderung, optimistische Sperre (`rev`) gegen das Überschreiben paralleler Handarbeit.
|
||
|
||
## 3. Umfang
|
||
|
||
### 3.1 v1 – Muss
|
||
|
||
| # | Bereich | Inhalt |
|
||
|---|---|---|
|
||
| 1 | Anbindung | OAuth 2.1 für claude.ai (CIMD), Rollen-Gate, Verbindungsübersicht mit Widerruf |
|
||
| 2 | Content generisch | Schema-Erkennung (Post-Typen, Taxonomien, WP-Meta, Pods-Felder); Einträge suchen/lesen/anlegen/bearbeiten; veröffentlichen/zurückziehen/planen; duplizieren und Kopie gegen Original tauschen; Papierkorb; Revisionen |
|
||
| 3 | Menüs | anlegen, Einträge deklarativ setzen, Positionen zuweisen |
|
||
| 4 | Medien | suchen, ansehen (inkl. Vorschaubild), Upload per URL und per Datei, Download, Metadaten/Alt-Texte (auch Stapel), Löschen mit Verwendungsprüfung |
|
||
| 5 | Divi-Seiten | Seitenbaum, Modul-Katalog, einfügen/ändern/verschieben/löschen/duplizieren, seitenübergreifendes Ersetzen mit Dry-Run |
|
||
| 6 | Divi Theme Builder | Vorlagen auflisten/anlegen/zuweisen, Layouts bearbeiten, Dynamic Content (Pods-Felder, Meta, Post-Daten) |
|
||
| 7 | Divi Library / globale Module | speichern, einfügen (Kopie/global), zwischen Seiten kopieren, in globales Modul umwandeln, ähnliche Abschnitte finden |
|
||
| 8 | Divi-Designsystem | globale Farben, Variablen, Presets lesen und schreiben; Snapshots |
|
||
| 9 | Divi-Theme-Optionen | Schriften, Größen, Farben, Buttons, Layout-Maße, Logo, Divi-SEO – über Whitelist |
|
||
| 10 | WP-Einstellungen | Allgemein, Lesen (Startseite), Permalinks, Diskussion, Website-Icon – über Whitelist |
|
||
| 11 | Rückmeldung | einheitliches `ToolResult`; `page_render_summary` |
|
||
| 12 | Protokoll | Änderungsprotokoll mit Aufbewahrungsdauer, Cron-Bereinigung, Leeren |
|
||
| 13 | Anleitungen | Server-Instructions, Tool `lit/guide`, MCP-Prompts |
|
||
|
||
### 3.2 Kann
|
||
|
||
- Google Fonts herunterladen und über Divis Font-Upload selbst hosten.
|
||
- Pods-Strukturen (Pods, Felder) anlegen.
|
||
- Signierte, zeitlich begrenzte Vorschau-Links für Entwürfe ohne Login.
|
||
- Freitext-Hinweise pro Seite (z. B. Tonalität, Du/Sie) als Ergänzung der Server-Instructions.
|
||
|
||
### 3.3 Später
|
||
|
||
- SEO-Plugins (Yoast, Rank Math) als eigene Integrationen.
|
||
- „Fast gleich“-Erkennung von Abschnitten mit Detail-Unterschieden.
|
||
- Tickets und wiederkehrende Termine (The Events Calendar Pro).
|
||
- Umstieg auf MCP-Protokoll 2026-07-28 (sobald der Adapter es unterstützt, siehe §11).
|
||
|
||
### 3.4 Nicht im Umfang
|
||
|
||
- Benutzerverwaltung (Sicherheitsrisiko; ggf. später mit eigenem Konzept).
|
||
- Mehrsprachigkeit (WPML/Polylang).
|
||
- Divi Premade Layouts.
|
||
- Divi 4 / Shortcode-Inhalte (werden gelesen/erhalten, aber nicht bearbeitet).
|
||
|
||
## 4. Architektur
|
||
|
||
### 4.1 Bausteine auf der Kundenseite
|
||
|
||
```
|
||
claude.ai ──OAuth 2.1 (CIMD, PKCE)──▶ wp-media/mcp-oauth (Autorisierung, Token → WP-Benutzer)
|
||
│
|
||
▼
|
||
wordpress/mcp-adapter (MCP-Protokoll, Streamable HTTP)
|
||
│
|
||
▼
|
||
WP-LIT-MCP (Abilities, Server-Konfiguration, Admin)
|
||
```
|
||
|
||
- WP-LIT-MCP bindet `wp-media/mcp-oauth` und `wordpress/mcp-adapter` per Composer ein (Jetpack-Autoloader, `vendor/autoload_packages.php`). Ausgeliefert wird ein einzelnes Plugin.
|
||
- WP-LIT-MCP enthält **keine eigene OAuth-Implementierung**. Die Anbindungsschicht ist austauschbar; Rückfalloption ist `akirk/mcp-connect` (separates Plugin, nutzt allerdings das inzwischen veraltete Dynamic Client Registration).
|
||
- Versionen werden in `composer.lock` fixiert; jedes Update durchläuft den Konformitätstest (§11.4).
|
||
|
||
### 4.2 Anpassungen an wp-media/mcp-oauth
|
||
|
||
Die Bibliothek (v1.1.x) hat Lücken, die WP-LIT-MCP schließt:
|
||
|
||
| Lücke | Lösung |
|
||
|---|---|
|
||
| Kein Rollen-Gate (jeder eingeloggte Benutzer kann autorisieren) | Eigene Capability `lit_mcp_use`, vergeben an die in den Einstellungen freigegebenen Rollen. Gesetzt über die Adapter-Filter `mcp_adapter_{discover_abilities,get_ability_info,execute_ability}_capability` und zusätzlich in jeder Ability geprüft. |
|
||
| Erzeugtes Application Password gilt für alle REST-Routen (Issue #62) | Code-Analyse (v1.1.2): Das Klartext-Passwort wird verworfen, die Token-Prüfung läuft nur in der MCP-Route – vermutlich nicht ausnutzbar. Etappe 0 prüft das per Ende-zu-Ende-Test (Bearer-Token gegen `/wp/v2/users/me` muss 401 liefern). Nur falls der Test fehlschlägt: Filter auf `rest_authentication_errors`, der Bearer-Requests außerhalb der MCP-Route abweist. |
|
||
| Server fest mit drei Meta-Tools, keine direkten Tools | WP-LIT-MCP registriert den Server `mcp-oauth-server` auf `mcp_adapter_init` mit Priorität < 10 selbst, mit `OAuthHttpTransport` und eigener Tool-Liste. Folge bis upstream PR #63: harmloser „duplicate server“-Log-Eintrag. |
|
||
| Adapter auf `^0.5` gepinnt | Akzeptiert; Beobachtung der Upstream-Entwicklung. |
|
||
|
||
Ob dieser Aufbau stabil funktioniert, entscheidet Etappe 0 (§12).
|
||
|
||
### 4.3 Tool-Exposition (hybrid)
|
||
|
||
- **Direkte Tools (~20):** mit vollem Schema sofort sichtbar; nur direkte Tools können Bilder (`ImageContent`) zurückgeben. Standard-Set:
|
||
`lit/guide`, `lit/content-types`, `lit/content-query`, `lit/content-get`, `lit/content-create`, `lit/content-update`, `lit/post-publish`, `lit/media-search`, `lit/media-preview`, `lit/media-upload-from-url`, `lit/divi-outline`, `lit/divi-node-get`, `lit/divi-insert`, `lit/divi-update`, `lit/divi-move`, `lit/divi-delete`, `lit/divi-design-system`, `lit/divi-catalog`, `lit/library-insert`, `lit/page-render-summary`.
|
||
- **Stand nach Etappe 2 (Entscheidung D2, 2026-09-26):** 21 direkte Tools – das Standard-Set oben ohne `lit/library-insert` (kommt mit Etappe 3), dazu `lit/site-status` (leeres Eingabeschema, Anker der Verbindungstests) und `lit/media-download` (eingebettete Ressource, funktioniert nur direkt). `lit/divi-duplicate-node` und `lit/divi-replace-text` sind indirekt. Mit Etappe 3 sind es 22; das Budget wird dort erneut geprüft (Kosten entstehen vor allem durch große Eingabeschemas, nicht durch die Zahl). **Stand nach Etappe 3a:** 22 direkte Tools (dazu `lit/library-insert`); indirekt neu `lit/library-list`, `lit/library-save`, `lit/divi-node-copy`, `lit/divi-dynamic-sources`. Neue Tool-Gruppe „Divi-Bibliothek“ (`lit/library-*`); `lit/divi-node-copy` und `lit/divi-dynamic-sources` gehören zur Gruppe „Divi“. **Stand nach Etappe 3b:** weiterhin 22 direkte Tools; indirekt neu `lit/tb-list`, `lit/tb-create-template`, `lit/tb-assign`, `lit/tb-activate` (neue Tool-Gruppe „Divi Theme Builder“; „nur lesen“ sperrt auch Schreibzugriffe der Divi-Werkzeuge auf Theme-Builder-Layouts, deaktiviert gelten Vorlagen und Layouts als nicht vorhanden) sowie `lit/library-find-similar`, `lit/library-make-global` (Gruppe „Divi-Bibliothek“).
|
||
- **Alle übrigen Abilities:** über die Meta-Tools des Adapters (`discover-abilities`, `get-ability-info`, `execute-ability`).
|
||
- In den Einstellungen änderbar, welche Abilities direkt, indirekt oder deaktiviert sind.
|
||
- Ability-Namen: `lit/<bereich>-<aktion>`. Der Adapter bildet daraus Tool-Namen (`lit-<bereich>-<aktion>`).
|
||
|
||
### 4.4 Plugin-Struktur
|
||
|
||
- Composer, PSR-4 (`LIT\MCP\` → `src/`), PHP ≥ 8.1, WordPress ≥ 6.9 (getestet mit 7.0).
|
||
- Kein Acorn (Größe, Konfliktrisiko auf fremden Seiten, kein Nutzen für ein Plugin ohne UI-Schwerpunkt).
|
||
|
||
```
|
||
wp-lit-mcp.php Plugin-Header, Bootstrap
|
||
src/
|
||
Core/
|
||
Plugin.php Start, Hooks, Abhängigkeitsprüfung
|
||
IntegrationRegistry.php sammelt verfügbare Integrationen
|
||
AbilityRegistrar.php registriert Abilities + Kategorien, Server-Konfiguration
|
||
Access.php Rollen-Gate, Capability lit_mcp_use, App-Password-Scope-Filter
|
||
ToolResult.php einheitliche Rückmeldung
|
||
ToolError.php verwertbare Fehler
|
||
ChangeLog/ Tabelle, Repository, Cron-Bereinigung
|
||
Guides/ Guide-Loader, Server-Instructions, Prompts
|
||
Admin/ Einstellungsseite, Protokoll-Ansicht (Settings API, WP_List_Table)
|
||
Integrations/
|
||
Integration.php Interface: isAvailable(), abilities(), prompts()
|
||
(Sonderfälle innerhalb einer Integration: abilities() lässt nicht nutzbare Tools einfach weg)
|
||
WordPress/ Content, Schema, Status/Kopie, Revisionen, Menüs, Einstellungen
|
||
Media/ Medien-Tools, Verwendungssuche
|
||
Divi/
|
||
BlockTree/ Parser, Serializer, Node, Pfad-Adressierung (reines PHP)
|
||
Schema/ Modul-Katalog, Attributpfad-Validierung
|
||
Compose/ Kurzform → Blöcke, Platzhalter-Auflösung
|
||
Pages/ Seiten-Tools, Speicher-Pipeline
|
||
Library/ Library, globale Module, find_similar
|
||
ThemeBuilder/ Vorlagen, Zuweisungen, Dynamic Content
|
||
Design/ Farben, Variablen, Presets, Theme-Optionen, Snapshots
|
||
Pods/ Feld-Adapter für die Schema-Erkennung, Schreiben via Pods-API
|
||
docs/guides/*.md Anleitungen für lit/guide
|
||
tests/Unit, tests/Integration, tests/Fixtures
|
||
```
|
||
|
||
### 4.5 Rechte (dreistufig)
|
||
|
||
1. **Verbinden:** mcp-oauth-Autorisierung (jeder eingeloggte Benutzer).
|
||
2. **Nutzen:** Capability `lit_mcp_use` (nur freigegebene Rollen) – geprüft über Adapter-Filter und in jeder Ability.
|
||
3. **Handeln:** konkrete Prüfung pro Ability, z. B. `edit_post` für die Ziel-ID, `publish_post` fürs Veröffentlichen, `upload_files`, `edit_theme_options` für Divi-Designsystem und Menüs, `manage_options` für WP-Einstellungen, `edit_others_posts`, `edit_theme_options` und Divis Rollen-Recht „Theme Builder“ für den Theme Builder (Divi-Anforderung und Gate von Divis Theme-Builder-Seite; Etappe 3b), dazu `edit_post` je Vorlage/Layout; Vorlagen ohne `edit_post` antworten wie fehlende IDs, aktive davon erscheinen nur als Anzahl.
|
||
|
||
## 5. Divi-Kern
|
||
|
||
### 5.1 Grundidee
|
||
|
||
Seiten, Theme-Builder-Layouts (`et_header_layout`, `et_body_layout`, `et_footer_layout`) und Library-Einträge (`et_pb_layout`) speichern Block-Markup in `post_content`. Alle Divi-Bearbeitungstools arbeiten auf jeder dieser Post-Arten über die `post_id`.
|
||
|
||
### 5.2 BlockTree
|
||
|
||
- Parst `post_content` in einen Baum (auf Basis von `parse_blocks`, mit Sonderbehandlung für `divi/global-layout` und `globalModule`, die `parse_blocks` laut Divi-Code nicht korrekt verarbeitet).
|
||
- Serialisiert den Baum zurück; unveränderte Knoten werden aus ihrem Original-Markup übernommen.
|
||
- **Invariante:** Parse → Serialize ohne Änderung ergibt byte-identischen Inhalt. Fremde/unbekannte Blöcke bleiben unberührt. Ausnahme beim Speichern (nicht im BlockTree): Divi selbst normalisiert Seiten mit eigenen HTML-/Attribut-Feldern beim Speichern (`module.decoration.attributes`, `module.advanced.html` mit `htmlBefore`/`htmlAfter`/`elementType`) – Divi parst und serialisiert dann die ganze Seite neu, was nur Bytes ändert, die noch nicht in Divis `serialize_blocks()`-Form vorlagen; gemeldet als `CHANGED_ON_SAVE` (Ruling S7).
|
||
- Reines PHP ohne WordPress-Abhängigkeit (vollständig unit-testbar).
|
||
- Attributwerte mit `$variable(...)$` werden beim Serialisieren wie von Divi erwartet escaped (`"` → `"`).
|
||
- Umsetzung (D3): eigener Tokenizer mit dem Delimiter-Muster von `WP_Block_Parser` statt `parse_blocks()` – ohne WordPress testbar, jedes Byte zwischen den Delimitern bleibt erhalten. Knoten mit `globalModule`, `divi/global-layout` oder nicht dekodierbaren Attributen sind undurchsichtig: sie werden nicht betreten, nur als Ganzes verschoben, dupliziert oder gelöscht (bearbeitet werden globale Module seit Etappe 3a im Bibliothekseintrag, E2). Unbalanciertes Markup wird abgelehnt, nie repariert.
|
||
|
||
### 5.3 Adressierung und optimistische Sperre
|
||
|
||
- `lit/divi-outline` liefert den Baum mit Pfad-IDs (`s0`, `s0.r1`, `s0.r1.c0.m2`), Modultyp, Admin-Label, Textauszug und Preset-Namen.
|
||
- Jede Antwort enthält `tree_rev` = Hash des aktuellen `post_content` (Sperre der Divi-Werkzeuge) und `rev` = Sperre des ganzen Eintrags (`Rev::ofPost`, dieselbe wie bei `lit/content-get` und `lit/content-update`; Ruling P16).
|
||
- Jedes Divi-Schreib-Tool verlangt `tree_rev`. Weicht sie ab, wird abgelehnt (`rev_mismatch`), nichts geschrieben; der Client liest neu. Pfad-IDs gelten immer relativ zu einer `tree_rev`. Jede Schreib-Antwort liefert die neue `tree_rev` und die neuen Pfad-IDs der geänderten Knoten.
|
||
- Buchstaben der Pfad-IDs: `s` Abschnitt, `r` Zeile (auch `row-inner`), `c` Spalte (auch `column-inner`), `m` Modul (auch Kind-Module und Gruppen), `g` globales Modul bzw. globales Layout, `x` fremder Block (z. B. Block-Editor); gezählt wird je Buchstabe innerhalb des Elternknotens, `divi/placeholder` ist transparent.
|
||
|
||
### 5.4 Modulbeschreibung
|
||
|
||
**Kurzform** (kuratiertes Mapping für ~20 Module: Text, Heading, Button, Image, Blurb, CTA, Icon, Divider, Testimonial, Team Member, Accordion(+Item), Tabs(+Tab), Toggle, Gallery, Slider(+Slide), Contact Form(+Field), Map, Video, Number Counter, Social Media Follow(+Item), Icon List(+Item)):
|
||
|
||
```json
|
||
{ "type": "button", "text": "Termin buchen", "url": "/kontakt",
|
||
"preset": "CTA primär", "label": "Hero – Button" }
|
||
```
|
||
|
||
**Vollform** (alle Module, alle Einstellungen, Divis Attributpfade):
|
||
|
||
```json
|
||
{ "type": "heading",
|
||
"attrs": { "title.decoration.font.font": {
|
||
"desktop": { "color": "{{color:primary}}" },
|
||
"phone": { "size": "28px" } } } }
|
||
```
|
||
|
||
- Attributpfade werden gegen den Katalog (`get_all_core_modules_metadata`) validiert; unbekannte Pfade → `invalid_attr_path` mit Vorschlägen.
|
||
- Responsive-Werte über die Schlüssel `desktop` / `tablet` / `phone` (optional `hover`, `sticky`, wo das Modul es unterstützt).
|
||
- Kurz- und Vollform sind kombinierbar (Kurzform + zusätzliche `attrs`).
|
||
|
||
**Struktur:** Abschnitt → Zeilen (`"columns": "1_3,2_3"`) → Spalten → Module. Spezialabschnitte (fullwidth) über `"section_type"`.
|
||
|
||
**Platzhalter** (vom Plugin in Divis `$variable(...)$`-Syntax übersetzt):
|
||
|
||
| Platzhalter | Ergebnis |
|
||
|---|---|
|
||
| `{{color:primary}}`, `{{color:<Name>}}` | globale Farbe (`gcid-…`; Aliase primary/secondary/heading/body/link) |
|
||
| `{{var:<Name>}}` | globale Variable (`gvid-…`), Suche über Label |
|
||
| `{{font:heading}}`, `{{font:body}}` | Theme-Schriften (`--et_global_heading_font` / `--et_global_body_font`) |
|
||
| `{{post:title}}`, `{{post:excerpt}}`, `{{post:date}}`, … | Dynamic Content (Post-Daten) |
|
||
| `{{field:<meta_key>}}` | Dynamic Content `custom_meta_<meta_key>` (Pods/Meta) |
|
||
| `{{link:<ID>}}` | interner Link: Dynamic Content `post_link_url_<Typ>` mit `post_id` (nur Link-Felder; Ziel muss für den Benutzer lesbar sein, nicht im Papierkorb, kein automatischer Entwurf, kein Anhang; Entwürfe/private Ziele rendert Divi als `?page_id=`; Etappe 3a, E13a) |
|
||
| `"preset": "<Name>"` | `modulePreset: ["<id>"]` |
|
||
|
||
Unbekannte Namen → Fehler mit Liste der vorhandenen.
|
||
|
||
### 5.5 Qualitätsregeln und Warnungen
|
||
|
||
Jede Schreib-Rückmeldung enthält Warnungen zu:
|
||
- festen Farben/Schriften, wenn eine passende Variable existiert,
|
||
- Bildern ohne Alt-Text,
|
||
- leeren Modulen,
|
||
- Sprüngen in der Überschriftenhierarchie,
|
||
- Verwendung des Code-Moduls,
|
||
- ähnlichen, bereits existierenden Abschnitten (Hinweis auf `lit-library-insert` und `lit/library-find-similar`) – verglichen wird nur ein neu eingefügter Abschnitt mit den Abschnitten der Divi-Bibliothek (Struktur-Fingerabdruck, höchstens 200 Einträge, je Anfrage einmal gelesen), nur mit Bibliothekszugang (Gruppe nicht deaktiviert, Recht „Divi-Bibliothek“; P13) und nicht bei `lit/library-insert` selbst (Etappe 3b, E11).
|
||
|
||
Kurzform setzt Admin-Labels automatisch (`<Abschnitt> – <Modul>`), sofern nicht angegeben.
|
||
|
||
### 5.6 Speicher-Pipeline
|
||
|
||
1. Rechte prüfen (`edit_post`), `tree_rev` prüfen.
|
||
2. Änderung auf dem BlockTree ausführen, validieren (alles oder nichts).
|
||
3. Serialisieren, `wp_slash()`, `wp_update_post()` – Status unverändert, vorher Wiederherstellungspunkt (Revision). Für Benutzer ohne `unfiltered_html` wird kses für genau diesen Aufruf abgeschaltet: `filter_block_content()` würde sonst jeden unveränderten Block neu serialisieren (Byte-Identität, globale Module; in DDEV nachgewiesen). Das ist nur vertretbar, weil keine client-gelieferte Zeichenkette ungeprüft in `post_content` gelangt (D7): Klartext-Werte werden je Feldtyp bereinigt (Text: `sanitize_text_field`; Rich-Text: `wp_kses_post`, abhängig von `unfiltered_html`; URLs: `esc_url_raw`, geroutet über die Attribut-Metadaten des Katalogs, ersatzweise über den Schlüsselnamen). Werte mit `$variable(...)$` – ob aus Platzhaltern erzeugt oder unverändert aus `lit/divi-node-get` zurückgegeben – werden geparst, streng geprüft (zulässiger Typ, existierende gcid-/gvid-/Dynamic-Content-Quellennamen, whitelisted Settings-Schlüssel, String-Settings bereinigt) und vom Plugin neu serialisiert; alles andere wird mit `validation_failed` abgelehnt. Ob Divi das Dynamic-Content-`before`/`after` bei der Ausgabe selbst escaped, wird in Etappe 2b im Divi-Quellcode verifiziert; die Bereinigung gilt unabhängig davon (Verteidigung in der Tiefe, R2).
|
||
4. Post-Meta `_et_pb_use_divi_5=on`, `_et_pb_use_builder=on` setzen (Seiten und Theme-Builder-Layouts; Bibliothekseinträge nicht).
|
||
5. `ET_Core_PageResource::remove_static_resources($post_id, 'all', true)`; bei globalen Library-Elementen und Theme-Builder-Änderungen `('all', 'all', true)` sowie `et_theme_builder_clear_wp_cache('all')`.
|
||
6. Protokolleintrag, `ToolResult` zurückgeben.
|
||
|
||
### 5.7 Tools
|
||
|
||
| Ability | Art | Beschreibung |
|
||
|---|---|---|
|
||
| `lit/divi-outline` | lesen | Baum mit IDs, Labels, Textauszügen, `rev` und `tree_rev` |
|
||
| `lit/divi-node-get` | lesen | vollständige Attribute eines Knotens (Vollform) |
|
||
| `lit/divi-catalog` | lesen | Module, Kurzform-Felder, wichtige Attributpfade; Detail pro Modul |
|
||
| `lit/divi-design-system` | lesen | Farben, Variablen, Presets, Theme-Schriften/-Größen |
|
||
| `lit/divi-dynamic-sources` | lesen | verfügbare Dynamic-Content-Quellen für einen Post-Typ (über `DynamicContentOptions::get_options` mit einem Beispiel-Post des Typs) – Etappe 3a (E12, E14); nur textartige Felder (Antwort F4): Beziehungs-, Datei-, Tabellen- und unbekannte Felder stehen mit Grund unter `omitted`, Auswahlfelder liefern den gespeicherten Wert; Beispiel-Post nur einer, den der Benutzer bearbeiten darf |
|
||
| `lit/page-render-summary` | lesen | gerenderte Seite als strukturierter Auszug (Überschriften, Texte, Links, Bilder+Alt); Inhaltsbereich, im Prozess über `the_content` gerendert (ohne Header/Footer/Theme Builder); Teil der WordPress-Integration, funktioniert auch ohne Divi (D5) |
|
||
| `lit/divi-insert` | schreiben | Knoten (Kurz-/Vollform, auch ganze Abschnitte) an Position `parent`/`before`/`after` einfügen |
|
||
| `lit/divi-update` | schreiben | Werte setzen/entfernen (Kurz- oder Vollform) |
|
||
| `lit/divi-move` | schreiben | Knoten verschieben (auch zwischen Zeilen/Abschnitten) |
|
||
| `lit/divi-delete` | schreiben, destruktiv | Knoten entfernen |
|
||
| `lit/divi-duplicate-node` | schreiben | Knoten duplizieren |
|
||
| `lit/divi-replace-text` | schreiben | Text seitenübergreifend (je Inhaltstyp) ersetzen, `dry_run` (Standard `true`) liefert Treffer je Seite mit `tree_rev`; ausgeführt wird nur auf diesen `targets` mit `confirm: true`, jede Seite mit eigener Revision (D10) |
|
||
| `lit/library-list` | lesen | Einträge nach Typ (`layout_type`) und Scope, mit `cursor`; mit `id` Detail inkl. Knoten-Übersicht und betroffener Seiten (ersetzt `lit/library-get`, E9); nur Einträge mit `edit_post` |
|
||
| `lit/library-save` | schreiben | Knoten als Library-Eintrag speichern (normal oder global; global braucht Divis „Globale Bibliothekselemente bearbeiten“, P7); Knoten auf der Seite bleibt unverändert; StoredNodeGuard (E6) |
|
||
| `lit/library-insert` | schreiben | Library-Eintrag als Kopie oder globale Instanz im Format des Visual Builders (`localAttrs`-Schnappschuss, `globalParent`) einfügen; direkt |
|
||
| `lit/divi-node-copy` | schreiben | Knoten von Eintrag A nach Eintrag B kopieren (Seiten und Bibliothekseinträge; byte-gleich, `source_tree_rev` Pflicht, S7/S26-Prüfung E6) |
|
||
| `lit/library-make-global` | schreiben | Knoten in globales Modul umwandeln (alles oder nichts); optional gleichartige Vorkommen ersetzen: gleichartig = inhaltsgleich einschließlich aller Texte (Inhalts-Fingerabdruck und normalisierte Bytes), `library_id` + `targets`, Probelauf + `confirm`, P8a, Revision je Seite; Seite N scheitert → vorherige bleiben ersetzt, Fehler nennt geänderte/gescheiterte/unveränderte Seiten (E10). Nur Inhaltstypen `page` und `post` – keine Bibliothekseinträge, keine Theme-Builder-Layouts, auch nicht als Quelle; Knoten mit Verweis auf einen Eintrag (jede Schreibweise) werden kein globales Modul |
|
||
| `lit/library-find-similar` | lesen | ähnliche Abschnitte seitenübergreifend (Struktur-Fingerabdruck: Modultypen, Aufbau, Presets) und Inhalts-Fingerabdruck (`identical`); höchstens 200 Einträge je Aufruf, `cursor`, nur bearbeitbare Einträge, nie Bibliothekseinträge oder Theme-Builder-Layouts (E11) |
|
||
| `lit/tb-list` | lesen | Vorlagen, Bedingungen (Divis Beschriftungen, Objekte nur als ID), Layouts (`shared_with`), `template_rev`; `detached` = von einem veralteten Theme-Builder-Fenster entfernte Vorlagen; optional Divis Bedingungskatalog; nicht bearbeitbare Vorlagen fehlen, aktive nur als Anzahl |
|
||
| `lit/tb-create-template` | schreiben | Vorlage mit Header/Body/Footer-Layouts anlegen (`et_theme_builder_insert_layout`, `et_theme_builder_store_template`, Meta `_et_template`); immer deaktiviert (Antwort F1); je Bereich neu, global (Standardvorlage), leer oder ausgeblendet; alles oder nichts; abgelehnt, solange der Theme Builder einen Entwurf hat |
|
||
| `lit/tb-assign` | schreiben | Bedingungen (`_et_use_on`/`_et_exclude_from`, z. B. `singular:post_type:person:all`) setzen – nur Divis eigene, Objekte lesbar, Autoren nur mit `list_users`; aktive Vorlage nur nach Probelauf und `confirm`; `reattach` für vom Theme Builder entfernte Vorlagen (bleiben deaktiviert) |
|
||
| `lit/tb-activate` | schreiben | Vorlage aktivieren/deaktivieren – einzige Stelle, die eine Vorlage sichtbar macht; immer Probelauf, dann `confirm` (Antwort F1, Etappe 3b); Deaktivieren geht immer, auch bei Theme-Builder-Entwurf (mit Warnung) und im Papierkorb |
|
||
|
||
## 6. WordPress-Basis
|
||
|
||
### 6.1 Schema-Erkennung (`lit/content-types`)
|
||
|
||
- Post-Typen mit `show_ui`: Name, Labels, `supports`, hierarchisch, Divi-fähig, Anzahl.
|
||
- Taxonomien pro Typ.
|
||
- Felder pro Typ, zusammengeführt aus:
|
||
- `get_registered_meta_keys()` (Kern),
|
||
- **Pods-Adapter:** Feldtyp, Pflicht, Auswahlwerte, Beziehungsziel, Mehrfachwert (über Pods-API),
|
||
- gefundenen Meta-Schlüsseln (Stichprobe; `_`-Schlüssel ausgeblendet, sofern kein Adapter sie kennt).
|
||
- Status pro Feld: `writable`, `readonly`, `unknown` (Schreiben erlaubt, mit Warnung).
|
||
|
||
### 6.2 Content-Tools (jeder Post-Typ)
|
||
|
||
| Ability | Beschreibung |
|
||
|---|---|
|
||
| `lit/content-query` | Filter: Typ, Status, Suche, Taxonomie, Feldwert, Datum; Cursor-Paginierung |
|
||
| `lit/content-get` | Kerndaten, Terms, Felder, Beitragsbild; bei Divi-Inhalt Verweis auf `lit/divi-outline` |
|
||
| `lit/content-create` | neuer Eintrag, **Standard: Entwurf**; Felder gegen Schema validiert; optional Divi-Inhalt in Kurzform |
|
||
| `lit/content-update` | Kerndaten, Terms, Felder ändern (Status unverändert) |
|
||
| `lit/post-publish`, `lit/post-unpublish`, `lit/post-schedule` | Statuswechsel, explizit |
|
||
| `lit/post-duplicate` | Entwurfskopie inkl. Meta, Terms, Divi-Flags |
|
||
| `lit/post-replace-with-copy` | Inhalt/Meta/Terms der Kopie ins Original übernehmen (ID, URL, Menüeinträge bleiben); Original erhält vorher Revision; Kopie → Papierkorb |
|
||
| `lit/post-trash` | nur Papierkorb, nie endgültig löschen |
|
||
| `lit/revisions-list`, `lit/revision-restore` | Revisionen |
|
||
|
||
- Pods-Felder werden über die Pods-API geschrieben (Beziehungen, Caches), sonstige Felder über die Meta-API.
|
||
- Erweiterungspunkt `lit_mcp_after_save` (Action): Integrationen können abgeleitete Felder nachberechnen (z. B. falls The Events Calendar dies erfordert – Prüfung in Etappe 0).
|
||
|
||
### 6.3 Medien
|
||
|
||
| Ability | Beschreibung |
|
||
|---|---|
|
||
| `lit/media-search` | Text, MIME-Typ, Datum, `missing_alt`, `unused` |
|
||
| `lit/media-get` | Metadaten, Größen, URLs, Verwendungsorte |
|
||
| `lit/media-preview` | verkleinertes Bild als `ImageContent` (direktes Tool, kein `outputSchema`) |
|
||
| `lit/media-upload-from-url` | Import via `wp_safe_remote_get` (SSRF-Schutz), MIME-Whitelist, Größenlimit |
|
||
| `lit/media-upload` | Base64-Upload, Limit einstellbar (Standard 5 MB) |
|
||
| `lit/media-download` | Original oder Größe als eingebettete Ressource (Blob) |
|
||
| `lit/media-update` | Alt, Titel, Bildunterschrift, Beschreibung – auch Stapel |
|
||
| `lit/media-delete` | nur mit `confirm: true`; bei Verwendung abgelehnt außer `force: true` |
|
||
|
||
Verwendungssuche: Anhang-ID in Divi-Attributen, Beitragsbildern, Galerie-Feldern und Meta.
|
||
|
||
Divi-Bildmodule, Hintergründe und Galerien referenzieren Bilder per Anhang-ID (plus URL, wie Divi es speichert).
|
||
|
||
### 6.4 Menüs
|
||
|
||
`lit/menu-list`, `lit/menu-get` (Baum), `lit/menu-create`, `lit/menu-set-items` (deklarativer Gesamtbaum oder Einzeloperationen hinzufügen/verschieben/entfernen), `lit/menu-assign-location`.
|
||
|
||
### 6.5 WordPress-Einstellungen
|
||
|
||
`lit/wp-settings-get`, `lit/wp-settings-update` über Whitelist:
|
||
- Allgemein: `blogname`, `blogdescription`, `WPLANG`, `timezone_string`, `date_format`, `time_format`
|
||
- Lesen: `show_on_front`, `page_on_front`, `page_for_posts`, `posts_per_page`
|
||
- Diskussion: `default_comment_status`, `default_ping_status`
|
||
- Permalinks: `permalink_structure` (danach `flush_rewrite_rules()`)
|
||
- Website-Icon: `site_icon`
|
||
|
||
Gesperrt: `admin_email`, `users_can_register`, `default_role`, `siteurl`, `home`.
|
||
|
||
## 7. Divi-Designsystem und Theme-Optionen
|
||
|
||
| Ability | Beschreibung |
|
||
|---|---|
|
||
| `lit/divi-colors-set` | globale Farben anlegen/ändern inkl. der fünf Hauptfarben (über `GlobalData::set_global_colors`) |
|
||
| `lit/divi-variables-set` | Variablen (numbers, strings, images, links, fonts) über `GlobalData::set_global_variables` |
|
||
| `lit/divi-presets-set` | Modul- und Gruppen-Presets anlegen/ändern, per Name (über `GlobalPreset::save_data`) |
|
||
| `lit/divi-theme-options-get`, `lit/divi-theme-options-update` | Whitelist mit Typ und Beschreibung pro Feld (s. u.) |
|
||
| `lit/divi-design-snapshots`, `lit/divi-design-restore` | Snapshots auflisten und wiederherstellen |
|
||
| `lit/divi-font-upload-google` (Kann) | Google-Schrift (TTF) laden, über `FontsUtility::font_add` ablegen |
|
||
|
||
Theme-Options-Whitelist (Auszug, vollständige Liste in der Implementierung mit Typen):
|
||
- Schriften: `heading_font`, `body_font`, `heading_font_weight`, `body_font_weight`, `primary_nav_font`, `secondary_nav_font`, `all_buttons_font`
|
||
- Größen: `body_font_size`, `tablet_body_font_size`, `phone_body_font_size`, `body_header_size`, `tablet_header_font_size`, `phone_header_font_size`, `body_font_height`, `body_header_height`, `body_header_spacing`, `body_header_style`
|
||
- Layout: `content_width`, `gutter_width`, `section_padding`, `row_padding`
|
||
- Farben: `accent_color`, `secondary_accent_color`, `header_color`, `font_color`, `link_color`
|
||
- Buttons: `all_buttons_*` inkl. `*_hover`
|
||
- Logo: `divi_logo`
|
||
- SEO: `divi_seo_home_*`, `divi_seo_single_*`, `divi_seo_index_*`
|
||
|
||
Regeln:
|
||
- Schreiben ausschließlich über Divis eigene Funktionen; danach `ET_Core_PageResource::remove_static_resources('all', 'all', true)`.
|
||
- Vor jeder Änderung wird der betroffene Bereich (Farben, Variablen, Presets oder Theme-Optionen) als **Snapshot** gesichert (eigene Option, begrenzte Anzahl, Standard 20). Snapshot-ID im `ToolResult` und im Protokoll.
|
||
- Voraussetzung: `edit_theme_options`; für Variablen zusätzlich Divis Rollen-Recht `variables_manager`.
|
||
|
||
Ablauf „Corporate Design übernehmen“ (Prompt, §9.3): der KI-Assistent liest das CD im Chat → `lit/divi-design-system` → schlägt Zuordnung vor → nach Bestätigung Schreiben über die Tools oben.
|
||
|
||
## 8. Rückmeldung, Fehler, Protokoll, Einstellungen
|
||
|
||
### 8.1 ToolResult
|
||
|
||
```json
|
||
{ "ok": true,
|
||
"summary": "Button in 'Hero' aktualisiert",
|
||
"changed": [{ "id": "s0.r0.c0.m2", "type": "divi/button", "action": "updated", "label": "Hero – Button" }],
|
||
"outline": "…betroffener Abschnitt…",
|
||
"rev": "a1b2c3", "tree_rev": "d4e5f6",
|
||
"warnings": ["Feste Farbe #ff0000 – Variable 'Primär' ist ähnlich"],
|
||
"revision_id": 812, "snapshot_id": null, "log_id": 4711,
|
||
"preview_url": "…", "edit_url": "…&et_fb=1" }
|
||
```
|
||
|
||
Rückgabe als `structuredContent` plus kurze Text-Zusammenfassung. Listen immer mit `cursor`/`limit`.
|
||
|
||
### 8.2 Fehler
|
||
|
||
- Fachliche Fehler → Tool-Ergebnis mit `isError: true` und `{ code, message, hint, fields? }`. Codes: `rev_mismatch`, `invalid_attr_path`, `validation_failed`, `forbidden`, `not_found`, `in_use`, `confirm_required`, `unsupported`.
|
||
- Alles oder nichts pro Aufruf; Stapel-Tools melden Ergebnis pro Eintrag.
|
||
- Ausnahmen aus WordPress/Divi werden abgefangen, protokolliert (PHP-Error-Log) und neutral gemeldet (kein Stacktrace an den Client).
|
||
|
||
### 8.3 Änderungsprotokoll
|
||
|
||
- Tabelle `{prefix}lit_mcp_log`: `id`, `created_at`, `user_id`, `client` (Name aus OAuth), `ability`, `object_type`, `object_id`, `summary`, `revision_id`, `snapshot_id`, `result`.
|
||
- Keine Inhalte, nur Verweise.
|
||
- Aufbewahrung einstellbar (Standard 90 Tage), täglicher WP-Cron-Job, Button „Protokoll leeren“.
|
||
- Admin-Ansicht (`WP_List_Table`), filterbar, Links zu Revision/Wiederherstellen.
|
||
|
||
### 8.4 Einstellungsseite (Einstellungen → LIT MCP)
|
||
|
||
- **Verbindung:** Status Adapter/OAuth, MCP-Server-URL zum Kopieren, Site-Health-Test (Discovery-Dokumente erreichbar, 401 mit `WWW-Authenticate`).
|
||
- **Zugriff:** erlaubte Rollen (Standard: Administrator); aktive Verbindungen je Benutzer mit Widerruf (über die von mcp-oauth erzeugten Application Passwords).
|
||
- **Tools:** direkt / indirekt / deaktiviert je Ability. (Das Divi-Code-Modul ist immer erlaubt, nur nachrangig – keine Einstellung.)
|
||
- **Limits:** Upload-Größe, Protokoll-Aufbewahrung, Anzahl Snapshots.
|
||
- Umsetzung mit Settings API, ohne JS-Framework.
|
||
|
||
## 9. Anleitungen für den KI-Assistenten
|
||
|
||
### 9.1 Server-Instructions
|
||
|
||
Dynamisch pro Seite erzeugt (Server-Beschreibung → `instructions`), ca. 15 Zeilen:
|
||
- aktive Integrationen und Post-Typen,
|
||
- Kernregeln: vor dem Schreiben `lit/divi-outline` und `lit/divi-design-system` lesen; Variablen/Presets vor festen Werten; native Module vor Code-Modul; Status nie ändern ohne ausdrücklichen Wunsch; immer `rev` (bei Divi-Änderungen `tree_rev`) mitgeben,
|
||
- Verweis auf `lit/guide`.
|
||
- Etappe 3a: Zeile „Divi-Bibliothek: …“ (globale Module im Bibliothekseintrag ändern, Probelauf und `confirm: true`, Guide `divi-library`), nur wenn die Gruppe „Divi-Bibliothek“ aktiv und beschreibbar ist.
|
||
- Etappe 3b: Zeile „Divi Theme Builder: …“ (neue Vorlagen deaktiviert, Aktivieren nur mit `lit/tb-activate`, Guide `theme-builder`), nur bei aktiver, beschreibbarer Gruppe „Divi Theme Builder“.
|
||
|
||
### 9.2 `lit/guide(topic)`
|
||
|
||
Direktes Tool; Anleitungen als Markdown in `docs/guides/`, mit dem Plugin versioniert, per Filter `lit_mcp_guides` erweiterbar.
|
||
Themen: `overview`, `divi-structure`, `divi-shortform`, `divi-attrs`, `divi-placeholders`, `divi-design-system`, `divi-library`, `theme-builder`, `content-types`, `media`, `workflows`. Thema `all` liefert alle Themen in einem Aufruf (Etappe 3a).
|
||
|
||
### 9.3 MCP-Prompts
|
||
|
||
`corporate-design-uebernehmen`, `neue-website-aufsetzen`, `seite-pruefen`, `globale-module-vorschlagen`, `custom-post-type-vorlage`.
|
||
(Stand Etappe 3b: noch keine MCP-Prompts im Plugin; `globale-module-vorschlagen` steht als Ablauf im Guide `divi-library`, `custom-post-type-vorlage` im Guide `theme-builder`.)
|
||
|
||
## 10. Sicherheit
|
||
|
||
- OAuth 2.1 mit PKCE über mcp-oauth; Tokens an den MCP-Server gebunden; kein Token-Passthrough an Dritte.
|
||
- Rollen-Gate + Rechteprüfung pro Ability (§4.5).
|
||
- App-Password-Scope auf die MCP-Route beschränkt (§4.2).
|
||
- Whitelists für WP-Einstellungen und Divi-Theme-Optionen.
|
||
- Uploads: `wp_safe_remote_get`, MIME-Whitelist, Größenlimits.
|
||
- Destruktive Aktionen: `confirm: true` erforderlich; kein endgültiges Löschen von Posts.
|
||
- Eingaben werden gegen JSON Schema und fachlich validiert; Bereinigung von Divi-Schreibwerten siehe §5.6/D7 (eine Quelle der Wahrheit): je Feldtyp (`sanitize_text_field`/`wp_kses_post`/`esc_url_raw`, URLs geroutet über Katalog-Metadaten bzw. Schlüsselname), `$variable(...)$`-Werte geparst/geprüft/neu serialisiert, sonst `validation_failed`.
|
||
- HTTPS erforderlich (Hinweis im Admin, wenn nicht aktiv).
|
||
|
||
## 11. MCP-Konformität
|
||
|
||
Referenz: https://modelcontextprotocol.io/specification
|
||
|
||
### 11.1 Zielversion
|
||
|
||
- **Sofort:** Protokollversion **2025-11-25** (vom Adapter unterstützt).
|
||
- **Später:** **2026-07-28** (zustandslos, `server/discover`, CIMD bevorzugt), sobald der Adapter sie unterstützt. Der Umstieg ist ein eigenes Arbeitspaket.
|
||
|
||
### 11.2 Verantwortung
|
||
|
||
| Bereich | Zuständig | Sicherung |
|
||
|---|---|---|
|
||
| JSON-RPC, Transport (Streamable HTTP), Versionsverhandlung, Header, Origin-Prüfung | MCP Adapter | Versionen fixiert, Konformitätstest pro Update |
|
||
| Autorisierung: OAuth 2.1, PKCE, RFC 9728/8414-Discovery, CIMD, Audience-Bindung | mcp-oauth | Etappe 0 prüft u. a. `WWW-Authenticate` bei 401, `resource`-Parameter (RFC 8707), `iss` (RFC 9207); Lücken upstream melden oder per Filter ergänzen |
|
||
| Tools, Prompts, Ergebnisse | WP-LIT-MCP | §11.3 |
|
||
|
||
### 11.3 Anforderungen an WP-LIT-MCP
|
||
|
||
- `inputSchema` für jedes Tool, `outputSchema` wo strukturiert (JSON Schema 2020-12); Ergebnisse als `structuredContent` + Text.
|
||
- Fachliche Fehler als `isError: true`, Protokollfehler als JSON-RPC-Fehler.
|
||
- Annotations korrekt: `readOnlyHint` (Lese-Tools), `destructiveHint` (Löschen, Ersetzen, Austausch), `idempotentHint`.
|
||
- Zustandslos: kein serverseitiger Sitzungszustand; `rev`/`tree_rev` als explizite, servererzeugte Handles in Tool-Argumenten.
|
||
- Deterministische Reihenfolge der Tool-Liste.
|
||
- Cursor-Paginierung für Listen.
|
||
- Tool-Namen spezifikationskonform und eindeutig (`lit-…`).
|
||
- Bestätigungen vorerst über `confirm: true`; Multi-Round-Trip-Elicitation erst, wenn Adapter und claude.ai sie unterstützen.
|
||
|
||
### 11.4 Konformitätstests
|
||
|
||
- MCP Inspector gegen den Server (Etappe 0 und bei jedem Update von Adapter/mcp-oauth).
|
||
- Automatischer Test je Ability: Ergebnis gegen `outputSchema` validiert.
|
||
- Ende-zu-Ende-Test mit echtem claude.ai-Connector.
|
||
|
||
## 12. Etappen
|
||
|
||
| Etappe | Inhalt | Ergebnis |
|
||
|---|---|---|
|
||
| **0 – Anbindung testen** | Plugin-Gerüst, Composer, mcp-oauth + Adapter, Rollen-Gate, App-Password-Scope-Filter, eigener Server mit direkten Tools, `lit/guide` (overview), ein Test-Tool; claude.ai-Connector über `ddev share`/Staging; MCP Inspector; Test: The Events Calendar-Eintrag generisch anlegen | Entscheidung: mcp-oauth bleibt oder Wechsel zu mcp-connect; Events-Erweiterungspunkt nötig ja/nein |
|
||
| **1 – WordPress-Basis** | Schema-Erkennung inkl. Pods, Content-Tools, Status/Kopie/Austausch, Revisionen, Medien, Menüs, WP-Einstellungen, `ToolResult`, Protokoll, Einstellungsseite | Seiten/Beiträge/Pods-Einträge pflegen, Medien verwalten, Websites mit Struktur und Menü aufsetzen |
|
||
| **2 – Divi-Seiten** | BlockTree, Katalog, Kurz-/Vollform, Platzhalter, Outline/Insert/Update/Move/Delete/Duplicate/Replace, Warnungen, `page-render-summary`, Divi-Guides (umgesetzt in 2a: lesen, 2b: schreiben) | Divi-Seiten mit dem KI-Assistenten bauen und pflegen |
|
||
| **3 – Library & Theme Builder** | Library-Tools, Node-Copy, Make-Global, Find-Similar, Theme-Builder-Tools, Dynamic Content | CPT-Vorlagen bauen, globale Module einführen (3a Bibliothek, 3b Theme Builder und Konsolidierung) |
|
||
| **4 – Designsystem** | Farben, Variablen, Presets, Theme-Optionen inkl. SEO, Snapshots, Prompts | Corporate Design in einem Rutsch übernehmen |
|
||
| **U – Auslieferung & Updates** (nach Etappe 1) | **OFFEN – bewusst noch nicht spezifiziert.** Bekannt: Build mit `composer install --no-dev` (~3,3 MB vendor), Updates nur anzeigen (manueller Klick), `plugin-update-checker`; Hosting (Gitea / GitHub / eigene Subdomain mit `update.json`) und Signaturprüfung werden später entschieden | – |
|
||
|
||
Kann-Kriterien nach Etappe 4 oder bei freier Kapazität.
|
||
|
||
- Divi-Bibliothek: Einträge (Module, Abschnitte, Layouts) per Tool **löschen** und **umbenennen**. Heute gibt es nur list/save/insert/make-global/find-similar. Löschen ist destruktiv und trifft globale Module samt Verwendungen, braucht also Probelauf und `confirm: true`.
|
||
|
||
## 13. Tests
|
||
|
||
- **Unit (PHPUnit, Brain Monkey, Mockery):** BlockTree (Roundtrip-Invariante), Kurzform → Markup, Attributpfad-Validierung, Platzhalter, Schema-Merge, Whitelists, ToolResult.
|
||
- **Fixtures:** echte, im Divi Builder gebaute Seiten (inkl. globaler Module, Presets, Variablen, Dynamic Content) als Roundtrip- und Änderungs-Testdaten.
|
||
- **Integration (DDEV, WP-CLI/REST):** jede Ability gegen die lokale Installation; gerenderte Ausgabe enthält `et_pb_*`-Klassen.
|
||
- **Konformität:** §11.4.
|
||
- **Manuelle Abnahme pro Etappe:** Bearbeitbarkeit im Visual Builder, claude.ai-Ablauf.
|
||
- Qualitätswerkzeuge: phpcs (WPCS), PHPCompatibilityWP.
|
||
|
||
## 14. Risiken
|
||
|
||
| Risiko | Gegenmaßnahme |
|
||
|---|---|
|
||
| mcp-oauth jung, Lücken (Rollen, Scope, direkte Tools) | eigene Absicherungen (§4.2), Etappe 0 als Entscheidungspunkt, Rückfall mcp-connect |
|
||
| Adapter 0.7 bricht API, rät vom Bundling ab | Versionen fixieren, Konformitätstest, Umstieg geplant |
|
||
| Divi ändert Speicherformat | Divi-eigene Metadaten/Funktionen nutzen, Fixtures, Tests je Divi-Update, `builderVersion` setzen |
|
||
| `.well-known`/POST auf `/wp-json/` durch Hoster/WAF blockiert | Site-Health-Test, Fehlersuche-Doku |
|
||
| Design-Qualität neuer Abschnitte ohne Vorlagen | Library-first-Arbeitsweise, Designsystem-Platzhalter, Guides, Warnungen |
|
||
| Parallele Bearbeitung im Builder | `tree_rev`-Sperre |
|
||
| Veraltetes Theme-Builder-Fenster speichert und entfernt neue Vorlagen | Ablehnung bei Theme-Builder-Entwurf, `detached` in `lit/tb-list`, `reattach` (deaktiviert); Warnung in jeder Anlege-Antwort (Etappe 3b) |
|
||
| Ungewöhnliche Schreibweisen globaler Verweise (P25), z. B. ein maskierter `divi/global-layout`-Block in einem Modulwert, den Divi in Shortcode-Modulen und WooCommerce-Textmodulen erneut auswertet | bekanntes Restrisiko, dokumentiert im Guide `divi-library`; braucht Bearbeitungsrechte auf der verweisenden Seite; `UsageMatcher` erkennt die übrigen Schreibweisen fail-closed |
|
||
| Datenformate Designsystem nur aus Code abgeleitet (lokal keine Daten) | vor Etappe 4 echte Daten im Builder anlegen und als Fixtures sichern |
|
||
|
||
## 15. Offene Punkte (in Etappen zu klären)
|
||
|
||
- Etappe 0: Funktioniert der Workaround für direkte Tools mit mcp-oauth stabil? Erfüllt mcp-oauth `iss`/`resource`-Anforderungen?
|
||
- Etappe 0: Erscheinen generisch angelegte The Events Calendar-Einträge korrekt?
|
||
- Etappe 2: erledigt – Kurzform-Felder aus Divis Conversion-Outlines abgeleitet (`ShortformMap`), gegen den Live-Katalog geprüft (`tests/Integration/divi-shortform-check.php`), dokumentiert im Guide `divi-shortform`.
|
||
- Etappe 4: Format der Presets/Variablen an echten Daten verifizieren.
|