PDF Manipulation System in DesktopCommanderMCP: Text Extraction, Markdown Conversion, and Modification
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. 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 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.
// 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. 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.
// 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. 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.
// 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. Three primary commands handle document workflows:
- read_pdf: Converts a PDF (local path or URL) to Markdown and returns metadata. Requires
pathorurlparameter. - write_pdf: Renders supplied Markdown into a new PDF file. Requires
pathandcontentparameters, with optionaloptionsfor PDF formatting. - edit_pdf: Applies page-level edits (delete, insert, replace) on an existing PDF. Requires
pathand anoperationsarray 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. This handler exposes standardized read, write, and edit methods. A factory pattern in 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
pdf2mdviasrc/tools/pdf/lib/pdf2md.tsto parse PDFs into structured Markdown with metadata. - PDF creation employs
md-to-pdfinsrc/tools/pdf/markdown.tswith Chrome executable caching for performance. - Document editing relies on
pdf-libinsrc/tools/pdf/manipulations.tssupporting delete, insert, and replace operations. - The Server RPC API in
src/server.tsexposesread_pdf,write_pdf, andedit_pdfcommands with mandatory parameter validation. - Architecture uses the
PdfFileHandlersingleton 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 to parse PDF binaries into a PdfParseResult containing page-wise text, images, and metadata. The parsePdfToMarkdown function in 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 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 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.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →