How PDF Support Works in Desktop Commander MCP: Extraction, Creation, and Modification

Desktop Commander MCP provides comprehensive PDF support through a dedicated file handler that extracts text to Markdown using @opendocsg/pdf2md, creates PDFs from Markdown via md-to-pdf and Puppeteer, and modifies documents with pdf-lib page manipulations.

Desktop Commander MCP treats PDF documents as first-class content through its specialized PDF file handler architecture. The implementation, found in the wonderwhy-er/DesktopCommanderMCP repository, abstracts complex PDF operations into three core capabilities: text extraction, document creation, and page-level modification. This design allows the Model Context Protocol (MCP) server to read, write, and edit PDF files using standard Markdown as an intermediate format.

PDF Text Extraction (PDF to Markdown)

The parsePdfToMarkdown Pipeline

When reading a PDF file, the PdfFileHandler class invokes parsePdfToMarkdown() from src/tools/pdf/markdown.ts. This function streams the PDF content into a Uint8Array buffer and processes it through @opendocsg/pdf2md:

// src/tools/pdf/markdown.ts
const pdfResult = await parsePdfToMarkdown(path, range);
// Internally uses: pdf2md(buffer) from @opendocsg/pdf2md

The conversion produces a PdfParseResult object containing the document's text content structured as Markdown, with each PDF page represented as a separate string in the pages array.

Metadata and Page Structure

The extraction process captures rich metadata including author, title, and total page count. The FileResult returned by the handler includes:

  • mimeType: application/pdf
  • pages: Array of Markdown strings (one per page)
  • metadata: Document properties extracted during parsing

For image extraction, the system leverages [src/tools/pdf/extract-images.ts](https://github.com/wonderwhy-er/DesktopCommanderMCP/blob/main/src/tools/pdf/extract-images.ts), which uses unpdf to extract embedded images for downstream processing.

PDF Creation (Markdown to PDF)

The parseMarkdownToPdf Workflow

Creating PDF documents is handled by the write_pdf tool, which orchestrates the parseMarkdownToPdf() function. This utility converts Markdown content into formatted PDFs using md-to-pdf:

// src/tools/pdf/markdown.ts
const pdf = await mdToPdf({ content: markdown }, options);
return pdf.content; // Buffer containing the PDF

The md-to-pdf library renders the Markdown through Puppeteer, providing full CSS support and configurable page layouts via the options parameter.

Chrome/Chromium Resolution

Before rendering, parseMarkdownToPdf() ensures a Chrome binary is available through getChromePath(). The resolution strategy checks:

  1. Puppeteer's cached Chrome installation
  2. System-installed Chrome/Chromium binaries
  3. Automatic download via @puppeteer/browsers (fallback)

If no Chrome installation is found, the function throws a descriptive error directing users to install Chrome manually, preventing silent failures during PDF generation.

PDF Modification (Page Editing)

Page Deletion and Insertion

Desktop Commander MCP supports surgical page-level modifications through editPdf(), implemented in src/tools/pdf/manipulations.ts. This function exposes two primary operations via pdf-lib:

  • deletePages(pdfDoc, pageIndexes): Removes specific pages by their zero-based indices
  • insertPages(pdfDoc, pageIndex, sourcePdfDocument): Inserts pages from a source PDF at a specified position

The editPdf Implementation

The PdfFileHandler.editRange() method delegates modification requests to editPdf(), which loads the target document into a PDFDocument instance, applies the requested transformations, and serializes the result:

// src/utils/files/pdf.ts
const editedBuffer = await editPdf(buffer, operations);
await fs.writeFile(targetPath, editedBuffer);

This workflow supports complex reordering scenarios, such as deleting cover pages, inserting chapters from external files, or rearranging existing content without re-rendering the entire document from Markdown.

Supporting Utilities and Architecture

The PDF subsystem relies on several specialized modules that provide low-level functionality:

Summary

  • Text Extraction: Uses parsePdfToMarkdown() with @opendocsg/pdf2md to convert PDF pages to Markdown while preserving metadata.
  • Document Creation: Leverages parseMarkdownToPdf() with md-to-pdf and Puppeteer to render Markdown into formatted PDFs, with automatic Chrome binary resolution.
  • Page Modification: Implements editPdf() using pdf-lib for deletion and insertion operations without full document re-creation.
  • Handler Architecture: Centralizes PDF logic in PdfFileHandler, registered via the file factory pattern for seamless integration with the MCP server.

Frequently Asked Questions

How does Desktop Commander MCP extract text from PDFs?

The system uses the parsePdfToMarkdown() function in src/tools/pdf/markdown.ts, which internally calls @opendocsg/pdf2md to parse PDF buffers into Markdown text. This preserves document structure by returning each page as a separate Markdown string within a result object that includes metadata like author and title.

What library does Desktop Commander MCP use to create PDFs from Markdown?

PDF creation relies on md-to-pdf, a Node.js library that uses Puppeteer to render Markdown content with CSS styling. The parseMarkdownToPdf() function handles the conversion and manages Chrome binary detection to ensure the rendering engine is available.

Can Desktop Commander MCP edit existing PDF files?

Yes, the tool supports page-level modifications through the editPdf() function in src/tools/pdf/manipulations.ts. Using pdf-lib, it can delete specific page indexes or insert pages from other PDF documents, allowing for surgical edits without converting the entire file to Markdown and back.

How does the tool handle Chrome dependencies for PDF generation?

The getChromePath() utility implements a three-tier resolution strategy: it first checks Puppeteer's cache, then searches system installations, and finally attempts to download Chrome via @puppeteer/browsers. If all methods fail, it provides clear error messaging instructing users to install Chrome manually.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →