Commit Graph

5 Commits

Author SHA1 Message Date
Adriano b32669caa7 feat(mcp-docugen): Markdown autocontenuto con CSS Tielogic iniettato inline
Problema: i template puntavano a un path host hardcoded
(stylesheet: /home/adriano/.../themes/tielogic.css), quindi il file .md
generato non era portabile — su un'altra macchina md-to-pdf non trovava
il CSS e produceva PDF senza stile.

Soluzione: il Renderer legge il CSS da Settings.inline_stylesheet_path
(default /app/themes/tielogic.css nel container) e lo inietta come
blocco <style>...</style> subito dopo il frontmatter YAML del Markdown
restituito dall'LLM. Il file .md risultante è autocontenuto e portabile.

- renderer.py: nuovo arg inline_stylesheet_path + funzione
  _inject_inline_stylesheet (idempotente, gestisce Markdown senza
  frontmatter, no-op se CSS vuoto)
- config.py: Settings.inline_stylesheet_path: Path | None
- main.py: passa il path al Renderer
- mcp-docugen.Dockerfile: COPY themes ./themes nello stage builder per
  trasportare /app/themes/tielogic.css nell'immagine runtime
- templates_seed/{offerta,report-analisi}/template.md: rimossa la riga
  `stylesheet:` dal frontmatter di output + regola tassativa che vieta
  all'LLM di emettere blocchi <style> di sua iniziativa (evita
  conflitti di cascade visti in test)
- 4 nuovi test unit (76 totali): iniezione dopo frontmatter, prepend
  quando frontmatter assente, no-op CSS vuoto, integrazione full E2E
  via Renderer.generate

scripts/bundle-css.py: utility per fixare file .md legacy che
referenziavano stylesheet: come path host (sostituisce la riga con
<style> inline pescando il CSS dal repo)

README aggiornato con rationale e workflow.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 15:35:41 +02:00
Adriano 419c1acc7a feat(mcp-docugen): templates seed versionati + auto-seed all'avvio
- templates_seed/{offerta,report-analisi}/template.md: template Tielogic
  ufficiali versionati come sorgente di verità nel repo
- template_seed.py: copia idempotente seed→volume al boot, mai
  sovrascrive template esistenti (preserva edit fatti via MCP runtime)
- config.py: nuova Settings.templates_seed_dir
  (default /app/services/mcp-docugen/templates_seed)
- main.py: chiamata seed_templates() in build_app dopo TemplateStore init
- 4 nuovi test unit (idempotenza, skip se seed_dir mancante,
  no-op su entry non valide). 72 test verde totali

Workflow: edit del template nel repo → rebuild image → al primo boot
il volume vuoto riceve i template; se il template esiste già nel
volume (es. modificato dall'utente via tool MCP) viene preservato.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 12:19:29 +02:00
Adriano b4c2935c53 feat(mcp-docugen): tema CSS Tielogic, Swagger pubblico, README aggiornato
- themes/tielogic-devnotes.css: stile DEVNOTES + offerta Tielogic per md-to-pdf
  (cover bianca con logo+box FORNITORE/CLIENTE, tabelle finanziarie, badge,
  status-card, sezione ACCETTAZIONE con firme, A4 portrait)
- main.py: exempt_paths estesi a /docs /redoc /openapi.json (Swagger UI
  accessibile senza Bearer per esplorazione interattiva)
- README: stato mcp-docugen aggiornato, layout docker/gateway, setup completo
  con docker compose + smoke test

Template runtime (offerta, report-analisi) vivono nel volume Docker
docugen-data, non versionati nel repo.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 12:16:41 +02:00
Adriano 494a95d80c fix(mcp-docugen): mount FastMCP a root + lifespan session_manager.run()
- streamable_http_app() espone /mcp internamente; mount a root evita doppio prefisso.
- mcp.session_manager.run() integrato nel lifespan FastAPI: l'app mounted non
  riceve automaticamente il proprio lifespan -> la task group streamable-http
  non veniva inizializzata e le richieste MCP fallivano con RuntimeError.

Smoke test end-to-end via gateway Caddy (porta 8090):
- MCP initialize handshake OK
- tools/list espone 6 tool corretti
- template_create + template_list: round-trip con persistenza su volume
- document_generate propaga LLMAuthError come MCP isError:true
- Registrato in claude mcp list: ✓ Connected

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 12:42:00 +02:00
Adriano e8705dcd0b feat(mcp-docugen): Task 7-10 renderer, http_routes, mcp_tools, main bootstrap
- Renderer: orchestratore generate() — validazione strict variabili,
  materializzazione image vars come asset effimeri su disco + URL rewrite,
  asset paths template da ./assets/X -> {PUBLIC_BASE_URL}/assets/<t>/X,
  integrazione LLM error -> record success=0
- FastAPI sub-app: GET /health (no auth), /assets/{t}/{f} (auth+traversal check),
  /generated/{gen_id}/{f} (410 su scaduto o mancante)
- FastMCP server con 6 tool: template_create/update/delete/list/get,
  document_generate. Tools esposti anche via mcp.tools dict per test.
- main.build_app() compone http_app + FastMCP mount su /mcp + auth middleware
  + lifespan cleanup task TTL (24h). run() entry point per script console.

68 test passed. Build Docker arca-mcp-docugen:dev verificata,
/health endpoint risponde correttamente nel container.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 12:27:16 +02:00