Server-side PDF generation via Model Context Protocol (MCP)
This MCP server enables Claude Desktop and other MCP clients to generate professional PDFs from HTML content server-side, with all the features of the client-side library.
Model Context Protocol (MCP) is an open protocol that enables seamless integration between LLM applications and external data sources and tools. This MCP server exposes PDF generation capabilities to Claude Desktop and other MCP clients.
- Server-Side PDF Generation - Generate PDFs without browser dependencies
- Full Feature Support - All features from the client-side library
- File System Integration - Save PDFs directly to disk
- Claude Desktop Integration - Use with Claude Desktop via MCP
- Token-Efficient Design - Optimized for minimal token usage
-
Main Package Built: The MCP server depends on the built main package
# From the root of the repository pnpm install pnpm run build -
MCP Server Dependencies: Install MCP server dependencies
cd mcp pnpm install pnpm run build
Add to your Claude Desktop configuration (~/Library/Application Support/Claude/claude_desktop_config.json on macOS):
{
"mcpServers": {
"html-to-pdf": {
"command": "node",
"args": [
"/path/to/html-to-pdf-generator/mcp/dist/index.js"
]
}
}
}After restarting Claude Desktop, you can use PDF generation commands:
Example Conversation:
You: Generate a PDF with a title "Hello World" and save it to /tmp/hello.pdf
Claude: I'll generate that PDF for you.
[Uses generate_pdf tool]
PDF generated successfully!
- File: /tmp/hello.pdf
- Size: 15.2 KB
- Format: A4 Portrait
Run the MCP server directly:
cd mcp
pnpm startThe server communicates via stdio and follows the MCP protocol.
The MCP server provides three token-efficient tools for PDF generation:
Generate a PDF from HTML content or template. Supports all PDF features including watermarks, headers/footers, metadata, and image optimization.
Parameters:
html(string, required): HTML content or template- Templates support
{{variables}},{{#each array}}...{{/each}},{{#if condition}}...{{/if}}
- Templates support
outputPath(string, required): Absolute path for the output PDFtemplateContext(object, optional): Variables for template substitutionoptions(object, optional): PDF generation optionsformat: Paper format ('a4' | 'letter' | 'a3' | 'legal')orientation: Page orientation ('portrait' | 'landscape')margins: Margins in mm [top, right, bottom, left]showPageNumbers: Show page numbers (boolean)scale: Scale factor 1-4 for qualityimageQuality: Image quality 0-1watermark: Watermark configuration (text or image)headerTemplate/footerTemplate: Dynamic headers/footersmetadata: PDF metadata (title, author, subject, keywords, creator)emulateMediaType: 'screen' or 'print' for CSSimageOptions: Image processing (dpi, format, backgroundColor, optimizeForPrint)
Example (Basic HTML):
{
"html": "<h1>Hello World</h1><p>This is a PDF.</p>",
"outputPath": "/tmp/document.pdf",
"options": {
"format": "a4",
"orientation": "portrait",
"margins": [10, 10, 10, 10],
"showPageNumbers": true,
"metadata": {
"title": "My Document",
"author": "John Doe"
}
}
}Example (Template with Variables):
{
"html": "<h1>{{title}}</h1>{{#each items}}<p>{{name}}: ${{price}}</p>{{/each}}",
"outputPath": "/tmp/invoice.pdf",
"templateContext": {
"title": "Invoice #1234",
"items": [
{"name": "Item 1", "price": "10.00"},
{"name": "Item 2", "price": "20.00"}
]
},
"options": {
"format": "a4",
"metadata": {"title": "Invoice #1234"}
}
}Response:
{
"success": true,
"message": "PDF generated successfully",
"filePath": "/tmp/document.pdf",
"fileSize": 15432,
"format": "a4",
"orientation": "portrait",
"generationTime": "1823ms"
}Generate a single PDF from multiple HTML content items with automatic scaling. Each item can specify a target page count, and content will be auto-scaled to fit. Ideal for multi-section reports, invoices, or documents.
Parameters:
items(array, required): Array of content items- Each item has:
html(string, required): HTML content for this itempageCount(number, required): Target page count (content will be scaled to fit)title(string, optional): Title for this sectionnewPage(boolean, optional): Control page breakstrue: Force item to start on a new pagefalse: Allow item to share page with previous contentundefined(default): Add page break after each item
- Each item has:
outputPath(string, required): Absolute path for the output PDFoptions(object, optional): Same PDF options asgenerate_pdf
Example:
{
"items": [
{
"html": "<h1>Section 1: Executive Summary</h1><p>Long content...</p>",
"pageCount": 2,
"title": "Executive Summary",
"newPage": true
},
{
"html": "<h1>Section 2: Details</h1><p>More content...</p>",
"pageCount": 3,
"title": "Details",
"newPage": true
}
],
"outputPath": "/tmp/report.pdf",
"options": {
"format": "a4",
"showPageNumbers": true,
"metadata": {"title": "Multi-Section Report"}
}
}Response:
{
"success": true,
"message": "Batch PDF generated successfully",
"filePath": "/tmp/report.pdf",
"fileSize": 245678,
"totalPages": 5,
"itemCount": 2,
"items": [
{"index": 0, "pageCount": 2, "startPage": 1, "endPage": 2},
{"index": 1, "pageCount": 3, "startPage": 3, "endPage": 5}
],
"generationTime": "2341ms"
}Generate PDF from a URL. CORS-aware - only works with same-origin or CORS-enabled URLs. Supports waiting for selectors and injecting custom CSS/JS.
Parameters:
url(string, required): URL to convert to PDF (must be same-origin or CORS-enabled)outputPath(string, required): Absolute path for the output PDFurlOptions(object, optional): URL-specific optionswaitForSelector(string): CSS selector to wait for before capturetimeout(number): Max wait time in ms (default: 10000)injectCSS(string): Custom CSS to inject into pageinjectJS(string): Custom JavaScript to execute
options(object, optional): Same PDF options asgenerate_pdf
Example:
{
"url": "https://example.com/page",
"outputPath": "/tmp/webpage.pdf",
"urlOptions": {
"waitForSelector": ".content-loaded",
"timeout": 15000,
"injectCSS": ".no-print { display: none; }"
},
"options": {
"format": "a4",
"emulateMediaType": "print"
}
}Response:
{
"success": true,
"message": "PDF from URL generated successfully",
"filePath": "/tmp/webpage.pdf",
"fileSize": 123456,
"pageCount": 3,
"sourceURL": "https://example.com/page",
"generationTime": "3245ms"
}Add text watermarks to your PDFs:
{
"html": "<h1>Confidential Document</h1>",
"outputPath": "/tmp/confidential.pdf",
"options": {
"watermark": {
"text": "CONFIDENTIAL",
"opacity": 0.3,
"fontSize": 48,
"color": "#ff0000",
"position": "diagonal"
}
}
}Use inline CSS or style tags in your HTML:
{
"html": "<style>h1{color:blue;}</style><h1>Styled Title</h1>",
"outputPath": "/tmp/styled.pdf"
}The MCP server supports all features from the main library:
- ✅ Watermarks (text & image)
- ✅ Headers/Footers with templates
- ✅ PDF Metadata
- ✅ Print Media CSS
- ✅ Template Variables
- ✅ Font Handling
- ✅ Table of Contents
- ✅ Bookmarks
- ✅ Enhanced Image Optimization (DPI, format, transparency)
pnpm run buildpnpm run devTest the MCP server with the MCP Inspector:
npx @modelcontextprotocol/inspector node dist/index.jsEnsure the main package is built:
cd .. # Go to root directory
pnpm run build- Check the config file path is correct
- Ensure the absolute path to
dist/index.jsis correct - Restart Claude Desktop completely
- Check logs in
~/Library/Logs/Claude/(macOS)
Ensure the output directory exists and has write permissions:
mkdir -p /tmp/pdfs
chmod 755 /tmp/pdfsIssues and pull requests are welcome! Please see the main repository CONTRIBUTING.md for guidelines.
MIT License - See LICENSE for details.
Part of HTML to PDF Generator - A modern, framework-agnostic library for professional PDF generation.