resume-pdf-mcp
Compiles LaTeX resumes into PDFs via MCP tools, including validation, preview, template compilation, and LaTeX export, with security defaults like path isolation and no shell escapes.
README
resume-pdf-mcp
Production-grade Model Context Protocol (MCP) server that compiles LaTeX resumes into PDFs.
GitHub: https://github.com/shashimehta03/mcp-resume
Works with Claude Desktop, Claude Code, Cursor, VS Code, and any MCP-compatible client.
What it does
Exposes MCP tools so your AI client can:
| Tool | Purpose |
|---|---|
compile_resume |
Compile LaTeX → PDF (XeLaTeX or pdfLaTeX) |
validate_resume |
Check LaTeX before compile (structure + safety) |
preview_resume |
Page count, PDF size, compile duration |
export_tex |
Save .tex into the output folder |
list_templates |
List built-in resume templates |
compile_template |
Fill a template with JSON variables → PDF |
version |
Server / engine / build info |
Security defaults: filename sanitization, path isolation, no shell interpolation, -no-shell-escape, size/timeout limits, stderr-only logging (LaTeX source is never logged in full).
Complete setup checklist (follow in order)
Do every step once after cloning. Details for each step are in the sections below.
- Install Node.js 20+ and a LaTeX engine (
pdflatexand/orxelatex) — see Requirements - Clone the repo and run
npm installthennpm run build— see Clone and install - Confirm build output exists:
dist/index.jsanddist/templates/must be present - Note your absolute paths: Node binary + clone folder — see What you must change after cloning
- Configure your MCP host (pick one):
- Claude Desktop → Configure Claude Desktop
- Cursor → Configure Cursor
- Claude Code → Configure Claude Code
- Replace every example path in the config with your paths (Windows: use
\\in JSON) - Do not leave
npm startrunning — Claude/Cursor start the server themselves - Fully quit and reopen the host app (Claude: tray → Quit, not just close the window)
- Verify the server is running (Claude: Settings → Developer →
resume-pdf= running) - Use Chat mode (Claude Desktop) — Cowork/Code may ignore this MCP server
- Smoke-test in chat: ask Claude/Cursor to call the
versiontool - Optional: run
npm run test:toolslocally to confirm TeX works without an MCP host
After you change code later: npm run build → quit/reopen the MCP host again.
Requirements
- Node.js 20+ (22 LTS recommended)
- A LaTeX engine on PATH
- Windows: MiKTeX or TeX Live (
pdflatex/xelatex) - macOS:
brew install --cask mactex-no-gui(or BasicTeX) - Linux:
texlive-xetex/texlive-latex-recommended
- Windows: MiKTeX or TeX Live (
Verify:
node -v
pdflatex --version
# and/or
xelatex --version
Clone and install (do this first)
git clone https://github.com/shashimehta03/mcp-resume.git
cd mcp-resume
npm install
npm run build
Confirm the build:
# Windows PowerShell
Test-Path .\dist\index.js
Test-Path .\dist\templates\index.json
# macOS / Linux
ls dist/index.js dist/templates/index.json
Optional local env file (MCP hosts do not auto-load .env — still set env in their JSON):
cp .env.example .env
You do not need to keep npm start running for Claude/Cursor. Those apps spawn the server themselves. Only run npm start / npm run test:tools for local smoke tests.
What you must change after cloning
Repo examples keep sample paths on purpose. After clone, change them to your machine.
| What | Default in repo / examples | Change to |
|---|---|---|
| Project folder | E:\\mcp_resume / /Users/YOU/mcp-resume |
Where you cloned the repo |
args entrypoint |
.../dist/index.js |
<your-clone>/dist/index.js (after npm run build) |
OUTPUT_DIR |
./output or example absolute path |
<your-clone>/output (use absolute in MCP hosts) |
TEMP_DIR |
./temp |
<your-clone>/temp |
TEMPLATES_DIR |
dist/templates |
<your-clone>/dist/templates (or leave unset) |
command (Node) |
node or C:\\Program Files\\nodejs\\node.exe |
Full path to node (Claude Desktop usually needs the full path) |
DEFAULT_ENGINE |
xelatex in .env.example, pdflatex in some examples |
Whichever engine you installed |
cwd (optional) |
project root | Same as your clone path |
More notes: examples/README.md.
Find your paths
Windows (PowerShell):
# Node
(Get-Command node).Source
# Project (run from inside the clone)
(Get-Location).Path
# Real Claude config path on Microsoft Store / MSIX installs
$pkg = (Get-AppxPackage -Name "*Claude*").PackageFamilyName
Join-Path $env:LOCALAPPDATA "Packages\$pkg\LocalCache\Roaming\Claude\claude_desktop_config.json"
macOS / Linux:
which node
pwd # from inside the clone
# Config is usually:
# ~/Library/Application Support/Claude/claude_desktop_config.json (macOS)
Windows JSON tip: every backslash in a path must be doubled: E:\\mcp_resume\\dist\\index.js.
Configure Claude Desktop
1) Build the project
npm install
npm run build
2) Open the config Claude actually reads
In Claude Desktop:
Settings → Desktop app → Developer → Edit Config
That opens claude_desktop_config.json.
Windows Microsoft Store / MSIX builds (important)
“Edit Config” may open:
%APPDATA%\Claude\claude_desktop_config.json
…but the app often reads:
%LOCALAPPDATA%\Packages\Claude_*\LocalCache\Roaming\Claude\claude_desktop_config.json
Edit the LocalCache file (or copy your finished config into both).
If you only edit the %APPDATA% file, Claude may ignore your server with no error.
Details: MSIX config path issue.
3) Add the server (merge into existing JSON)
If the file already has preferences / coworkUserFilesPath, keep them. Only add or update the top-level mcpServers key (do not paste a second { ... } object).
Valid shape (copy, then replace paths):
{
"mcpServers": {
"resume-pdf": {
"command": "C:\\Program Files\\nodejs\\node.exe",
"args": ["E:\\mcp_resume\\dist\\index.js"],
"cwd": "E:\\mcp_resume",
"env": {
"OUTPUT_DIR": "E:\\mcp_resume\\output",
"TEMP_DIR": "E:\\mcp_resume\\temp",
"TEMPLATES_DIR": "E:\\mcp_resume\\dist\\templates",
"DEFAULT_ENGINE": "pdflatex",
"LOG_LEVEL": "info",
"NODE_ENV": "production"
}
}
}
}
What to change in that block (defaults left above on purpose):
| Key | Change? |
|---|---|
command |
Yes → your node.exe / node absolute path |
args[0] |
Yes → your clone’s dist/index.js |
cwd |
Yes → your clone folder |
OUTPUT_DIR / TEMP_DIR / TEMPLATES_DIR |
Yes → folders under your clone |
DEFAULT_ENGINE |
If needed → pdflatex or xelatex |
LOG_LEVEL / NODE_ENV |
Optional |
macOS / Linux example (same keys — only paths change):
{
"mcpServers": {
"resume-pdf": {
"command": "/usr/local/bin/node",
"args": ["/Users/YOU/mcp-resume/dist/index.js"],
"cwd": "/Users/YOU/mcp-resume",
"env": {
"OUTPUT_DIR": "/Users/YOU/mcp-resume/output",
"TEMP_DIR": "/Users/YOU/mcp-resume/temp",
"TEMPLATES_DIR": "/Users/YOU/mcp-resume/dist/templates",
"DEFAULT_ENGINE": "xelatex",
"LOG_LEVEL": "info"
}
}
}
}
Repo template: examples/claude-desktop-config.json.
4) Fully quit and reopen Claude
Closing the window is not enough. Use the tray / menu bar → Quit, confirm no Claude process is left, then start Claude again.
MCP servers are loaded only at startup.
5) Verify
- Settings → Developer → Local MCP servers
- Select
resume-pdf - Status should be running (not failed / disconnected)
- If failed: open View Logs on that server
- Start a new Chat (not Cowork, not Code)
- Ask:
Call the resume-pdf version tool and show the result.
To steer Claude every time:
Always use resume-pdf MCP tools (compile_resume, validate_resume, compile_template)
for any resume/LaTeX/PDF work. Do not compile LaTeX yourself in the sandbox.
PDFs land in your OUTPUT_DIR (for example <clone>/output).
Optional: install as a Claude Desktop Extension
If the JSON mcpServers entry does not stay connected on your Claude build:
npm run build
npm run install:claude
Then fully quit/reopen Claude and check Settings → Developer / Extensions for Resume PDF (enabled).
Before relying on that helper on another machine, point these at your clone (repo defaults are examples — leave them until you change them):
mcpb/manifest.json→user_config.*.defaultmcpb/server/index.js→ fallbackRESUME_PDF_MCP_ROOT
Configure Cursor
- Open Cursor MCP settings (or project
.cursor/mcp.json/ global MCP config, depending on your Cursor version). - Add a server entry like:
{
"mcpServers": {
"resume-pdf": {
// CHANGE: "node" is usually fine in Cursor if Node is on PATH
"command": "node",
// CHANGE: absolute path to YOUR clone
"args": ["E:/mcp_resume/dist/index.js"],
"env": {
// CHANGE these to YOUR clone paths
"OUTPUT_DIR": "E:/mcp_resume/output",
"TEMP_DIR": "E:/mcp_resume/temp",
"DEFAULT_ENGINE": "pdflatex"
}
}
}
}
See also examples/cursor-mcp.json.
Restart Cursor / reload MCP servers after saving.
Configure Claude Code
Add to your Claude Code MCP config (see examples/claude-code-mcp.json):
{
"mcpServers": {
"resume-pdf": {
"command": "node",
// CHANGE: YOUR clone's dist entry
"args": ["./dist/index.js"],
// CHANGE: YOUR clone directory
"cwd": "/absolute/path/to/mcp-resume",
"env": {
"DEFAULT_ENGINE": "xelatex",
"OUTPUT_DIR": "./output",
"TEMP_DIR": "./temp"
}
}
}
}
Or from the project folder:
claude mcp add resume-pdf -- node ./dist/index.js
(Adjust to your Claude Code version’s exact mcp add syntax.)
Environment variables
Copy .env.example. Values below are defaults — change only if you need to.
| Variable | Default | Notes |
|---|---|---|
OUTPUT_DIR |
./output |
Prefer absolute path in MCP host env |
TEMP_DIR |
./temp |
Per-request workspaces |
DEFAULT_ENGINE |
xelatex |
Use pdflatex if XeLaTeX isn’t installed |
MAX_LATEX_SIZE |
512000 |
Max LaTeX source bytes |
COMPILE_TIMEOUT |
60000 |
Compile timeout (ms) |
MAX_MEMORY_MB |
1024 |
Soft memory guidance |
LOG_LEVEL |
info |
silent | error | warn | info | debug |
TEMPLATES_DIR |
dist/templates (runtime) |
Override if you move templates |
KEEP_TEMP_ON_FAILURE |
false |
Set true to debug failed compiles |
MCP hosts pass these via the env block in their JSON config (they do not automatically load .env).
How to use (from the AI chat)
Once the server is running in the client:
Compile raw LaTeX
Use compile_resume with engine pdflatex and this LaTeX:
\documentclass{article}
\begin{document}
Hello from resume-pdf-mcp
\end{document}
Validate first
Use validate_resume on this LaTeX before compiling: ...
Use a template
Use list_templates, then compile_template with template_name "modern-simple"
and variables for name, email, summary, skills, experience, education.
Example payload shape: examples/sample-template-request.json.
Expected success response
{
"success": true,
"pdf_path": ".../output/resume.pdf",
"tex_path": ".../output/resume.tex",
"compilation_logs": "...",
"execution_time": 0.82
}
Local testing (without Claude)
npm test # unit + integration
npm run test:coverage
npm run test:tools # hits all tools; watch USAGE logs on stderr
npm run test:smoke # compile minimal-ats template once
Docker
docker compose build
docker compose run --rm resume-pdf-mcp
Image includes TeX Live. See docs/docker.md.
For Claude Desktop via Docker, point command at docker and pass your compose/run args (stdio must stay attached).
Project layout
src/ TypeScript source (tools, services, latex, config)
dist/ Build output (what MCP hosts should run)
mcpb/ Claude Desktop extension manifest + launcher
examples/ Sample MCP configs and requests
docs/ Installation, usage, architecture, contributing
tests/ Vitest suite
output/ Generated PDFs/TeX (gitignored contents)
temp/ Compile workspaces (gitignored contents)
Architecture:
Tool → ResumeService → LatexCompiler → FileSystemService → XeLaTeX/pdfLaTeX
Troubleshooting
| Problem | Fix |
|---|---|
| Tool not in Claude | Use Chat mode; fully Quit/reopen; confirm Developer shows running |
| Config saved but ignored (Windows) | Edit the MSIX LocalCache\Roaming\Claude\claude_desktop_config.json path |
ENGINE_NOT_FOUND |
Install MiKTeX/TeX Live; put pdflatex/xelatex on PATH; set DEFAULT_ENGINE |
Server disconnected |
Rebuild (npm run build); use full node path; set cwd; Quit Claude and reopen |
| Claude compiles in sandbox instead | Server not connected — fix Developer status; instruct Claude to use compile_resume |
| Wrong output folder | Set absolute OUTPUT_DIR in the MCP env block |
Logs (Windows MSIX):
%LOCALAPPDATA%\Packages\Claude_*\LocalCache\Roaming\Claude\logs\mcp-server-resume-pdf.log
Documentation
Development scripts
npm run dev # tsx stdio server
npm run build
npm start
npm run lint
npm run typecheck
npm run install:claude # install local Claude Desktop extension helper
License
MIT — see LICENSE.
Links
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。