--- name: wordcraft-mcp description: "Word-Dokumente (.docx, .odt, .md, PDF) mit dem WordCraft-MCP-Server erstellen, bearbeiten und prüfen (inkl. Nachverfolgung). Verwenden, wenn WordCraft-Werkzeuge verbunden sind oder der Nutzer WordCraft nennt; typisch für Angebote, Briefe, Betriebsanleitungen, Arbeitsanweisungen, 8D-Reports, Vorlagen. Nicht für eingebaute docx-Hilfen ohne WordCraft-Server." --- # Dokumente mit WordCraft (MCP) WordCraft ist ein Open-Source-Textverarbeitungsprogramm (Rust), das Word-Parität anstrebt. Alles ist ein Befehl mit stabiler ID; Ribbon, CLI und MCP rufen dieselben Befehle auf. ## Voraussetzung Die Werkzeuge `list_commands`, `execute`, `render_page` … müssen verbunden sein. Ihr Präfix hängt vom Client und vom Namen der Erweiterung bzw. des Servers ab (z. B. `mcp__…__WordCraft_for_Claude__list_commands`). Sind sie zurückgestellt, nach dem Werkzeugnamen ohne Präfix suchen und alle benötigten auf einmal laden. Fehlen sie, dem Nutzer sagen, dass der Server nicht verbunden ist (Einrichtung siehe README), statt auf ein anderes Programm auszuweichen. ## Freigaben Schutz durch Lese- und Schreib-Root (nicht die Freigabe-Dialoge). Lesen weit, Schreiben eng. Zusammenhängende Schritte immer als `batch`. Genau Dateipfade vom Nutzer erfragen statt zu raten. ## Tools | Tool | Zweck | |---|---| | `list_commands` | alle Befehle, mit `query` filtern | | `execute` | einen Befehl ausführen: `{command, params}` | | `batch` | mehrere Befehle in Reihenfolge (stoppt beim ersten Fehler) | | `new_document` | blank, sample, letter, resume, report | | `open_document` / `save_document` | docx, doc (nur öffnen), odt, rtf, html, md, tex, txt, json; speichern auch pdf, png | | `type_text` | an der Schreibmarke tippen (ersetzt Markierung) | | `select_text` | n-tes Vorkommen eines Textes markieren | | `get_text` / `inspect_document` | Dokument zurücklesen (Struktur als JSON, inkl. Kopf-/Fußzeilen unter `parts`) | | `render_page` | Seite als PNG | | `parity` | Funktionsabdeckung gegenüber Word | | `screenshot`, `click`, `key`, `ui_inspect` | nur mit verbundener Desktop-App | ## Arbeitsweise 1. **Befehls-IDs nie raten.** Vor jedem unbekannten Befehl `list_commands` mit `query` aufrufen (z. B. `table.`, `insert.`, `layout.`, `styles.`, `review`, `caret.`, `select.`). 2. **Alles im batch.** Auch Markieren: `select.text {text, occurrence?}`, `select.range {anchor: Pos, focus: Pos}`, `select.collapse`. `text.insert` ersetzt eine bestehende Markierung. Damit lassen sich ganze Dokumente in wenigen Aufrufen umbauen. 3. **Formatvorlagen statt Direktformatierung.** `styles.modify` an Normal/Heading1/Heading2/Title; Absätze nur per `para.set {"props":{"style":"Heading1"}}` zuweisen. 4. **Prüfen, bevor gespeichert wird.** `inspect_document`, `render_page`. 5. **Speichern** mit `save_document` in den Schreibordner; PDF per Endung `.pdf`. 6. **Rundreise prüfen:** gespeicherte Datei neu öffnen und erneut prüfen. ## Dateien finden und Zugriff Es gibt **keinen Befehl zum Auflisten von Ordnern**. `open_document` auf einen Pfad: - `os error 5 (Zugriff verweigert)` → Pfad ist ein existierender Ordner - `os error 2 (nicht gefunden)` → existiert nicht Liegt eine Datei **außerhalb des Lese-Ordners**, wird sie abgelehnt. Dann: (a) Nutzer bitten, den Lese-Ordner in den Einstellungen weiter zu fassen, oder (b) – wenn der Client Dateizugriff mit Nutzerfreigabe hat – die Datei mit Freigabe in den Arbeitsordner **kopieren** und nur mit der Kopie arbeiten. Original nie überschreiben. ## Neues Dokument – Grundeinrichtung (DE) `new_document blank` startet in **US-Letter** und englischer Sprache. Immer zuerst: ```json [{"command":"layout.size","params":{"name":"A4"}}, {"command":"layout.margins","params":{"top":70.87,"bottom":56.69,"left":70.87,"right":56.69}}, {"command":"review.language","params":{"lang":"de-DE","default":true}}, {"command":"styles.modify","params":{"style":"Normal","chr":{"font":"Arial","size":10.5,"lang":"de-DE"}}}] ``` Ohne de-DE zeigt `render_page` deutsche Wörter mit roten Wellenlinien. Text aufbauen: `para.set {style}` → `text.insert` → `text.newParagraph`, Stil für jeden Absatz explizit setzen. ## Fallen (im Test bestätigt) - **`format.set` ohne Markierung** wirkt nicht auf den gerade eingefügten Text, sondern auf den folgenden Absatz. Immer erst markieren (`select.text` / `select.range`), dann formatieren. - **Nummerierte Listen:** `para.numbering {"kind":"numbered"}` (auch `numberedParen`, `upperLetter`, `lowerLetter`, `lowerRoman`, `outline`). `para.bullets {"kind":"decimal"}` nimmt „decimal“ still als Aufzählungszeichen. Ende: `para.numbering {"off":true}`. Aufzählung: `para.bullets {"kind":"bullet"}` … `para.bullets {"off":true}`. - **`table.insertRowBelow`** übernimmt Ausrichtung und Fettdruck der Nachbarzeile nicht → danach `para.set {align}` und `format.set` setzen. - **Absätze mit gemischtem Format** (z. B. fettes Label + Tab + Wert): nicht den ganzen Absatz ersetzen (sonst übernimmt alles das Format des ersten Laufs), sondern nur den Wertteil per `select.text`. - **`inspect_document`:** `len` und alle `off` sind **UTF-8-Bytes** (ä/ö/ü/ß = 2). Für Textstellen mit Umlauten lieber `select.text` als selbst berechnete Offsets. - **Absätze löschen:** von **unten nach oben** arbeiten; `select.range` vom Ende (`off = len`) des letzten verbleibenden Absatzes bis zum Ende des letzten zu löschenden Absatzes, dann `text.delete`. Indizes danach neu berechnen. - **Hinweiskasten:** `para.set {"props":{"shading":[r,g,b],"borders":{"top":{…},"bottom":{…},"left":{…},"right":{…}}}}`; im nächsten Absatz zurücksetzen (`shading` weiß, `borders` style none). - **Abstand vor einem Absatz:** `para.set {"props":{"style":"Normal","spaceBefore":24}}`. - **Gelbe Platzhalter-Markierung** (`format.set {"props":{"highlight":"yellow"}}`) bleibt beim Überschreiben erhalten – Nutzer bei Vorlagen darauf hinweisen (Word: Strg+A → Texthervorhebung „Keine Farbe“). ## Kopf- und Fußzeile, Seitenzahl - Nach `insert.header` / `insert.footer` **sofort** `insert.closeHeader`, sonst landet folgender Text in der Kopf-/Fußzeile. - `insert.footer {"text": ...}` setzt die Schreibmarke **an den Anfang** des Textes. `preset: "blank"` legt „[Type here]“ an. Deshalb **ohne Parameter** öffnen und dann tippen: ```json [{"command":"insert.footer"}, {"command":"text.insert","params":{"text":"Seite "}}, {"command":"insert.pageField"}, {"command":"text.insert","params":{"text":" von "}}, {"command":"insert.field","params":{"instr":"NUMPAGES","result":"1"}}, {"command":"para.set","params":{"props":{"align":"center"}}}, {"command":"insert.closeHeader"}] ``` - Kontrolle: `inspect_document` → `parts[]` mit `kind: header/footer`. ## Tabellen - `insert.table {"rows":n,"cols":n,"style":"TableGrid"}` liefert `{"table":[index]}` = Blockindex. - Zellen **nicht per Tab** füllen, sondern anspringen: `caret.set {"pos":{"path":[tabelle, zeile, spalte, 0],"off":0,"story":"body"}}` dann `text.insert`. - Kopfzeile: Caret in Zeile 0 → `table.properties {"headerRow":true}`, `table.selectRow`, `table.shading {"color":"D9E2F3"}`, `format.set {"props":{"bold":true}}`. - `table.columnWidth` ändert **nur die Spalte der Schreibmarke**. Alle Spalten so setzen, dass die Summe = Satzspiegel (A4 mit 2,5/2 cm ≈ 467,7 pt). ## Überarbeitung fremder Dokumente (Nachverfolgung) 1. Original nur öffnen, nie darauf speichern; erste Speicherung sofort mit neuem Namen in den Schreibordner. 2. `file.setAuthor {"name":"…"}` und `review.trackChanges {"value": true}` – **immer mit value**. 3. Ersetzen: `select_text` → `type_text`. Ergebnis ist Einfügung + Löschung. 4. **`select_text` findet auch bereits nachverfolgt gelöschten Text.** Nach einer Ersetzung nicht erneut nach dem alten Wortlaut suchen. 5. Begründungen als Kommentar: Text markieren, `review.newComment {"text": ...}`. 6. Prüfen: `review.changes` und `review.comments` – auch nach dem Neuöffnen. ## Rezepte Platzhalter-Konvention: `{{Feldname}}` (Jinja2-kompatibel). ### 1. Neues Dokument A4, Ränder, de-DE, Formatvorlagen Title/Heading1/Heading2/Normal anpassen → Inhalt aufbauen → Kopfzeile → Fußzeile „Seite x von y“ → Tabelle mit Kopfzeile → nummerierte Liste (`para.numbering`) → ggf. Hinweiskasten → `render_page` → speichern. ### 2. Vorlage aus bestehendem Dokument Kopie im Lese-Ordner öffnen → `inspect_document` → Löschungen von unten nach oben → Ersetzungen per `select.range` (Absatzindex) bzw. `select.text` (Teilstücke) → Platzhalter `{{Feldname}}` gelb markieren → `get_text` prüfen, dass keine Ursprungsdaten (Namen, Adressen, Preise) übrig sind → unter neuem Namen speichern. ### 3. Vorlage füllen Vorlage öffnen → Felder per `select.text "{{Feld}}"` + `text.insert` im batch ersetzen → wiederholbare Listenpunkte ergänzen/löschen → Markierung entfernen → `get_text` auf `{{` prüfen → rendern → unter neuem Namen speichern (.docx + .pdf). ## Abschlussprüfung - Alle Seiten mit `render_page` ansehen; Seitenzahl plausibel. - Bei Vorlagen/gefüllten Dokumenten: `get_text` auf `{{` bzw. Altdaten prüfen. - Gespeicherte Datei neu öffnen und kurz gegenlesen. - Pfad dem Nutzer nennen. ## Datenschutz - Grün: allgemeine/technische Inhalte ohne Kundenbezug. - Gelb: Projekt-/Geschäftsinfos, Preise (oft vertraulich) nur nach Abwägung oder anonymisiert. - Rot: personenbezogene Daten (Ansprechpartner, E-Mail, Telefon) und NDA-Inhalte nicht in die Cloud-KI. - Vorlagen aus **geschwärzten** Kopien erstellen; im Freitext Platzhalter statt echter Namen verwenden. ## Eigenschaften (Kurzreferenz) Längen in Punkt, Farben als `"#RRGGBB"`, `[r,g,b]` oder `{"Rgb":[r,g,b]}`; bei Tabellenbefehlen `"RRGGBB"` ohne #. Unbekannte Feldnamen werden **still ignoriert**. - Zeichen (`format.set {"props": …}`): `font`, `size`, `bold`, `italic`, `underline`, `color`, `highlight`, `vertAlign`, `lang`, `link` - Absatz (`para.set {"props": …}`): `style`, `align`, `indentLeft`, `indentFirst`, `spaceBefore`, `spaceAfter`, `lineSpacing` (`{"rule":"multiple","value":1.15}`), `keepNext`, `keepLines`, `pageBreakBefore`, `outlineLevel`, `numbering`, `tabs`, `borders`, `shading` ## Renderer-Grenzen (0.8.0) - mehrzeilige Zellen in dunkel hinterlegten Tabellenköpfen zeigen nur die letzte Zeile - Seitenzahlfelder in Fußzeilen importierter python-docx-Dokumente bleiben leer Bei Auffälligkeiten erst das Original rendern und vergleichen. ## Word-Kompatibilität - Bei unbekannten Funktionen `parity` abfragen. - Original nie überschreiben. - Nutzer bitten, das Ergebnis in Word zu öffnen und gegen das Original zu prüfen (ggf. `review.compare`). ## Grenzen - Die Ordnerbeschränkung gilt nur headless; mit verbundener Desktop-App entfällt sie. - Befehle ohne Pfad wirken immer auf das zuletzt geöffnete Dokument. Vor dem Öffnen eines anderen Dokuments speichern.