Skip to main content

mcp-docgen

A Markdown-driven Model Context Protocol (MCP) server to create, read, edit and convert Word (.docx), Excel (.xlsx), PowerPoint (.pptx), PDF and HTML documents.

Built entirely on mature, permissively-licensed Python libraries (python-docx, python-pptx, openpyxl, XlsxWriter, reportlab, pypdf, markdown-it-py, markdownify, beautifulsoup4) — no proprietary dependencies. MIT licensed.

Part of the Touka project: giving AI agents the ability to produce, read and edit real Office documents using only open-source building blocks.

Why

LLMs are great at producing Markdown. mcp-docgen converts Markdown to polished Office documents — and reads them back to Markdown — so an MCP-capable assistant (Claude Desktop, Touka, …) can run a full read → edit → write loop on real .docx / .xlsx / .pptx / .pdf / .html files, and convert between any of them.

Install & run

uvx mcp-docgen          # once published to PyPI
# or, from a local checkout:
uv sync && uv run mcp-docgen

The server speaks MCP over stdio.

MCP client configuration

{
  "mcpServers": {
    "docgen": {
      "command": "uvx",
      "args": ["mcp-docgen"],
      "env": { "MCP_DOCGEN_OUTPUT_DIR": "/absolute/path/to/workdir" }
    }
  }
}

From a local checkout, swap the command for:

{ "command": "uv", "args": ["run", "--directory", "/path/to/mcp-docgen", "mcp-docgen"] }

Tools

Create (Markdown / structured data → file)

Tool Input → Output
create_docx(markdown, output_path, title?) Markdown → Word
create_pptx(markdown, output_path, title?) Markdown → PowerPoint
create_pdf(markdown, output_path, title?) Markdown → PDF
create_html(markdown, output_path, title?) Markdown → HTML
create_xlsx(sheets, output_path) structured rows → Excel

Markdown features: headings, bold / italic / inline code, bullet & numbered lists (nested), tables, block quotes, fenced code blocks, horizontal rules.

PowerPoint slide convention: # Heading starts a new slide (its title); content below becomes bullet points; --- forces a slide break; title adds a leading title slide.

Excel sheets: [{ "name": str, "rows": [[cell, …], …], "header"?: bool }]. Cells may be strings / numbers / booleans / null; the first row is a bold, frozen header unless "header": false.

Read (file → Markdown / structured data)

Tool Returns
read_docx(input_path, base_dir?) { "markdown": … }
read_pptx(input_path, base_dir?) { "markdown": … }
read_xlsx(input_path, base_dir?) { "sheets": [{ "name", "rows" }] } (round-trips with create_xlsx)
read_pdf(input_path, base_dir?) { "num_pages", "pages": […], "text" }
read_html(input_path, base_dir?) { "markdown": … }

Reading docx/pptx to Markdown enables editing without in-place tools: read → edit the Markdown → create_* to regenerate.

Edit (in-place, preserving the rest)

Tool Effect
edit_xlsx(input_path, output_path, edits) set cells / append rows / add sheets, keeping other sheets, formulas & formatting
append_docx(input_path, output_path, markdown) append Markdown content to the end
append_pptx(input_path, output_path, markdown) append Markdown-derived slides to the end

edits = { "set_cells": [{"sheet","cell","value"}], "append_rows": [{"sheet","rows"}], "add_sheet": [{"name","rows"}] }.

PDF page operations

Tool Effect
pdf_merge(input_paths, output_path) concatenate PDFs in order
pdf_split(input_path, output_dir?) one file per page
pdf_extract(input_path, pages, output_path) extract a page subset (e.g. "1-3,5")

Note on PDF "editing": clean open-source PDF editing means page operations (merge / split / extract), not reflowing or replacing body text — PDFs are not designed for in-place text editing. To revise PDF content, regenerate with create_pdf.

Create/edit tools return {"path": <absolute path>}; pdf_split returns {"paths": […]}.

Convert (any format → any format)

Tool Effect
convert_document(input_path, output_path) convert between formats — both inferred from the file extensions

