# PDF Generation in Desktop Commander MCP: Libraries, Methods, and Code Examples

> Explore PDF generation in Desktop Commander MCP. Discover key libraries like md-to-pdf and puppeteer, methods, and code examples for efficient PDF creation and manipulation.

- Repository: [Eduard Ruzga/DesktopCommanderMCP](https://github.com/wonderwhy-er/DesktopCommanderMCP)
- Tags: how-to-guide
- Published: 2026-08-02

---

**Desktop Commander MCP implements PDF generation through five specialized libraries: `md-to-pdf` for Markdown conversion, `@puppeteer/browsers` for Chrome management, `@opendocsg/pdf2md` for reverse conversion, `unpdf` for image extraction, and `pdf-lib` for structural editing.**

Desktop Commander MCP is an open-source Model Context Protocol server that provides comprehensive document processing capabilities. The PDF generation implementation resides primarily within the `src/tools/pdf/` directory, where specialized modules wrap industry-standard libraries to handle conversion, extraction, and manipulation tasks. Understanding these specific libraries and their integration patterns enables developers to extend the server's functionality or adapt similar architectures for their own TypeScript applications.

## Core PDF Generation Libraries

The project adopts a modular approach, delegating specific PDF tasks to specialized libraries rather than relying on monolithic solutions.

### Markdown to PDF Conversion with `md-to-pdf`

The primary engine for converting Markdown content to PDF documents is the **`md-to-pdf`** library. In [`src/tools/pdf/markdown.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/pdf/markdown.ts), the `parseMarkdownToPdf()` function wraps the library's `mdToPdf()` method, injecting Chrome executable paths discovered through the `@puppeteer/browsers` integration.

This conversion requires a Chromium-based browser to render the HTML intermediate. The code handles Chrome path resolution through `getChromePath()`, `installChrome()`, and `findSystemChrome()` functions defined in the same file (lines 86-122), ensuring the PDF generation pipeline never stalls due to missing browser binaries.

### Chrome Discovery via `@puppeteer/browsers`

PDF generation reliability depends on consistent Chrome availability. The **`@puppeteer/browsers`** module provides the underlying mechanism for locating system Chrome installations or downloading browser binaries when needed. The `ensureChromeAvailable()` function proactively manages this dependency, kicking off background downloads if neither cached nor system-installed browsers are detected.

### PDF to Markdown Reverse Conversion

For extracting text content from existing PDFs, Desktop Commander MCP utilizes **`@opendocsg/pdf2md`**. The wrapper function `parsePdfToMarkdown()` in [`src/tools/pdf/markdown.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/pdf/markdown.ts) loads PDF files into `Uint8Array` buffers and passes them to the `pdf2md()` function. This implementation in [`src/tools/pdf/lib/pdf2md.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/pdf/lib/pdf2md.ts) (lines 70-78) returns structured data including page content, metadata, and references to embedded images.

### Image Extraction with `unpdf`

Raster asset extraction leverages the **`unpdf`** library. The `extractImagesFromPdf()` function in [`src/tools/pdf/extract-images.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/pdf/extract-images.ts) utilizes `unpdf`'s `extractImages()` method to pull image data from PDF page streams. This capability supports workflows requiring visual content analysis or document reconstruction.

### Structural PDF Editing via `pdf-lib`

Manipulating PDF structure—such as deleting, inserting, or reordering pages—relies on the **`pdf-lib`** library. The `editPdf()` function in [`src/tools/pdf/manipulations.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/pdf/manipulations.ts) demonstrates this integration:

- **`PDFDocument.load()`**: Parses existing PDF bytes
- **`pdfDoc.removePage()`**: Deletes specified pages by index
- **`pdfDoc.insertPage()`**: Adds new pages at specific positions
- **`pdfDoc.save()`**: Serializes modifications back to bytes

## Implementation Examples

The following code patterns demonstrate how these libraries work together within the Desktop Commander MCP architecture.

### Generate PDF from Markdown Content

```typescript
import { parseMarkdownToPdf } from '@/tools/pdf/markdown.js';

const md = '# Hello World\nThis is a PDF generated from Markdown.';

const options = { 
  pdf_options: { 
    format: 'A4', 
    margin: { top: '1in' } 
  } 
};

const pdfBuffer = await parseMarkdownToPdf(md, options);
// Returns Node Buffer containing PDF file bytes

```

This calls `mdToPdf()` internally, automatically resolving Chrome paths through `getChromePath()`.

### Convert PDF to Structured Markdown

```typescript
import { parsePdfToMarkdown } from '@/tools/pdf/markdown.js';

const result = await parsePdfToMarkdown('docs/example.pdf');

console.log(result.metadata.title);
console.log(result.pages[0].text);

```

The function delegates to `pdf2md()` from `@opendocsg/pdf2md` after converting the file to `Uint8Array`.

### Edit PDF Structure

```typescript
import { editPdf } from '@/tools/pdf/manipulations.js';

const operations = [
  {
    type: 'delete',
    pageIndexes: [1, 2]  // zero-based indexes
  },
  {
    type: 'insert',
    pageIndex: 0,
    markdown: '# New Intro\nAdded via md-to-pdf.'

  }
];

const editedPdf = await editPdf('docs/example.pdf', operations);
// Returns Uint8Array of modified PDF

```

The `editPdf()` function uses `pdf-lib` to load the source document, apply the operation schema, and generate modified bytes.

### Ensure Chrome Availability at Startup

```typescript
import { ensureChromeAvailable } from '@/tools/pdf/markdown.js';

// Call once when server initializes
ensureChromeAvailable();

```

This preventive measure ensures PDF generation capabilities remain available without runtime interruptions.

## File Structure and Architecture

The PDF generation capabilities are organized across specific tool modules:

- **[`src/tools/pdf/markdown.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/pdf/markdown.ts)**: Core PDF generation utilities; wraps `md-to-pdf`, Chrome discovery, and PDF-to-Markdown conversion
- **[`src/tools/pdf/lib/pdf2md.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/pdf/lib/pdf2md.ts)**: Thin wrapper around `@opendocsg/pdf2md` for parsing logic
- **[`src/tools/pdf/manipulations.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/pdf/manipulations.ts)**: PDF editing operations built on `pdf-lib`
- **[`src/tools/pdf/extract-images.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/pdf/extract-images.ts)**: Image extraction logic using `unpdf`
- **[`src/utils/files/pdf.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/files/pdf.ts)**: High-level façade exposing PDF operations to the broader application

The [`package.json`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/package.json) file declares these external dependencies: `md-to-pdf`, `@opendocsg/pdf2md`, `pdf-lib`, `unpdf`, and `@puppeteer/browsers`.

## Summary

- **Desktop Commander MCP** implements PDF generation through five specialized npm packages rather than custom engines
- **`md-to-pdf`** handles Markdown-to-PDF conversion with Chrome/Chromium rendering via **`@puppeteer/browsers`**
- **`@opendocsg/pdf2md`** provides reverse conversion capabilities from PDF to structured Markdown
- **`unpdf`** extracts raster images from PDF documents for content analysis
- **`pdf-lib`** enables structural modifications including page deletion, insertion, and layout changes
- All functionality resides under `src/tools/pdf/` with clear separation between conversion, extraction, and manipulation concerns

## Frequently Asked Questions

### What is the primary library for Markdown to PDF conversion in Desktop Commander MCP?

The **`md-to-pdf`** library serves as the primary engine for converting Markdown content to PDF documents. The `parseMarkdownToPdf()` function in [`src/tools/pdf/markdown.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/pdf/markdown.ts) wraps this library, handling both the conversion logic and Chrome browser dependency injection through the `launch_options` parameter.

### How does Desktop Commander MCP handle Chrome browser dependencies?

The server utilizes **`@puppeteer/browsers`** to manage Chrome availability through three main functions: `findSystemChrome()` checks for existing installations, `installChrome()` downloads browser binaries when needed, and `getChromePath()` returns the executable path. The `ensureChromeAvailable()` function proactively ensures browser readiness before PDF generation requests occur.

### Can Desktop Commander MCP extract images from existing PDF files?

Yes, the **`unpdf`** library provides image extraction capabilities through the `extractImages()` method. This functionality is implemented in [`src/tools/pdf/extract-images.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/pdf/extract-images.ts) and enables the server to pull raster assets from PDF page streams for further processing or analysis.

### Which library handles structural modifications like page deletion and insertion?

**`pdf-lib`** manages all structural PDF editing operations. The `editPdf()` function in [`src/tools/pdf/manipulations.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/pdf/manipulations.ts) uses `PDFDocument.load()` to parse existing documents, applies operations through methods like `removePage()` and `insertPage()`, and serializes results via `pdfDoc.save()` to produce modified PDF bytes.