How DesktopCommander Handles PDF Manipulation: Text Extraction and Markdown-to-PDF Creation

DesktopCommander processes PDFs through a three-stage pipeline that extracts text and images using @opendocsg/pdf2md, generates PDFs from markdown via md-to-pdf with Puppeteer, and modifies existing documents using pdf-lib for page deletion and insertion operations.

DesktopCommanderMCP provides robust PDF manipulation capabilities that bridge the gap between binary documents and editable markdown. According to the wonderwhy-er/DesktopCommanderMCP source code, the implementation in src/tools/pdf/ offers a complete workflow for extracting structured content from existing PDFs, creating new documents from markdown, and performing surgical edits on page collections.

PDF Text Extraction Pipeline

The text extraction system follows a modular architecture that separates data loading from content parsing.

Loading PDF Sources

The loadPdfToBuffer function in src/tools/pdf/markdown.ts handles the initial ingestion phase. This utility determines whether the PDF originates from a remote URL or a local filesystem path and returns a unified Buffer/ArrayBuffer for downstream processing. This abstraction allows the extraction logic to operate identically regardless of the document's source location.

Extracting Text and Images

The core conversion logic resides in src/tools/pdf/lib/pdf2md.ts, which wraps the third-party @opendocsg/pdf2md library. The function constructs a page list, applies font-aware transformations through makeTransformations and transform calls, and delegates image extraction to src/tools/pdf/extract-images.ts. The result is a PdfParseResult object containing an array of PdfPageItem objects, each providing the page number, plain text content, and any extracted images.

The Public API Wrapper

The parsePdfToMarkdown(source, pageNumbers?) function exported from src/tools/pdf/markdown.ts serves as the primary entry point. It orchestrates the pipeline by loading the buffer, invoking the pdf2md converter, and returning the structured result with full metadata and per-page content arrays.

// Extract text (and images) from a PDF file
import { parsePdfToMarkdown } from './src/tools/pdf/index.js';

(async () => {
  const result = await parsePdfToMarkdown('docs/report.pdf');
  console.log('Metadata:', result.metadata);
  result.pages.forEach(p => console.log(`Page ${p.pageNumber} text:\n`, p.text));
})();

Creating PDFs from Markdown

DesktopCommander converts markdown to PDF through a Chrome-based rendering pipeline that ensures consistent stylesheet application.

Chrome/Chromium Discovery

The getChromePath function in src/tools/pdf/markdown.ts implements a resilient binary discovery strategy. It first checks the Puppeteer cache for existing installations, falls back to system-installed Chrome executables, and finally downloads a fresh Chromium build via @puppeteer/browsers if no suitable binary is found. This guarantees that md-to-pdf has a compatible rendering engine available.

Markdown-to-PDF Conversion

The parseMarkdownToPdf(markdown, options?) function accepts markdown content and optional rendering configuration. Using the discovered Chrome executable, it delegates to the md-to-pdf library, which renders the markdown to HTML and prints it to PDF. The function returns a Buffer representing the newly created PDF document, ready for disk storage or further manipulation.

// Create a PDF from markdown
import { parseMarkdownToPdf } from './src/tools/pdf/index.js';
import fs from 'fs/promises';

(async () => {
  const markdown = '# Title\n\nSome **styled** text.';

  const pdfBuffer = await parseMarkdownToPdf(markdown);
  await fs.writeFile('out/generated.pdf', pdfBuffer);
})();

Editing Existing PDFs

The manipulation layer in src/tools/pdf/manipulations.ts enables non-destructive editing of existing PDFs through the pdf-lib library.

Deleting Pages

The editPdf(pdfPath, operations[]) function processes deletion operations by calling normalizePageIndexes from src/tools/pdf/utils.ts to handle negative indices (Python-style reverse indexing). It removes pages in reverse order to maintain correct page numbering during the deletion sequence, then returns the modified document as a Uint8Array.

Inserting Pages from Markdown

The editing API supports inserting pages from two sources: external PDF files or dynamically generated markdown. When inserting markdown content, the function invokes parseMarkdownToPdf to create a temporary PDF buffer, then uses pdf-lib to graft these pages into the target document at the specified index. This enables workflows like prepending cover pages or inserting appendix sections generated from markdown templates.

// Edit a PDF: delete page 2 and insert a markdown-generated page after page 1
import { editPdf } from './src/tools/pdf/index.js';
import fs from 'fs/promises';

(async () => {
  const ops = [
    { type: 'delete', pageIndexes: [2] },                     // remove original page 2
    {
      type: 'insert',
      pageIndex: 1,
      markdown: '## New Section\n\nInserted from markdown.'

    }
  ];
  const edited = await editPdf('docs/report.pdf', ops);
  await fs.writeFile('out/edited.pdf', edited);
})();

Summary

  • parsePdfToMarkdown in src/tools/pdf/markdown.ts extracts structured text and images from PDFs using @opendocsg/pdf2md and extract-images.ts.
  • parseMarkdownToPdf generates PDFs from markdown via md-to-pdf, with automatic Chrome/Chromium discovery through getChromePath.
  • editPdf in src/tools/pdf/manipulations.ts modifies existing PDFs using pdf-lib, supporting page deletion with normalized indexing and insertion of markdown-generated content.
  • The utility functions in src/tools/pdf/utils.ts provide critical helpers like normalizePageIndexes for robust page manipulation.

Frequently Asked Questions

How does DesktopCommander extract text from PDF files?

DesktopCommander extracts text through the parsePdfToMarkdown function, which loads the PDF into a buffer and delegates parsing to pdf2md.ts. The underlying @opendocsg/pdf2md library parses the raw bytes, applies font-aware transformations, and returns a PdfParseResult containing per-page text content and metadata.

What libraries does DesktopCommander use for PDF manipulation?

The codebase uses @opendocsg/pdf2md for text extraction, md-to-pdf with Puppeteer for markdown-to-PDF conversion, and pdf-lib for binary PDF editing. It also uses @puppeteer/browsers to manage Chrome/Chromium installations when system binaries are unavailable.

Can DesktopCommander insert markdown-generated pages into existing PDFs?

Yes. The editPdf function accepts an insert operation type that specifies markdown content. It dynamically generates a PDF from the markdown using parseMarkdownToPdf, then inserts the resulting pages at the specified index within the target document using pdf-lib APIs.

How does the tool handle Chrome/Chromium dependencies for PDF generation?

The getChromePath function implements a three-tier fallback strategy: it checks the Puppeteer cache first, then searches for system-installed Chrome binaries, and finally downloads a fresh Chromium build via @puppeteer/browsers if no existing binary is found. This ensures the md-to-pdf library always has a compatible rendering engine.

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 →