# PDF Manipulation System in DesktopCommanderMCP: Text Extraction, Markdown Conversion, and Modification

> Explore DesktopCommanderMCP's PDF manipulation system for text extraction, Markdown conversion, and editing. Utilize pdf2md, md-to-pdf, and pdf-lib via a secure RPC API.

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

---

**DesktopCommanderMCP provides a complete PDF manipulation pipeline that extracts text to Markdown using pdf2md, creates PDFs from Markdown via md-to-pdf with Puppeteer caching, and edits documents using pdf-lib, all exposed through a secure Server RPC API.**

DesktopCommanderMCP treats PDFs as first-class files, offering a unified system for reading, writing, and editing PDF documents through Markdown intermediates. The architecture isolates third-party libraries behind a consistent TypeScript API, enabling reliable document processing for AI-driven workflows.

## PDF Text Extraction Pipeline

The system extracts PDF content using the `pdf2md` library, wrapped in [`src/tools/pdf/lib/pdf2md.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/pdf/lib/pdf2md.ts). This module parses PDF binaries into a `PdfParseResult` object containing page-wise text, embedded images, and document metadata.

The `parsePdfToMarkdown` function in [`src/tools/pdf/markdown.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/pdf/markdown.ts) consumes this result to generate structured Markdown documents. During conversion, the extractor captures critical metadata including author, title, total page count, and per-page content boundaries, enabling downstream tools to make context-aware decisions based on document structure.

```typescript
// Extract a remote PDF to Markdown
import { parsePdfToMarkdown } from '@/tools/pdf/index.js';

const pdfUrl = 'https://example.com/report.pdf';
const result = await parsePdfToMarkdown(pdfUrl);
console.log(result.markdown);        // Markdown string
console.log(result.metadata.title); // PDF title

```

## Creating PDFs from Markdown

PDF generation leverages the `md-to-pdf` package within [`src/tools/pdf/markdown.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/pdf/markdown.ts). The `mdToPdf` function (also exposed as `parseMarkdownToPdf`) renders Markdown strings into PDF buffers, accepting optional configuration objects for page size, margins, and formatting.

To optimize performance, the implementation caches the Chrome executable required for headless rendering. The `getPuppeteerCacheDir` and `findPuppeteerChrome` functions manage a private Puppeteer cache, preventing repeated downloads and significantly speeding up subsequent conversion calls.

```typescript
// Create a new PDF from Markdown
import { parseMarkdownToPdf } from '@/tools/pdf/index.js';

const markdown = '# Quarterly Report\n\nData and charts...';

const pdfBuffer = await parseMarkdownToPdf(markdown, { 
  pdf_options: { format: 'A4' } 
});
await fs.writeFile('quarterly.pdf', pdfBuffer);

```

## Editing and Modifying Existing PDFs

All mutating operations are delegated to **pdf-lib** through [`src/tools/pdf/manipulations.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/pdf/manipulations.ts). The editing workflow follows a consistent pattern: load the target PDF into a `PDFDocument` via `loadPdfDocumentFromBuffer`, apply one or more operations, then serialize the result using `pdfDoc.save`.

### Page-Level Operations

The system supports three primary mutation types:

- **deletePages**: Removes specified pages by zero-based index
- **insertPages**: Splices new content (from existing PDFs or Markdown) at specific positions
- **replacePages**: Substitutes existing pages with alternative content

When inserting Markdown-derived content, the system first converts the Markdown to a PDF buffer using `parseMarkdownToPdf`, then integrates it into the target document before saving.

```typescript
// Edit a PDF – delete pages 2-4 and insert a new page at index 1
import { editPdf } from '@/tools/pdf/index.js';

await editPdf({
  pdfPath: 'original.pdf',
  operations: [
    { type: 'delete', pageIndexes: [1, 2, 3] },
    {
      type: 'insert',
      pageIndex: 0,
      markdown: '## New Intro Page\n\nWelcome!',

      pdfOptions: { pdf_options: { format: 'A4' } },
    },
  ],
});

```

## Server RPC API Interface

The PDF capabilities are exposed to clients through the Server RPC API defined in [`src/server.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/server.ts). Three primary commands handle document workflows:

- **read_pdf**: Converts a PDF (local path or URL) to Markdown and returns metadata. Requires `path` or `url` parameter.
- **write_pdf**: Renders supplied Markdown into a new PDF file. Requires `path` and `content` parameters, with optional `options` for PDF formatting.
- **edit_pdf**: Applies page-level edits (delete, insert, replace) on an existing PDF. Requires `path` and an `operations` array describing the modifications.

## Architecture and Implementation Details

### File Handler Abstraction

PDF handling is encapsulated in the `PdfFileHandler` class located in [`src/utils/files/pdf.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/files/pdf.ts). This handler exposes standardized `read`, `write`, and `edit` methods. A factory pattern in [`src/utils/files/factory.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/utils/files/factory.ts) lazily instantiates and returns a singleton PDF handler instance, ensuring consistent resource management across the codebase.

### Robust Error Handling and Security

All PDF-lib operations are wrapped in `try/catch` blocks with explicit cleanup. Temporary resources invoke `pdfDocument.cleanup` or `destroy` methods when available, preventing memory leaks during batch processing.

Security measures include explicit forbidding of direct filesystem writes for PDF creation—requiring use of the `write_pdf` command—and validation via `isPdfFile` MIME-type checks. Path validation ensures only legitimate PDF files are processed, protecting against directory traversal attacks.

## Summary

- **Text extraction** uses `pdf2md` via [`src/tools/pdf/lib/pdf2md.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/pdf/lib/pdf2md.ts) to parse PDFs into structured Markdown with metadata.
- **PDF creation** employs `md-to-pdf` in [`src/tools/pdf/markdown.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/pdf/markdown.ts) with Chrome executable caching for performance.
- **Document editing** relies on `pdf-lib` in [`src/tools/pdf/manipulations.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/pdf/manipulations.ts) supporting delete, insert, and replace operations.
- The **Server RPC API** in [`src/server.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/server.ts) exposes `read_pdf`, `write_pdf`, and `edit_pdf` commands with mandatory parameter validation.
- **Architecture** uses the `PdfFileHandler` singleton pattern with comprehensive error handling and security checks.

## Frequently Asked Questions

### How does DesktopCommanderMCP extract text from PDF files?

DesktopCommanderMCP uses the `@opendocsg/pdf2md` library wrapped in [`src/tools/pdf/lib/pdf2md.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/pdf/lib/pdf2md.ts) to parse PDF binaries into a `PdfParseResult` containing page-wise text, images, and metadata. The `parsePdfToMarkdown` function in [`src/tools/pdf/markdown.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/pdf/markdown.ts) then transforms this result into a structured Markdown document while preserving document metadata like author and title.

### What dependencies are required for Markdown-to-PDF conversion?

The Markdown-to-PDF conversion requires the `md-to-pdf` package, which internally uses Puppeteer to control a headless Chromium instance. DesktopCommanderMCP mitigates the performance overhead by caching the Chrome executable using `getPuppeteerCacheDir` and `findPuppeteerChrome` functions, avoiding repeated downloads across conversion calls.

### Can DesktopCommanderMCP modify existing PDFs without recreating them?

Yes, the system can edit existing PDFs through the `editPdf` function in [`src/tools/pdf/manipulations.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/pdf/manipulations.ts) using the `pdf-lib` library. It supports page deletion, insertion of new content (from Markdown or other PDFs), and page replacement. The workflow loads the document via `loadPdfDocumentFromBuffer`, applies operations, and saves using `pdfDoc.save`.

### What security measures protect PDF operations in the server?

The server in [`src/server.ts`](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/server.ts) enforces path validation and MIME-type verification through `isPdfFile` checks to ensure only legitimate PDFs are processed. Direct filesystem writes are forbidden; all PDF creation must use the `write_pdf` RPC command. Additionally, PDF-lib operations include `try/catch` blocks with explicit `cleanup` or `destroy` calls to prevent memory leaks and resource exhaustion.