--- name: wordcraft-mcp description: Word-Dokumente (.docx, .odt, .md, PDF) über den WordCraft-MCP-Server erstellen, bearbeiten und prüfen, inkl. Nachverfolgung – mit erprobten Fallen aus WordCraft 0.8.0; statt wordcraft-dokumente verwenden. --- # 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 Der MCP-Server muss verbunden sein (Tools wie `execute`, `list_commands`, `render_page`). In claude.ai heißen sie `mcp__claude-device__lcl-wordcraft-*` und sind oft **deferred**: zuerst per ToolSearch laden (`select:mcp__claude-device__lcl-wordcraft-list_commands,...`, alle benötigten in einem Aufruf). Fehlen sie auch dann, dem Nutzer den Grund nennen statt auszuweichen. Einrichtung (Windows, Store-App): Eintrag "wordcraft" in `%LOCALAPPDATA%\Packages\Claude_pzs8sxrjxfjjc\LocalCache\Roaming\Claude\claude_desktop_config.json`: `wordcraft-cli.exe mcp --author Claude --automation-read-root --automation-write-root \claude_out` **Achtung:** Die Claude-App überschreibt diese Datei, wenn sie im laufenden Betrieb Einstellungen speichert. Fehlt der Eintrag, neu eintragen und die App sofort neu starten. Alternativ laufende App steuern (nicht auf Ordner beschränkt): `wordcraft --control 7981` und `wordcraft-cli mcp --connect 127.0.0.1:7981`. ## Freigaben Der eigentliche Schutz sind `--automation-read-root` und `--automation-write-root`, nicht die Freigabe-Dialoge. Empfohlene Tool-Berechtigungen im Connector: - Immer erlauben: `list_commands`, `get_text`, `inspect_document`, `render_page`, `open_document`, `select_text`, `new_document`, `parity`, `execute`, `batch`, `type_text` - Optional nachfragen: `save_document` (nur bedingt wirksam, da `execute` mit `file.saveAs`/`file.exportPdf` ebenfalls speichern kann) - Nie: `screenshot`, `click`, `key`, `ui_inspect` (nur für `--connect`, dort ohne Ordnergrenzen) „Immer erlauben“ ist nur sicher, solange die Config die Root-Argumente enthält und kein `--connect` verwendet. Nach jedem Neueintrag prüfen. Aufrufe sparen: genaue Dateipfade vom Nutzer erfragen statt zu raten, zusammenhängende Schritte immer als `batch`. ## 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 `--connect` | ## Arbeitsweise 1. **Befehls-IDs nie raten.** Vor jedem unbekannten Befehl `list_commands` mit `query` aufrufen (z. B. `table.`, `insert.`, `layout.`, `styles.`, `review`, `caret.`). Präfix mit Punkt filtert gezielter. 2. **Formatvorlagen statt Direktformatierung.** `styles.modify` an Normal/Heading1/Heading2/Title; Absätze nur per `para.set {"props":{"style":"Heading1"}}` zuweisen. 3. **Gebündelt arbeiten.** Zusammenhängende Schritte als `batch`. 4. **Prüfen, bevor gespeichert wird.** `inspect_document` für Inhalt/Struktur/Kopf-Fußzeilen, `render_page` für Layout. 5. **Speichern** mit `save_document` in den Schreibordner; PDF per Endung `.pdf`. 6. **Rundreise prüfen:** gespeicherte Datei neu öffnen und `inspect_document`/`render_page` bzw. `review.changes` erneut aufrufen. ## Dateien finden 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 Damit lassen sich Ordner bestätigen, aber keine Dateinamen ermitteln. Bei Unklarheit den Nutzer nach dem genauen Dateinamen fragen statt viele Namen zu raten. ## 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. Aufzählung: `para.bullets {"kind":"bullet"}` vor dem ersten Punkt, `para.bullets {"off":true}` danach (hinterlässt `numbering num 0` am nächsten Absatz – harmlos). ## 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 – nachfolgende Einfügungen landen davor. `preset: "blank"` legt einen Platzhalter „[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"}] ``` - Für reinen Text in der Kopfzeile ist `insert.header {"text": ...}` + `insert.closeHeader` in Ordnung. - Kontrolle: `inspect_document` → `parts[]` mit `kind: header/footer`. Fehler korrigieren mit `insert.removeFooter` und neu aufbauen. ## 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**; die Tabelle wird dadurch schmaler/breiter. Alle Spalten so setzen, dass die Summe = Satzspiegel (pageW − marginLeft − marginRight; A4 mit 2,5/2 cm ≈ 467,7 pt). ## Positionen - `off` in Positionen zählt **UTF-8-Bytes**, nicht Zeichen (ä/ö/ü/ß = 2, ▬ oder – = 3). Für Textstellen mit Umlauten lieber `select_text` als selbst berechnete Offsets. - Kommentaranker und andere Objekte belegen Positionen im Absatz; nach `review.newComment` Offsets neu ermitteln. ## Überarbeitung fremder Dokumente (Nachverfolgung) 1. Original nur öffnen, nie darauf speichern; erste Speicherung sofort mit neuem Namen in den Schreibordner. 2. `file.setAuthor {"name":"Claude"}` und `review.trackChanges {"value": true}` – **immer mit value**; ohne schaltet der Befehl um und kann die Nachverfolgung ausschalten. 3. Ersetzen: `select_text` → `type_text`. Ergebnis ist Einfügung + Löschung (ganzes Wort). 4. **`select_text` findet auch bereits nachverfolgt gelöschten Text.** Nach einer Ersetzung nicht erneut nach dem alten Wortlaut suchen; zum Markieren das neue Wort verwenden. 5. Begründungen als Kommentar: Text markieren, `review.newComment {"text": ...}`. 6. Prüfen: `review.changes` (Liste mit author, kind, text) und `review.comments` – auch nach dem Neuöffnen der gespeicherten Datei. ## 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` ## Renderer-Grenzen (0.8.0) Bekannte Darstellungsfehler von `render_page`, die **nicht** von eigenen Änderungen kommen: - 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, bevor man die eigene Änderung verdächtigt. ## 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 `--connect` ist die App nicht eingeschränkt. - Befehle ohne Pfad wirken immer auf das zuletzt geöffnete Dokument. Vor dem Öffnen eines anderen Dokuments speichern.