How DesktopCommanderMCP Ensures Chrome Is Available for PDF Generation
DesktopCommanderMCP ensures Chrome is available for PDF generation by implementing a background initialization hook that searches Puppeteer caches, falls back to system installations, and automatically downloads Chrome if necessary, caching the discovered path for O(1) subsequent access.
DesktopCommanderMCP is a Model Context Protocol (MCP) server that creates and edits PDF documents by converting Markdown content. Because the underlying md-to-pdf library requires a Chrome or Chromium executable to render HTML to PDF, the system must ensure Chrome is available before processing any document operations. The solution implements a resilient three-step discovery process that executes asynchronously during server initialization.
The Three-Step Chrome Availability Process
The guarantee is implemented through a coordinated sequence spanning the server lifecycle, from startup initialization through runtime PDF generation.
Step 1: Background Initialization on Server Startup
Immediately after the MCP server completes its handshake with the client, the system triggers the availability check without blocking other operations. In src/index.ts at line 34, the oninitialized callback invokes ensureChromeAvailable():
// src/index.ts
server.oninitialized = async () => {
ensureChromeAvailable(); // Background check starts immediately
};
This non-blocking approach allows the server to begin handling tool requests while Chrome discovery proceeds in parallel.
Step 2: Multi-Tier Chrome Discovery and Caching
The ensureChromeAvailable() function delegates to getChromePath() defined in src/tools/pdf/markdown.ts. This function implements a cascading fallback strategy:
- Puppeteer Cache Check –
findPuppeteerChrome()searches for existing Chrome installations previously downloaded by Puppeteer. - System Installation –
findSystemChrome()locates Chrome or Chromium binaries installed on the host operating system. - Automatic Download –
installChrome()uses the@puppeteer/browserspackage to download a fresh Chrome binary as a last resort.
The discovered absolute path is stored in the module-level variable cachedChromePath, ensuring subsequent calls return instantly without repeating the search process.
Step 3: Runtime Injection into PDF Generation
When the write_pdf tool receives a request, it ultimately calls parseMarkdownToPdf() in markdown.ts. This function awaits getChromePath() and injects the executable path into md-to-pdf's launch options:
const chromePath = await getChromePath();
if (chromePath) {
options = {
...options,
launch_options: {
...options.launch_options,
executablePath: chromePath,
},
};
}
const pdf = await mdToPdf({ content: markdown }, options);
This injection ensures every PDF rendering operation uses the guaranteed Chrome binary, whether sourced from cache, system installation, or fresh download.
Key Implementation Files
The Chrome availability system spans four critical source files:
- src/tools/pdf/markdown.ts – Contains
ensureChromeAvailable(),getChromePath(),findPuppeteerChrome(),findSystemChrome(),installChrome(), andparseMarkdownToPdf(). - src/index.ts – Registers the initialization hook that triggers the background Chrome check.
- src/tools/filesystem.ts – Implements the
writePdftool that orchestrates PDF creation and modification. - src/server.ts – Defines the
write_pdftool schema exposed to MCP clients.
Practical Usage Examples
Creating a New PDF from Markdown
Call the write_pdf tool to generate a document from Markdown content:
// MCP client request (e.g., Claude Desktop)
write_pdf(
path="reports/summary.pdf",
content="# Quarterly Report\n\n- Revenue: $1M\n- Growth: 12%"
);
Modifying an Existing PDF
Insert or delete pages using structured content arrays:
write_pdf(
path="reports/summary.pdf",
content=[
{ type: "delete", pageIndexes: [0] },
{ type: "insert", pageIndex: 0, markdown: "# Updated Title\n\nNew intro page" }
],
outputPath="reports/summary_v2.pdf"
);
Direct Library Usage
Import the conversion helper directly for custom scripts:
import { parseMarkdownToPdf } from "./src/tools/pdf/markdown.js";
const pdfBuffer = await parseMarkdownToPdf("# Hello\n\nWorld", {});
await fs.writeFile("hello.pdf", pdfBuffer);
Summary
- Background initialization in
src/index.tstriggers Chrome discovery immediately after server startup without blocking request handling. - Three-tier fallback in
src/tools/pdf/markdown.tschecks Puppeteer caches, system installations, and downloads Chrome automatically if neither exists. - Path caching via
cachedChromePathensures subsequent PDF operations reference the executable in O(1) time. - Runtime injection passes the guaranteed Chrome path to
md-to-pdfthroughlaunch_options.executablePathduring everyparseMarkdownToPdf()call.
Frequently Asked Questions
What happens if Chrome is not installed on the system?
If findPuppeteerChrome() and findSystemChrome() both fail to locate an executable, the system automatically invokes installChrome() from @puppeteer/browsers to download a compatible Chrome binary. This ensures PDF generation proceeds without manual user intervention.
Does DesktopCommanderMCP download Chrome on every server restart?
No. The system first checks for existing Puppeteer-cached builds and system installations. Only if neither is found does it download Chrome. Furthermore, once discovered or downloaded, the path is stored in cachedChromePath, making subsequent calls instantaneous without repeating the search or download process.
Which file contains the actual PDF conversion logic?
The core conversion functions reside in src/tools/pdf/markdown.ts. This file exports parseMarkdownToPdf() and parsePdfToMarkdown(), along with the Chrome discovery utilities that ensure the conversion environment is properly configured.
Can I use a specific Chrome version with DesktopCommanderMCP?
The current implementation automatically selects or downloads a compatible version. While the getChromePath() function returns whatever Chrome it finds first in the cascade (Puppeteer cache, then system), advanced users could modify the installChrome() parameters in markdown.ts to specify particular browser versions through the @puppeteer/browsers API before compilation.
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 →