Skip to main content
Glama
launchapp-dev

animus-document-engine

README.md
# animus-document-engine

An **MCP (stdio) service** that renders, parses, converts, and edits Office
documents — **Excel (.xlsx), PowerPoint (.pptx), Word (.docx)** — from a
structured JSON **spec**. It is identity-free and stateless: it never touches
subjects, S3, or users. The [animus-launchapp](https://github.com/launchapp-dev/animus-launchapp)
portal orchestrates it (storage + scoping + subjects); this engine is the reusable
rendering core.

Part of **REQUIREMENT-053** — Documents as subjects.

## Why a spec

The **spec is the source of truth**. An AI authors a spec (not raw OOXML); a
deterministic renderer turns it into a real file. Editing = mutate the spec and
re-render — lossless, reviewable, and diffable. Binary payloads cross the MCP
boundary as base64.

## Tools

| Tool | In | Out |
|------|-----|-----|
| `render_document` | `format`, `spec` | base64 OOXML bytes |
| `parse_document` | `format`, `bytes_base64` | spec (**xlsx only** in v1) |
| `apply_edits` | `format`, `spec`, `ops[]` | edited, re-validated spec |
| `convert_document` | `bytes_base64`, `to` | base64 converted bytes (e.g. `pdf`) |
| `preview_document` | `bytes_base64`, `kind` (`pdf`\|`png`), `page` | base64 PDF or PNG thumbnail |

`convert_document` / `preview_document` use **LibreOffice compiled to WebAssembly**
(`@matbee/libreoffice-converter`) — no native `soffice` needed. The ~112 MB WASM
lives in this service, never in the portal image.

## Spec shapes (v1)

```jsonc
// xlsx
{ "sheets": [ { "name": "Revenue",
                "columns": [ { "header": "Month" }, { "header": "USD" } ],
                "rows": [ ["Jul", 1200], ["Aug", 1500] ] } ] }

// pptx
{ "title": "Kickoff",
  "slides": [ { "title": "Agenda", "bullets": ["Scope", "Timeline"] },
              { "title": "Next", "body": "…", "notes": "speaker note" } ] }

// docx
{ "title": "Spec",
  "blocks": [ { "type": "heading", "level": 1, "text": "Overview" },
              { "type": "paragraph", "text": "…" },
              { "type": "bullets", "items": ["a", "b"] },
              { "type": "table", "rows": [["a","b"],["c","d"]] } ] }
```

`apply_edits` ops: `{op:"set",path,value}`, `{op:"append",target,value}`,
`{op:"remove",target,index}`, `{op:"replace",value}` (`target` = `sheets`\|`slides`\|`blocks`).

## Run

```bash
npm install
npm run build
node dist/index.js        # MCP stdio server
```

Wire it into an Animus workflow phase (or any MCP client) as a stdio server:

```jsonc
{ "mcpServers": { "document-engine": { "command": "node", "args": ["dist/index.js"] } } }
```

## Dev

```bash
npm run dev        # tsx watch (stdio server)
npm run typecheck  # tsc --noEmit
npm run smoke      # render all 3 formats + xlsx parse/edit round-trip
tsx scripts/mcp-smoke.ts   # spawn the built server, call tools over MCP
```

## Scope (v1) & roadmap

- **Generate** all three formats — solid (pptxgenjs / docx / exceljs).
- **Parse** — xlsx (data + headers). **pptx/docx in-place parsing is DEFERRED** to
  a future Python worker (python-pptx / python-docx are the only libraries that
  faithfully round-trip arbitrary decks/docs); the engine errors loudly rather than
  silently dropping content.
- **Convert/preview** — via LibreOffice-WASM.

TDQS

A4/5.0

Scored across 5 tools

Disambiguation5/5

Each tool targets a distinct operation: editing a spec, converting format, parsing, previewing, and rendering. No overlap or ambiguity.

Naming Consistency4/5

Four tools follow a consistent 'verb_document' pattern, but 'apply_edits' breaks the pattern slightly. Still all are verb_noun and clear.

Tool Count5/5

With 5 tools, the set is well-scoped for a document engine covering editing, conversion, parsing, preview, and rendering without bloat.

Completeness4/5

Core workflows are covered: create (render from spec), edit (apply_edits), convert, parse, preview. Minor gap: no tool to initialize a new spec, but agent can write one directly.