PDFs are everywhere in business workflows — invoices, reports, contracts, forms. But if you've ever tried to manipulate PDFs programmatically, you know it's a mess. Libraries are either Java-based behemoths, require native binaries, or silently corrupt your files.
I wanted to build something for the MCP ecosystem that actually works. A server where an AI assistant can say "merge these three invoices, add page numbers, and encrypt the result" — and it just happens.
So I built pdf-toolkit-mcp: 16 tools for creating, reading, and manipulating PDFs, published as an npm package, and built entirely with Claude Code in two days.
What It Does
The server exposes 16 tools that any MCP client (Claude Desktop, Cursor, Windsurf, VS Code, etc.) can call:
Read operations:
- Extract text from any PDF
- Get metadata (author, title, page count, creation date)
- Get form field names and values
- Count pages
Write operations:
- Create PDFs from Markdown (tables, headers, code blocks, lists — all formatted)
- Create from templates (invoice, report, letter)
- Merge multiple PDFs into one
- Split a PDF into individual pages
- Rotate pages (90°, 180°, 270°)
- Add text watermarks
- Embed images
- Fill form fields
- Add page numbers
- Embed QR codes
- Encrypt with password protection
- Reorder pages
Every write tool returns the output path, page count, and file size. Every tool has MCP annotations so clients know which tools are read-only and which modify files.
The Tech Stack Decisions
This is where it gets interesting. Most PDF libraries in the Node ecosystem have serious problems:
pdf-lib (the popular one) can't do Markdown-to-PDF. It gives you low-level drawing primitives — you're manually positioning text, calculating line breaks, handling pagination yourself. Fine for stamping a watermark, terrible for generating a report from Markdown.
puppeteer/playwright route works but requires a headless browser. That's 200+ MB of Chromium bundled into what should be a lightweight MCP server. Startup time alone kills the developer experience.
Here's what I landed on:
- @pdfme/pdf-lib — fork of pdf-lib with better maintenance. Handles merge, split, rotate, metadata, form filling, text extraction.
-
pdfmake — the real find. It takes a JSON document definition and produces a PDF buffer. No browser, no native binaries, pure JavaScript. I pipe Markdown → HTML (via
marked) → pdfmake definitions (viahtml-to-pdfmake+jsdom) → PDF buffer. - unpdf — lightweight PDF text extraction that doesn't need native modules.
- fontkit v2 — font handling without the C++ binding nightmares.
- @modelcontextprotocol/sdk v1.29.0 — the official MCP SDK for TypeScript.
The entire package is under 100 kB on npm. No native dependencies. No Chromium. Works on Windows, macOS, and Linux without any platform-specific setup.
How I Actually Built It
I used Claude Code (the terminal-based coding agent) for the entire implementation. Not as a code suggestion tool — as the builder. Here's how the workflow looked:
Day 1 (evening session, ~8 hours): I planned the architecture in Claude AI (chat), then generated a detailed prompt file. Opened Claude Code in the terminal, pointed it at the prompt, and let it scaffold the project: TypeScript config, MCP server boilerplate, tool registration, all 10 initial tools, and 30 tests. Reviewed, tested, fixed edge cases, published v0.1.0 to npm by midnight.
Day 2 (morning session, ~2.5 hours): Six more tools — Markdown-to-PDF creation, templates, encryption, QR codes, page numbers, page reordering. This was harder because the PDF creation pipeline (Markdown → HTML → pdfmake → buffer) required debugging font registration, JSDOM memory leaks, and pdfmake's quirks with table rendering. Added 21 more tests (51 total), security hardening, README rewrite, published v0.2.0 by afternoon.
The key insight: planning is the bottleneck, not coding. I spent more time deciding the tech stack and designing the tool interfaces than I did writing code. Claude Code is fast at implementation but it can't tell you what to build or why to use pdfmake over Puppeteer. That's still your job.
Quick Start
Install and run with a single command:
npx -y @aryanbv/pdf-toolkit-mcp
Or add it to your MCP client config. Here's the Claude Desktop example (claude_desktop_config.json):
{
"mcpServers": {
"pdf-toolkit": {
"command": "npx",
"args": ["-y", "@aryanbv/pdf-toolkit-mcp"]
}
}
}
Works the same way for Cursor, Windsurf, VS Code with Copilot, or any MCP-compatible client.
Example: Generate an Invoice From a Conversation
Once configured, you can ask your AI assistant:
"Create an invoice for Acme Corp. 3 line items: Web Development ($5,000), API Integration ($2,500), Testing ($1,200). 18% GST. Save to ~/invoices/acme-march.pdf"
The assistant calls pdf_create_from_template with the invoice template, and you get a formatted PDF with company header, line items table, subtotal, tax calculation, and grand total.
Or chain multiple tools:
"Take the quarterly report markdown I just wrote, create a PDF, add page numbers, embed our company QR code on the first page, and encrypt it with password 'Q1-2026'"
Four tool calls, executed in sequence, final encrypted PDF ready to share.
What I Learned
The MCP ecosystem is real. Within a day of publishing v0.1.0 to npm, I had nearly 100 weekly downloads — without any marketing or blog post. People are actively searching for MCP servers that solve specific problems.
PDF is an underserved niche in MCP. There are hundreds of MCP servers for databases, web scraping, and API integrations. Very few handle document creation and manipulation. If you're looking for an MCP server to build, look at the gaps, not the crowded categories.
TypeScript-native matters for MCP. The MCP SDK is TypeScript-first. Going with a Python PDF library would've meant a separate runtime, IPC overhead, and packaging complexity. Keeping everything in the TypeScript ecosystem means the server starts in under a second and the package stays tiny.
Ship, then distribute. I spent two days building and one day submitting to every registry I could find: the official MCP registry, Glama, mcp.so, PulseMCP, awesome-mcp-servers, mcpservers.org. Registry listings are free and compound over time as people search for "pdf mcp server."
Try It
- npm: @aryanbv/pdf-toolkit-mcp
- GitHub: AryanBV/pdf-toolkit-mcp
If you're building with MCP clients and deal with PDFs at all, give it a try. Issues and PRs welcome.
I'm Aryan, a full-stack developer based in Bangalore building Prevyl, an export-tech SaaS platform. This was my first open-source MCP server, built to learn the protocol and contribute something useful to the ecosystem. You can find me on GitHub and LinkedIn.
Top comments (0)