docx-harness
v0.1.2
Published
Verified .docx generation for AI agents: structured spec -> compiler -> validator -> render loop. Ships as an MCP server and an agent skill.
Maintainers
Readme
docx-harness
Verified .docx generation for AI agents. The model writes a structured JSON spec — never raw OOXML or python-docx code — and the harness compiles it, validates it against schema + known-footgun rules, and renders page images the agent can look at. That loop (spec → compile → validate → render → fix) is what turns one-shot blind generation into self-correcting document production.
Ships two surfaces over one engine:
- Agent skill (
skill/SKILL.md) — drop-in for Claude Code / Codex. - MCP server (
mcp/server.js) — four tools for n8n, Claude Desktop, or any MCP client.
Model emits structured spec (JSON)
│
▼
Compiler builds .docx ← deterministic, footgun constants are compiler-owned
│
▼
Validator checks it ← XML well-formedness + rules R1–R7
│
▼
Renderer → page images ← the model's "eyes" (soffice → pdftoppm)
│
▼
Verified .docxWhy a spec, not code
Hand-written OOXML / python-docx fails silently: WidthType.PERCENTAGE breaks Google Docs, ShadingType.SOLID renders solid black, custom heading styles skip the TOC without outlineLevel, visible text is fragmented across Word's <w:r> runs. None throw errors. Here the compiler owns those constants, so the spec can't express the broken states — and the validator catches the ones that slip through.
Install
npm install -g docx-harness # global CLI
# or locally:
npm install docx-harnessRender preview additionally needs LibreOffice (soffice) and poppler-utils (pdftoppm). The CLI prints platform install instructions if they're missing.
CLI
node bin/harness.js create spec.json -o out.docx # compile + validate
node bin/harness.js validate out.docx # schema + footgun report
node bin/harness.js render out.docx -o preview # page images for visual checkExit 0 = schema valid, 1 = invalid spec or schema errors.
MCP server
One-time setup — add to your AI tool's MCP config:
// Claude Code: .claude/mcp.json
// Claude Desktop: claude_desktop_config.json
// opencode: opencode.json → mcpServers
// Cursor: .cursor/mcp.json
{
"mcpServers": {
"docx-harness": {
"command": "npx",
"args": ["-y", "docx-harness", "mcp"]
}
}
}Or run directly:
docx-harness mcp # starts MCP stdio server
node mcp/server.js # same thing, from sourceWorkspace (where generated files live) defaults to .harness-workspace/, override with DOCX_HARNESS_WORKSPACE.
| Tool | What it does |
|---|---|
| create_docx(spec) | Compiles spec → .docx, validates, returns file_id + report |
| validate_docx(file_id) | Schema + footgun rules on a generated doc |
| render_preview(file_id) | Renders pages to JPEGs the agent can Read |
| get_footgun_report(file_id) | Human-readable rule hits + fixes |
No LibreOffice/poppler needed for create_docx and validate_docx. Only render_preview requires them (the CLI prints install instructions if missing).
Spec schema
See skill/SKILL.md for the full schema with examples. Core block types: heading, paragraph, list, table, image, pageBreak, toc, section (for mixed orientation/page overrides). Page setup: {size: LETTER|A4|..., orientation, margins}. Document defaults: {font, fontSize, lineSpacing}.
{ "page": { "size": "A4" },
"defaults": { "font": "Times New Roman", "fontSize": 12, "lineSpacing": 1.5 },
"content": [
{ "type": "heading", "text": "Report", "level": 1 },
{ "type": "toc" },
{ "type": "paragraph", "text": "Body." },
{ "type": "table", "columns": ["Item","Price"], "rows": [["Widget","10"]] }
] }Validator rules
| Rule | Detects |
|---|---|
| R1 | XML parts well-formed |
| R2 | Required parts present (document.xml, [Content_Types].xml, rels) |
| R3 | Relationship ids resolve |
| R4 | Literal \n in text |
| R5 | PERCENTAGE table widths (Google Docs breakage) |
| R6 | SOLID shading with auto fill (renders black) |
| R7 | Missing explicit page size |
The footgun corpus is meant to grow from real failures — each rule needs a reproduction fixture + detection predicate, see test/validate.test.js.
Development
npm testTests cover spec validation, compilation to valid docx, and every validator rule against hand-built broken-docx fixtures (R1–R7).
Honest limitations
- The visual check is LibreOffice rendering, close to but not identical to Microsoft Word. For Word-exact output requirements, say so.
- The validator is a footgun-rule engine, not a full OOXML XSD schema validator. Schema-valid ≠ visually-correct; that's why the render step exists.
edit_docx(editing existing files), tracked changes, PPTX/XLSX are not in v0.1.
License
MIT. The footgun rules in this repo were derived from our own reproduction fixtures, not copied from any proprietary skill material.