Conversions among html / docx / pptx read straight into a rich intermediate model, so colour, font, size, alignment, images and table cell spans survive — no lossy Markdown round-trip. xlsx → xlsx is lossless (styles, formulas, merges). Other pairings degrade gracefully. The result reports an honest fidelity plus a warnings list of what that particular pairing drops:

Fidelity When What it means
rich html · docx · pptx among themselves, and xlsx → xlsx styling preserved (colour / font / align / images / cell spans; formulas for xlsx)
clean md → a flow format structure preserved (Markdown carries no styling to begin with)
lossy any → pptx; xlsx ↔ documents slides split on # headings; only tables map to / from worksheets
text-only pdf as a source pypdf extracts plain text only; layout, styling and tables are lost

Honest limits: a PDF source is plain text (the open-source ceiling); Markdown can't carry styling, so any .md step is structure-only. A few write-side gaps remain (docx clickable hyperlinks and cell shading), and only inline-style HTML is read.

convert_document returns { "path", "source_format", "target_format", "fidelity", "warnings" }.

Directories & safety

  • Output files are written inside MCP_DOCGEN_OUTPUT_DIR (default ./out).
  • Input files (read / edit) are read from MCP_DOCGEN_INPUT_DIR (default = the output dir), so a read → edit → write loop shares one working directory.
  • Every tool accepts an optional base_dir to use as the root for that single call (it roots both reads and writes), e.g. a host that jails each call to one user's directory. When MCP_DOCGEN_INPUT_DIR is configured, a per-call base_dir may only narrow within it — one that escapes the configured boundary is rejected.
  • Every path is interpreted relative to its base; any path escaping it (via .. or an absolute path) is rejected, missing inputs and wrong suffixes raise errors.
  • The server makes no network calls and spawns no subprocesses.

Examples

uv run python examples/generate_samples.py   # create report.docx / review.pptx / sales.xlsx
uv run python examples/roundtrip_demo.py      # create → read → edit → PDF → convert round-trip

Development

uv sync
uv run pytest
uv run ruff check .

License

MIT © 2026 Touka Project — see LICENSE.

Powered by python-docx, python-pptx, openpyxl, XlsxWriter, reportlab and pypdf; Markdown parsing by markdown-it-py; HTML reading by markdownify and BeautifulSoup. All MIT/BSD licensed.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mcp_docgen-0.6.0.tar.gz (33.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mcp_docgen-0.6.0-py3-none-any.whl (42.2 kB view details)

Uploaded Python 3

File details

Details for the file mcp_docgen-0.6.0.tar.gz.

File metadata

  • Download URL: mcp_docgen-0.6.0.tar.gz
  • Upload date:
  • Size: 33.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.5 {"installer":{"name":"uv","version":"0.10.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for mcp_docgen-0.6.0.tar.gz
Algorithm Hash digest
SHA256 b2d1ae4826a13fe891bc97371eb6ccffbf60d012f975ccd5b46196c89bb31069
MD5 bfbc62613bc1f49dab47fbf6201046b7
BLAKE2b-256 c439914981ffd1b3ec867cfcd8b702052310925f06ddb7e62ba75caee3afa9dc

See more details on using hashes here.

File details

Details for the file mcp_docgen-0.6.0-py3-none-any.whl.

File metadata

  • Download URL: mcp_docgen-0.6.0-py3-none-any.whl
  • Upload date:
  • Size: 42.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.5 {"installer":{"name":"uv","version":"0.10.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for mcp_docgen-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 fdf37a1beb0b23cf58bfd477896fd19e9c7e94bf79e39775277d319f46ee197c
MD5 a3778ded1e635eca2252ddc362da3f16
BLAKE2b-256 2cc5e5784a55277515f725c8f62c31edacce982ec91a3c6086f081279d74bd65

See more details on using hashes here.

Release history Release notifications | RSS feed

0.8.0

2 files

0.7.0

2 files

This release

0.6.0 This release

2 files

0.4.0

2 files

0.2.0

2 files

0.1.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page