Convert QMD/Markdown files to editable PowerPoint presentations
Project description
qmd_to_pptx
A Python library that converts QMD (Quarto Markdown) or Markdown files into editable PowerPoint (PPTX) presentations. It can be used directly as a Python library, or launched as an MCP server to be called from AI agents.
日本語版: README_ja.md
Table of Contents
- Installation
- Full Feature Demo
- Supported Features
- Usage as a Library
- Usage as an MCP Server
- Template Feature
- QMD Syntax Reference
Installation
Install using uv:
uv pip install -e .
Python 3.11 or later is required.
Full Feature Demo
tests/demo_full.qmd in the repository is a demo file covering all supported features.
Run the following command to generate demo_full.pptx and verify the output:
uv run python -c "from qmd_to_pptx import render; render('tests/demo_full.qmd', 'demo_full.pptx')"
Open demo_full.pptx in PowerPoint or a compatible application to review the result.
Supported Features
| Feature | Syntax |
|---|---|
| Slide split | ## heading (H2) or --- horizontal rule |
| Section slide | # heading (H1) |
| Text / paragraphs | Standard Markdown paragraphs |
| Unordered / ordered lists | - / 1. |
| Incremental list | ::: {.incremental} block |
| Table | | col1 | col2 | format |
| Code block | Triple backtick fences |
| Inline math | $...$ |
| Block math | $$...$$ |
| Mermaid diagram (standard) | ```mermaid code block |
| Mermaid diagram (Quarto native) | ```{mermaid} code block |
| Two-column layout | :::: {.columns} / ::: {.column} |
| Speaker notes | ::: {.notes} block |
| Template specification | YAML front matter reference-doc field |
Usage as a Library
Processing Flow
flowchart LR
A[QMD/Markdown file\nor text string] --> B[render function]
B --> C[PPTX file]
D[Template PPTX\noptional] --> B
Passing a File Path
Pass a file path string as the first argument of render() to read and convert that file.
from qmd_to_pptx import render
render("slides.qmd", "output.pptx")
Specify a template PPTX file to inherit its design and theme:
render("slides.qmd", "output.pptx", reference_doc="template.pptx")
Passing a Text String
If the first argument is a string that does not exist as a path on the filesystem, it is processed directly as Markdown text.
from qmd_to_pptx import render
markdown_text = """---
title: My Presentation
---
## Slide 1
Content text
"""
render(markdown_text, "output.pptx")
render Function Signature
| Argument | Type | Description |
|---|---|---|
input |
str |
File path to a QMD/Markdown file, or a Markdown text string |
output |
str |
Output PPTX file path |
reference_doc |
str | None |
Path to a template PPTX file (optional) |
When reference_doc is provided as an argument, it takes precedence over the format.pptx.reference-doc field in the YAML front matter.
Usage as an MCP Server
Starting the Server
When launched as an MCP server, AI agents (such as Claude Desktop) can call the markdown_to_pptx tool to generate PPTX files.
stdio mode (default)
qmd-to-pptx-mcp
or
qmd-to-pptx-mcp --transport stdio
HTTP mode
qmd-to-pptx-mcp --transport http --host 0.0.0.0 --port 8000
Claude Desktop Configuration
Add the following to the Claude Desktop configuration file (claude_desktop_config.json):
{
"mcpServers": {
"qmd_to_pptx": {
"command": "qmd-to-pptx-mcp",
"args": []
}
}
}
To launch directly from the project directory using uv:
{
"mcpServers": {
"qmd_to_pptx": {
"command": "uv",
"args": ["run", "--directory", "/path/to/qmd_to_pptx", "qmd-to-pptx-mcp"]
}
}
}
Exposed Tools
The MCP server exposes the following two tools.
markdown_to_pptx
| Parameter | Type | Description |
|---|---|---|
content |
string |
QMD or Markdown text string (the text content itself, not a file path) |
output |
string |
Output PPTX file path (a path on the server-side filesystem) |
template_id |
string (optional) |
A template ID registered in config/templates.yaml |
Returns a string indicating the generated file path on success, or an error message on failure. If the specified template_id is not registered, an error message listing available IDs is returned.
list_templates
No parameters. Returns the list of template IDs and descriptions registered in config/templates.yaml. If no templates are registered, a message indicating that is returned.
Communication Flow
flowchart LR
A[AI Agent\ne.g. Claude] -- MCP protocol --> B[qmd-to-pptx-mcp\nserver]
B -- markdown_to_pptx tool --> C[render function]
C --> D[PPTX file\nsaved on server]
In stdio mode, stdout is exclusively used for MCP protocol communication. All logs are written to stderr.
Template Feature
By registering PPTX templates in advance, you can specify a template ID when calling the markdown_to_pptx tool via the MCP server.
templates.yaml Format
Register templates in config/templates.yaml using the following format:
templates:
corporate_standard:
path: /path/to/corporate_standard.pptx
description: "Corporate standard template"
dark_theme:
path: /path/to/dark_theme.pptx
description: "Dark theme template"
| Field | Required | Description |
|---|---|---|
templates.<id>.path |
Required | Absolute path to the PPTX template file |
templates.<id>.description |
Optional | Description of the template |
Template entries that do not have a path field are skipped when loading.
Configuration File Path Resolution
The template configuration file path is resolved in the following order:
flowchart TD
A{Is the environment variable\nQMD_TO_PPTX_TEMPLATES set?} -- Yes --> B[Use the path from the env var]
A -- No --> C[Use config/templates.yaml\nin the current directory]
B --> D{Does the file exist?}
C --> D
D -- Yes --> E[Load templates]
D -- No --> F[Run with empty registry\nno error]
Setting the QMD_TO_PPTX_TEMPLATES environment variable to the absolute path of a YAML file will use that path instead of the default.
Checking Registered Templates
Call the MCP tool list_templates to retrieve the list of templates currently registered in the configuration file.
Verifying Template Compatibility
Use check_template.py to verify that a PPTX template has the required slide layouts for qmd_to_pptx.
python check_template.py <template.pptx>
Example:
python check_template.py my_template.pptx
The script checks the following layouts. If a layout is missing or has incorrect placeholders, it provides instructions on how to fix it in PowerPoint.
| Layout Name | Usage | Required Placeholder idx |
|---|---|---|
Title Slide |
Cover slide | 0 (title), 1 (subtitle) |
Title and Content |
Body slides (most common) | 0 (title), 1 (content) |
Section Header |
Section separator (# heading) |
0 (title) |
Two Content |
Two-column layout | 0 (title), 1 (left), 2 (right) |
Comparison |
Two-column with figures/tables | 0 (title), 1 (left), 2 (right) |
Content with Caption |
Text + figure/table mixed slide | 0 (title), 1 (content/figure), 2 (caption/text) |
Blank |
Blank slide (--- separator) |
— |
If Two Content, Comparison, or Content with Caption are not found in the template, they fall back to Title and Content automatically. When a layout is present but missing required placeholders, or when the fallback chain is broken, the script reports it as NG and shows the exact fix needed.
============================================================
Template check: my_template.pptx
============================================================
[OK] The following layouts are configured correctly:
✓ "Title Slide" — Cover slide
...
[Action Required]
[NG] "Content with Caption" does not exist (no fallback available).
→ Add this layout in PowerPoint Slide Master view,
set its name to "Content with Caption",
and add placeholders: idx=0 (title), idx=1 (content/figure), idx=2 (caption/text).
============================================================
Overall: NG — Fixing the template is strongly recommended.
============================================================
QMD Syntax Reference
YAML Front Matter
Write the metadata and settings for the entire presentation at the top of the file.
---
title: My Presentation Title
author: Author Name
date: 2026-03-15
format:
pptx:
incremental: false
reference-doc: template.pptx
---
| Field | Description |
|---|---|
title |
Title displayed on the title slide |
author |
Author name displayed on the title slide |
date |
Date displayed on the title slide |
format.pptx.incremental |
When true, all lists are displayed incrementally |
format.pptx.reference-doc |
Path to the template PPTX file |
Slide Splitting
## headings act as slide separators. A --- horizontal rule generates a blank slide with no title. # headings are treated as section header slides.
Two-Column Layout
Placing two ::: {.column} blocks inside a :::: {.columns} block creates a two-column slide layout.
Speaker Notes
Text inside a ::: {.notes} block is stored as presenter notes in the speaker view. It is not displayed on the slide itself.
Incremental Lists
Lists inside a ::: {.incremental} block are displayed as PowerPoint animations, one item at a time.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file qmd_to_pptx-0.1.3.tar.gz.
File metadata
- Download URL: qmd_to_pptx-0.1.3.tar.gz
- Upload date:
- Size: 1.5 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.0 {"installer":{"name":"uv","version":"0.10.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6cba422e76d4b4c30e2c0533f73e856a429d729a1afa49ae941bcf1d61b912cc
|
|
| MD5 |
43a59271feef3023e2da0c92600aba79
|
|
| BLAKE2b-256 |
c938f0dc5b065870c508c11d301bebe3bf4d7495f0ea975567df731c3312a95b
|
File details
Details for the file qmd_to_pptx-0.1.3-py3-none-any.whl.
File metadata
- Download URL: qmd_to_pptx-0.1.3-py3-none-any.whl
- Upload date:
- Size: 170.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.10.0 {"installer":{"name":"uv","version":"0.10.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
47fadf687ef56e8559b5096f95f761ebbbcb4d52302c29b403f5821775f366db
|
|
| MD5 |
6fa978fd44d5175253f5039b3b989961
|
|
| BLAKE2b-256 |
be322cb7bb68cd3b07640bc766c3ab02c770afe5ba7fd4b7e6c40b62bd35878f
|