md2star.api module

md2star — FastAPI HTTP surface.

Exposes the md2star Markdown → DOCX / PPTX / PDF bridge as HTTP endpoints so it can sit behind any reverse proxy and be consumed by other services. Kept intentionally aligned with the rest of the toolkit’s suite (os_helper.api / vocal_helper.api / …): a liveness probe, a JSON environment diagnostic, and a multipart action that uploads Markdown and streams back the compiled document.

Exposed surface:

  • GET  / — redirect to the browser bench at /gui.

  • GET  /gui — a minimal single-page conversion bench (drop a .md, pick a format, download the result). The self-contained HTML lives in md2star.gui; the page POSTs to /convert and adds no server logic. (For the full Overleaf-style editor with a live PDF preview, run md2star gui — that is md2star.gui_server, a separate stdlib server.)

  • GET  /health — liveness probe.

  • GET  /doctor — the same environment diagnostic as md2star doctor --json (which tools are present, per-format feature status).

  • POST /convert — upload a .md file, pick a target format (docx / pptx / pdf), and stream back the rendered document.

  • POST /extract — the reverse direction: upload a .docx / .pptx / .pdf and get its Markdown back as JSON, or pass twin=true (optionally diagrams=true) to receive a zip of <stem>.md + an assets/ folder — a self-contained, re-renderable Markdown twin. Needs the optional [ocr] extra (Kreuzberg); returns 503 with an install hint when it is absent.

Install the extra to get the runtime dependencies:

pip install 'md2star[api]'

Then run the app with any ASGI server:

uvicorn md2star.api:app --host 0.0.0.0 --port 8000
# or: md2star-api      (see [project.scripts])

Note that conversion still requires Pandoc on the host (and LibreOffice for PDF); GET /doctor reports what is available, and POST /convert returns HTTP 503 when a required system tool is missing.

Usage Example

>>> # Start the server:
>>> #   uvicorn md2star.api:app --reload
>>> # Convert Markdown to DOCX:
>>> #   curl -F 'file=@notes.md' 'http://localhost:8000/convert?fmt=docx' -o notes.docx
>>> # Environment diagnostic:
>>> #   curl -s http://localhost:8000/doctor
>>> # Full OpenAPI docs at http://localhost:8000/docs

Author

Warith Harchaoui, Ph.D. — https://linkedin.com/in/warith-harchaoui/

async md2star.api.convert(background, file=fastapi.File, fmt=fastapi.Query, author=fastapi.Query, lang=fastapi.Query, date=fastapi.Query)

Convert an uploaded Markdown file into a rendered document and stream it.

Parameters:
  • background (fastapi.BackgroundTasks) – Used to delete the temp working directory after the response streams.

  • file (fastapi.UploadFile) – The input Markdown document.

  • fmt (str, optional) – Target format — one of docx / pptx / pdf. Defaults to docx.

  • author (str or None, optional) – Optional Pandoc metadata forwarded to the converter when provided.

  • lang (str or None, optional) – Optional Pandoc metadata forwarded to the converter when provided.

  • date (str or None, optional) – Optional Pandoc metadata forwarded to the converter when provided.

Returns:

The compiled document, streamed with the format’s MIME type.

Return type:

fastapi.responses.FileResponse

Raises:

fastapi.HTTPException – 400 for an unknown format or invalid Markdown input, 503 when a required system tool (Pandoc / LibreOffice) is missing, 500 on any other conversion failure.

md2star.api.doctor()

Report the environment md2star runs in (tools present, feature status).

Returns:

The same payload as md2star doctor --json: a list of checks, a per-format features map, and a core_failing flag.

Return type:

dict

async md2star.api.extract(background, file=fastapi.File, twin=fastapi.Form, diagrams=fastapi.Form)

Read an uploaded DOCX/PPTX/PDF back into Markdown (the reverse direction).

Two modes:

  • text-only (default) — delegate to md2star.reverse.to_markdown() (Kreuzberg) and return {"filename": <stem>.md, "markdown": <text>}.

  • twin (twin=true, or diagrams=true which implies it) — delegate to md2star.reverse.to_markdown_twin(), which writes <stem>.md plus an assets/ folder; the response is a zip of both so the caller receives a self-contained, re-renderable Markdown source. With diagrams=true and the [ai] stack present, node-and-edge figures are re-authored as Mermaid; otherwise every image degrades to a scraped PNG.

Parameters:
  • background (fastapi.BackgroundTasks) – Deletes the temp working directory after the request completes.

  • file (fastapi.UploadFile) – The document to read back; extension must be docx / pptx / pdf.

  • twin (bool, default False) – Return the full editable twin (zip) rather than text-only JSON.

  • diagrams (bool, default False) – Reconstruct diagrams as Mermaid during a twin extraction (implies twin).

Returns:

Text-only mode: {"filename": <stem>.md, "markdown": <text>}. Twin mode: a application/zip file response (<stem>.zip).

Return type:

dict or fastapi.responses.FileResponse

Raises:

fastapi.HTTPException – 400 for an unsupported extension, 503 when the optional [ocr] extra (Kreuzberg) is not installed, 500 on any extraction failure.

md2star.api.gui()

Serve the minimal single-page conversion bench.

The page (defined in md2star.gui) is a build-step-free, self-contained HTML document: drop a Markdown file, pick a format, and it POSTs to the same /convert endpoint as the CLI and MCP surfaces. For the full editor with a live PDF preview, run md2star gui instead.

Returns:

The conversion-bench page.

Return type:

fastapi.responses.HTMLResponse

md2star.api.health()

Liveness probe.

Returns:

{"status": "ok"} when the service is up.

Return type:

dict of str

md2star.api.index()

Redirect the site root to the browser bench.

Returns:

A 307 redirect to /gui so opening the server root lands on the GUI.

Return type:

fastapi.responses.RedirectResponse

md2star.api.main()[source]

Entry point for the md2star-api console script.

Boots the FastAPI app with uvicorn in single-worker mode. Meant for local / container usage; behind a real load balancer, run uvicorn / gunicorn directly against md2star.api.app.

Return type:

None