# How the `write_pdf` Tool Renders HTML, CSS & SVG for PDF Generation in DesktopCommanderMCP

> Discover how the write_pdf tool in DesktopCommanderMCP converts HTML CSS and SVG to PDF. Learn about the headless Chromium rendering process for robust document generation.

- Repository: [Eduard Ruzga/DesktopCommanderMCP](https://github.com/wonderwhy-er/DesktopCommanderMCP)
- Tags: internals
- Published: 2026-08-03

---

**The `write_pdf` tool supports HTML, CSS, and SVG by converting Markdown to HTML, then rendering that HTML through a headless Chromium browser before exporting to PDF.**

The `write_pdf` tool in the [DesktopCommanderMCP](https://github.com/wonderwhy-er/DesktopCommanderMCP) repository enables rich PDF generation by leveraging a full browser engine. When you pass content containing raw HTML, embedded styles, or inline SVG, the tool preserves these elements throughout the conversion pipeline rather than stripping or sanitizing them. This browser-based approach ensures that complex layouts and vector graphics render exactly as designed.

## How HTML/CSS/SVG Support Works Under the Hood

The PDF generation pipeline in [`src/tools/pdf/markdown.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/pdf/markdown.ts) follows a three-stage process that treats your content like a web page:

### Markdown-to-HTML Conversion with `markdown-it`

First, the `parseMarkdownToPdf` function passes your content to **`md-to-pdf`**, which uses **`markdown-it`** to convert Markdown to HTML. Crucially, `markdown-it` does **not** escape or remove raw HTML blocks during this conversion.

This means any embedded HTML—`<div>` containers, `<span>` elements, or `<style>` tags—pass through unchanged to the next stage.

### Headless Chromium Rendering via Puppeteer

The generated HTML is then opened in a **Chrome/Chromium** instance launched via **Puppeteer**. The `getChromePath()` utility in [`src/tools/pdf/markdown.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/pdf/markdown.ts) handles Chrome detection and installation if needed.

Because this is a real browser engine, it:
- Parses and applies **CSS rules** from `<style>` tags or external stylesheets
- Renders **SVG graphics** at full vector quality
- Executes any standard web layout algorithms (flexbox, grid, etc.)

### PDF Export Through Chrome's Print Pipeline

Finally, Chromium's built-in PDF printer exports the rendered page to a buffer using `mdToPdf({ content: markdown }, options)`. The result is a PDF that visually matches what you'd see in a desktop browser.

## What HTML/CSS/SVG Features Are Supported

Because `write_pdf` delegates rendering to Chromium, you gain comprehensive web standards support:

| Feature | How to Use It | Example |
|---------|-------------|---------|
| **Raw HTML blocks** | Insert directly in Markdown | `<div class="callout">Note</div>` |
| **Embedded CSS** | `<style>` tag or inline `style=` | `<style>.red{color:red}</style>` |
| **Inline SVG** | `<svg>` element with markup | `<svg><circle cx="50" cy="50" r="40"/></svg>` |
| **External stylesheets** | Via `md-to-pdf` options | `styles: ['path/to/custom.css']` |

## Practical Code Examples

### Basic Markdown to PDF

```typescript
await writePdf(
  "report.pdf",
  "# Quarterly Report\n\nRevenue increased 23% year-over-year."

);

```

### PDF with Custom CSS Styling

```typescript
const markdown = `
<style>
  .metric { font-size: 24px; font-weight: bold; color: #2ecc71; }
  .label { color: #7f8c8d; text-transform: uppercase; }
</style>

# Dashboard

<div class="metric">$1.2M</div>
<div class="label">Total Revenue</div>

Standard Markdown still works **normally**.
`;

await writePdf("styled-dashboard.pdf", markdown);

```

### PDF with Inline SVG Graphics

```typescript
const markdown = `

# Architecture Diagram

<svg width="400" height="200" viewBox="0 0 400 200">
  <rect x="20" y="50" width="100" height="80" fill="#3498db" rx="5"/>
  <rect x="160" y="50" width="100" height="80" fill="#e74c3c" rx="5"/>
  <rect x="300" y="50" width="80" height="80" fill="#2ecc71" rx="5"/>
  <path d="M120 90 L160 90" stroke="#34495e" stroke-width="2" marker-end="url(#arrow)"/>
  <path d="M260 90 L300 90" stroke="#34495e" stroke-width="2" marker-end="url(#arrow)"/>
  <defs>
    <marker id="arrow" markerWidth="10" markerHeight="10" refX="9" refY="3" orient="auto">
      <path d="M0,0 L0,6 L9,3 z" fill="#34495e"/>
    </marker>
  </defs>
  <text x="70" y="95" text-anchor="middle" fill="white" font-size="14">API</text>
  <text x="210" y="95" text-anchor="middle" fill="white" font-size="14">Cache</text>
  <text x="340" y="95" text-anchor="middle" fill="white" font-size="14">DB</text>
</svg>
`;

await writePdf("architecture.pdf", markdown);

```

### Advanced Configuration with Chromium Options

```typescript
await writePdf(
  "enterprise-report.pdf",
  "# Confidential\n\nQuarterly financial data.",

  undefined,
  {
    launch_options: {
      args: ["--no-sandbox", "--disable-setuid-sandbox"],
      executablePath: "/usr/bin/google-chrome"
    },
    pdf_options: {
      format: "A4",
      printBackground: true,
      margin: { top: "2cm", right: "2cm", bottom: "2cm", left: "2cm" },
      displayHeaderFooter: true,
      headerTemplate: '<div style="font-size:9px; color:#999; width:100%; text-align:center;">Company Name</div>',
      footerTemplate: '<div style="font-size:9px; color:#999; width:100%; text-align:center;"><span class="pageNumber"></span> / <span class="totalPages"></span></div>'
    },
    basedir: "/app/templates",
    styles: ["/app/templates/corporate.css"],
    as_html: false
  }
);

```

## Key Source Files and Their Roles

- **[`src/tools/filesystem.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/filesystem.ts)** — Contains the `writePdf` implementation that validates arguments and orchestrates PDF creation
- **[`src/tools/pdf/markdown.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/pdf/markdown.ts)** — Houses `parseMarkdownToPdf` and `getChromePath()` for Chromium management and `md-to-pdf` invocation
- **[`src/tools/schemas.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/schemas.ts)** — Defines `WritePdfArgsSchema` with flexible `options` typing that forwards to `md-to-pdf`
- **[`src/server.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/server.ts)** — Registers the `write_pdf` tool and exposes help documentation
- **[`package.json`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/package.json)** — Declares `md-to-pdf` and `@puppeteer/browsers` dependencies that enable the HTML/CSS/SVG pipeline

## Summary

- **`write_pdf`** supports HTML, CSS, and SVG by rendering content through a headless Chromium browser rather than using a limited markup converter.
- The **three-stage pipeline** (Markdown → HTML → Chromium → PDF) preserves all web-standard formatting and graphics.
- **Raw HTML blocks**, **embedded `<style>` tags**, and **inline SVG elements** pass through unchanged to the browser renderer.
- Configure Chromium launch options and PDF export settings through the fourth `options` parameter forwarded to `md-to-pdf`.

## Frequently Asked Questions

### Can I use external CSS files instead of inline styles?

Yes. Pass file paths via the `styles` array in the options parameter. Files are resolved relative to the `basedir` option or absolute paths. The styles are injected into the HTML before Chromium rendering begins.

### Does SVG support include complex features like gradients and filters?

All standard SVG 1.1 features supported by Chromium work correctly, including linear/radial gradients, filters, patterns, and animations (rendered as static frames). Since rendering uses the same engine as Google Chrome, you can verify compatibility by testing your SVG in a regular browser first.

### What happens if Chrome isn't installed on the system?

The `getChromePath()` function in [`src/tools/pdf/markdown.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/pdf/markdown.ts) automatically attempts to install a compatible Chromium build via `@puppeteer/browsers` if no system Chrome is detected. You can also specify a custom executable path through `launch_options.executablePath`.

### Are there security concerns with rendering arbitrary HTML?

Because content executes in a headless browser, you should sanitize untrusted input before passing it to `write_pdf`. The tool does not implement its own CSP or sandboxing beyond what Puppeteer provides. For untrusted content, consider running the MCP server with restricted network access or pre-processing Markdown to strip dangerous HTML elements.