feat(mcp-docugen): nuovo tool MCP document_to_pdf via Playwright/Chromium

Aggiunge la possibilità di convertire un documento Markdown in PDF
direttamente lato server, senza richiedere al chiamante di avere
md-to-pdf, pandoc o altri tool sull'host. Il PDF è restituito come
stringa base64 nella risposta JSON-RPC, pronto a essere salvato,
allegato o spedito al cliente.

- pdf_renderer.py: nuovo modulo che parsea il frontmatter YAML del
  Markdown (incluso il blocco pdf_options stile Puppeteer/md-to-pdf),
  rende il body in HTML via markdown-it-py (supporta tabelle e
  HTML inline) e produce il PDF tramite Chromium headless gestito
  da Playwright. Le pdf_options camelCase (printBackground,
  displayHeaderFooter, headerTemplate, ...) vengono tradotte negli
  argomenti snake_case di page.pdf().
- mcp_tools.py: nuovo tool `document_to_pdf(markdown)` che ritorna
  `{pdf_b64, size_bytes}`; `document_generate` esteso con il
  parametro `output_format ∈ {md, pdf, both}` per emettere il PDF
  contestualmente alla generazione del Markdown.
- pyproject.toml + uv.lock: aggiunte le dipendenze playwright>=1.48
  e markdown-it-py[plugins]>=3.0.
- mcp-docugen.Dockerfile: nuova fase di runtime che installa le
  librerie native richieste da Chromium (libnss3, libgbm1, ecc.) e
  scarica il binario Chromium di Playwright in /opt/ms-playwright.
- 7 nuovi test unit (83 totali) che coprono lo split del frontmatter,
  il rendering Markdown→HTML con tabelle, la traduzione delle
  pdf_options camelCase→snake_case e l'errore su YAML invalido. Il
  test E2E che richiede Chromium è marcato skip in unit; lo smoke
  via MCP conferma generazione PDF da 134 KB / 4 pagine.

README aggiornato con le tre strade di conversione (server-side,
client-side, bundling) e la stima del nuovo costo immagine.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-25 16:16:56 +02:00
parent b32669caa7
commit 725190010c
7 changed files with 392 additions and 7 deletions
+6 -4
View File
@@ -13,7 +13,7 @@ Due pezzi, stesso repo:
| Servizio | Stato | Funzione |
|---|---|---|
| `mcp-docugen` | Implementato, 76 test verde, deploy Docker via gateway Caddy (porta 8090), 6 tool MCP esposti, template seed versionati con auto-seed al boot, CSS Tielogic iniettato inline nel Markdown generato | Genera Markdown formale da template + LLM (OpenRouter). Vedi [`docs/mcp-docugen-design.md`](docs/mcp-docugen-design.md) + [`docs/mcp-docugen-implementation.md`](docs/mcp-docugen-implementation.md). |
| `mcp-docugen` | Implementato, 83 test verde, deploy Docker via gateway Caddy (porta 8090), **7 tool MCP** esposti (CRUD template + `document_generate` + `document_to_pdf`), template seed versionati, CSS Tielogic iniettato inline, **render PDF server-side** via Chromium/Playwright | Genera Markdown formale da template + LLM (OpenRouter) e converte in PDF. Vedi [`docs/mcp-docugen-design.md`](docs/mcp-docugen-design.md) + [`docs/mcp-docugen-implementation.md`](docs/mcp-docugen-implementation.md). |
| `mcp-convert` | Da progettare | Conversione Markdown → PDF / DOCX / HTML (pandoc/typst backend). |
| `mcp-inbox` | Da progettare | Ingest da Telegram (+ STT opzionale via Whisper) verso draft inbox consumati da Claude Code desktop. |
@@ -88,11 +88,13 @@ Template attualmente disponibili:
Per propagare modifiche al template versionato su un'installazione esistente: usare il tool MCP `template_update`, oppure rimuovere il template dal volume e fare restart del container.
Conversione Markdown→PDF (in attesa di `mcp-convert`): `md-to-pdf <file>.md`.
Conversione Markdown→PDF: tre strade, in ordine di comodità.
Il CSS Tielogic non viene referenziato come path esterno: il `Renderer` lo legge da `themes/tielogic.css` (copiato nell'immagine Docker in `/app/themes/`) e lo inietta come blocco `<style>` inline subito dopo il frontmatter del Markdown generato. Vantaggio: il file `.md` prodotto è **autocontenuto e portabile** — chi lo riceve può convertirlo in PDF stilizzato anche senza avere il CSS sull'host.
1. **Server-side via tool MCP** (il `mcp-docugen` espone `document_to_pdf` e accetta `output_format="pdf"` su `document_generate`). Il render avviene dentro al container Docker tramite Chromium headless gestito da Playwright; il PDF viene restituito come stringa base64 nella risposta JSON-RPC. Opzione consigliata: il chiamante (Claude Code, script, altri MCP) riceve direttamente il PDF e non deve avere alcun tool installato.
2. **Client-side con `md-to-pdf`** (Node) sull'host che ha generato il Markdown. Comando: `md-to-pdf <file>.md`.
3. **Script di bundling** per documenti `.md` legacy che ancora referenziano `stylesheet:` come path host: `scripts/bundle-css.py <file.md> [--in-place]` rimuove la riga e inietta il CSS inline.
Per documenti `.md` legacy che ancora referenziano `stylesheet:` come path host: usare `scripts/bundle-css.py <file.md> [--in-place]` per rimuovere la riga e iniettare il CSS inline.
Il CSS Tielogic non viene mai referenziato come path esterno nel Markdown prodotto dal servizio: il `Renderer` lo legge da `themes/tielogic.css` (copiato nell'immagine Docker in `/app/themes/`) e lo inietta come blocco `<style>` inline subito dopo il frontmatter. Il file `.md` risultante è quindi **autocontenuto e portabile** — chi lo riceve può convertirlo in PDF stilizzato anche senza avere il CSS sull'host.
## Remote