idml-engine
Headless InDesign document composition via MCP: parse IDML templates, convert content to ICML stories, and compose complete newspaper IDML files conversationally.
README
idml-engine
Headless InDesign document composition. Parse a designer's IDML, convert editorial content to styled ICML stories, and compose complete newspaper IDML documents — no InDesign required at build time.
Built to replace two things at a working newspaper (The Wayland Post):
- DocsFlow (the commercial Google Docs → InDesign plugin) for one-way, batch content placement, and
- a Scripts-panel ExtendScript handoff that needed a human to click a button inside InDesign for every build.
An issue that took a staffed InDesign session now composes in about one second, headlessly, and the editor opens a finished IDML to refine.
How it works
content (Google Docs / DOCX / Markdown / HTML / JSON)
│ ingest.py — normalize to typed blocks (headline, byline, body, cutline…)
▼
typed blocks ──► story_converter.py ──► ICML stories (Pandoc, style-mapped)
│
▼
composer.py — "donor package" composition
• a real published-issue IDML (or purpose-built template) donates
Resources/ (all styles, fonts, colors) and MasterSpreads/ (the grid)
• generates fresh Spreads/ + Stories/: standing head, headline frame,
image grid with cutline captions, threaded body legs, bottom ad well
▼
complete .idml — opens in InDesign with the paper's exact design system
template_parser.py is the intelligence layer: it reads any IDML into a
manifest — style catalog, master geometry with computed column ranges, every
frame with threading, story-role classification (headline/body/caption/jump),
and DocsFlow live-links (story → Google Doc id, decoded merge base).
Quickstart
pip install idml-engine[all] # needs Pandoc on the machine for conversion
# understand a template or issue
idml-engine-parse issue.idml --summary
# convert a story
idml-engine-convert article.docx -o article.icml
# compose an issue (donor supplies styles/masters)
idml-engine-compose --donor published-issue.idml --manifest manifest.json --out new-issue.idml
Python API:
from idml_engine import composer, ingest, story_converter, template_parser
manifest = template_parser.parse_template("issue.idml")
blocks = ingest.from_file("article.docx")
story_converter.blocks_to_icml(blocks, "article.icml")
composer.compose("donor.idml", articles, "out.idml", ads=ads)
Layout priors — "trained" on your own paper
The composer doesn't guess layout metrics; it learns them from your archive.
layout_learner.py mines a corpus of published-issue IDMLs into
layout-priors.json — measured body-text density (chars/pt², drives column
capacity), headline-frame heights, caption heights, image sizes, ad-band
heights, and stories-per-page (quartile distributions). The composer
auto-loads priors (env IDML_ENGINE_PRIORS, or the file next to the
package) and falls back to model constants without them.
python -m idml_engine.layout_learner "path\to\published issues" -o layout-priors.json
At The Wayland Post: 27 issues mined → 729 body-story density samples, 937 headline frames, 1,200 placed images. The measured density (~31 chars/line) corrected the hand-tuned model's 40 by 25%.
MCP server (AI-drivable)
Every capability is exposed as MCP tools, so Claude (or any MCP client) can parse templates and compose issues conversationally:
claude mcp add idml-engine -- python -m idml_engine.mcp_server
Tools: parse_template, list_template_styles, get_template_geometry,
validate_template, ingest_content, convert_story, compose_issue,
compose_articles.
DocsBridge panel — the DocsFlow-style UI
uxp-panel/ is an InDesign UXP panel that replicates DocsFlow's workflow on
this engine: load an issue → per-article Place (drops the styled ICML
story and live-links it via storyTitle="docx:<google-doc-id>" — DocsFlow's
own convention) → Update re-places into the linked story's first frame,
preserving the frame chain. Status badges (placed / not placed / no copy)
survive save/reopen because the link rides in the document.
Backed by idml_engine/panel_service.py (localhost:3100 — manifest
listing, on-demand blocks→ICML, Drive refetch). Load the panel once via the
Adobe UXP Developer Tool (uxp-panel/manifest.json).
Commercial REST API
commercial/api_server.py wraps the same engine with Bearer-key auth and
per-key usage metering for hosted deployment (FastAPI):
uvicorn commercial.api_server:app --port 8080
# POST /api/compose /api/parse /api/convert (Authorization: Bearer <key>)
# GET /api/usage
Keys + metering are file-backed stubs; production wires them to Stripe
metered billing (see commercial/README.md).
Findings that made this possible
- ICML style mapping: Pandoc's ICML writer (stable since 2014) plus a
post-pass that strips its
" > Paragraph"style-name suffix yields stories whose styles match the template by exact name — InDesign adopts the template's formatting on Place. Trailing-space style names ("Byline ") survive round-trip. - Donor-package composition: a finished issue's IDML already carries the paper's whole design system. Cloning its resources and generating only spreads + stories produces documents InDesign opens cleanly.
- DocsFlow link format: DocsFlow stores its Google Doc live-links in
plain sight —
StoryTitle="docx:<file-id>"plus a merge-base blob that is just base64 → raw DEFLATE → JSON. A future release can read, preserve, and write these links for drop-in compatibility.
See docs/TEMPLATE-STRUCTURE.md for the full IDML anatomy notes.
Status
Alpha. Working end-to-end at one real newspaper. Not yet implemented: multi-article pages, jump lines ("Continued on…"), text wrap around images, DocsFlow-compatible link writing, IDML→PDF export (open in InDesign, or pair with InDesign Server / the UXP MCP bridge).
License
BSD-3-Clause (this library). The commercial API layer and hosted service are separate products built on top.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。