What This Is
Resume Matcher ships an MCP server. It lets Claude Code, Claude Desktop, Cursor, Codex or any other MCP client work with your resumes directly.
The split is simple. Claude (or your client’s model) writes the content. Resume Matcher stores it, checks it, scores it and renders the PDF. The server needs no AI API key, because none of its tools calls an AI model. It shares the web app’s database, so whatever Claude saves shows up in the app.
Before You Start
-
A local install. Follow Installation, then make sure the backend dependencies are synced:
cd apps/backend uv sync -
The web app running, for PDF work. PDF export,
verify_resume,tailor_and_verifyandparse_check_resumerender your resume in a browser, so they need the frontend and backend running as in the installation steps. The other tools work without them. -
Not Docker. A Docker install keeps its database inside the Docker volume, so a server started on your host would see an empty database. Docker installs aren’t supported yet.
Set Up Claude Code
Add the server with one command. Replace the path with the location of your clone:
claude mcp add resume-matcher -- uv run --directory /abs/path/to/Resume-Matcher/apps/backend resume-matcher-mcp
Then ask Claude to call get_status. It reports where the data lives and how many resumes and jobs it found.
Set Up Claude Desktop
Add this to claude_desktop_config.json, then restart Claude Desktop:
{
"mcpServers": {
"resume-matcher": {
"command": "/absolute/path/to/uv",
"args": ["run", "--directory", "/abs/path/to/Resume-Matcher/apps/backend", "resume-matcher-mcp"]
}
}
}
The file lives here:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
Use the absolute path of uv for command. Claude Desktop doesn’t inherit your shell’s PATH, so a bare uv isn’t found. Find the path with which uv on macOS or Linux, or where.exe uv on Windows. In JSON, double the backslashes in Windows paths.
Cursor, Codex and Other Clients
They use the same command and arguments:
- Command:
uv - Args:
run --directory <path>/apps/backend resume-matcher-mcp
Resume Matcher runs on donations.
More than 200,000 job seekers have used it, free, with no ads and no paywall. If it saved you time or helped you land an interview, sponsoring or buying a coffee keeps it that way.
What You Can Ask Claude
You don’t call tools yourself. You describe the job and Claude picks the tools. Some examples:
- “Import my resume from ~/Downloads/resume.pdf as a master resume.”
- “Import my resume from ~/Downloads/resume.pdf and tailor it to this job: [paste the job description]. Keep it to one page, fix anything the check flags, then export a PDF to my Desktop.”
- “Check whether an ATS can read the PDF at ~/Downloads/cv.pdf.”
- “Write a cover letter for my latest tailored resume and save it to that resume.”
Claude is told to keep your name and contact details, employers, dates and entry counts unchanged, and never to invent metrics or skills. Resume Matcher rejects a tailored save that breaks the preservation rules, and returns grounding warnings for rewrites that stray far from the source.
The Tools
The server exposes 27 tools, grouped by what they do to your data. Nothing deletes a resume or job.
Read-only (13). These never change anything.
| Tool | What it does |
|---|---|
get_status |
Data location, record counts, templates and limits. Claude calls it first. |
get_resume_schema |
The resume JSON schema plus authoring rules. |
list_resumes |
Your resumes, newest first. Masters are the tailoring sources. |
get_resume |
A resume’s data, cover letter and outreach message. |
get_job |
A stored job description with its keywords. |
get_resume_job |
The job a tailored resume was written for. |
extract_document_text |
Reads a local PDF, DOCX, DOC, MD or TXT file into markdown. |
validate_tailored_resume |
A dry run of the checks a tailored save must pass. |
score_resume |
Keyword match and ATS score for a saved resume or a draft. |
parse_check_file |
ATS parse check of a local PDF or DOCX. |
parse_check_resume |
ATS parse check of a saved resume as rendered. Needs the app running. |
verify_resume |
One render, then page count, parse check, keyword score and issues. Needs the app running. |
list_applications |
Tracker cards, optionally for one column. |
Adds new records, or refreshes a value that can be recomputed (6).
| Tool | What it does |
|---|---|
create_master_resume |
Creates a master resume from structured data Claude built. |
add_job |
Stores a job description, with the keywords Claude extracted for scoring. |
save_tailored_resume |
Saves a tailored resume as a new version. Rejected if it breaks the checks. |
tailor_and_verify |
Validates, saves and verifies a tailored resume in one call. |
recalculate_ats_score |
Recomputes and stores a tailored resume’s ATS score, like the builder’s Recalculate button. |
create_application |
Adds a tracker card. |
Overwrites what’s stored (8). These are marked as destructive in MCP, so your client may ask you to approve them.
| Tool | What it does |
|---|---|
update_resume |
Replaces a resume’s structured data. |
set_resume_title |
Renames a resume (80 characters at most). |
set_cover_letter |
Stores a cover letter, replacing the old one. |
set_outreach_message |
Stores an outreach message, replacing the old one. |
set_default_master |
Makes a master the default tailoring source. |
set_job_keywords |
Attaches keywords to a job, replacing the old ones. |
export_resume_pdf |
Renders a saved resume to PDF. Overwrites any file already at that path. Needs the app running. |
update_application |
Moves or edits a tracker card. |
Pick the target before an overwrite: look at what’s there first. tailor_and_verify and save_tailored_resume never overwrite anything, because they add a new tailored resume.
The Typical Flow
Claude’s built-in instructions walk it through these steps:
- Look around.
get_status, thenlist_resumesandget_resume. To import a file:extract_document_text,get_resume_schema, thencreate_master_resume. - Add the job.
add_jobwith the job description and the keywords Claude pulled out of it. - Write the tailored resume from the source resume.
- Tailor and verify.
tailor_and_verifyvalidates the draft, saves it, renders it once, parse-checks it and scores it. Ifsavedis false, nothing was written: Claude fixes the violations and calls it again. - Fix the issues. For each code in
issues, Claude edits withupdate_resumeand checks again withverify_resume.recalculate_ats_scorerefreshes the score the builder shows after edits. - Export.
export_resume_pdfwrites the final file. Without an output path it goes to anexportsfolder inside the data folder.
A saved tailored resume appears in the web app like any other. If the job has keywords, the save stores its ATS score, and unless Claude turns it off, it adds a card to the Applied column of the application tracker.
If verification fails after the save, the result says saved: true with a verify_error. Claude shouldn’t save again; it calls verify_resume instead.
Issue Codes
verify_resume and tailor_and_verify list what needs attention in issues:
| Code | What it means |
|---|---|
over_page_limit |
The PDF has more pages than the max_pages Claude asked for. |
text_layer |
The PDF has too little extractable text, under 50 visible characters. |
multi_column |
The parse check found a multi-column layout. |
garbled_glyphs |
The extracted text contains garbled characters (the check warned or failed). |
low_order_fidelity |
The PDF’s reading order scores below 0.9 against your resume’s data. |
fields_missing |
A field from your resume’s data is missing or garbled in the PDF text. |
roundtrip_truncated |
The round trip stopped at its limit of 300 fields, so later fields weren’t checked. |
injectable_keywords |
Job keywords your master resume already supports, but this resume lacks. |
render_failed |
The PDF couldn’t be rendered. The keyword score is still returned. |
On multi_column or low_order_fidelity, Claude is told to suggest a single-column template. See PDF Templates for the options. The round trip checks Resume Matcher’s own render against your data. It isn’t a test against a real ATS.
Limits
- Five master resumes.
create_master_resumefails once you have five. Delete one in the web app first. - Imports up to 4 MB.
extract_document_textandparse_check_fileread files up to 4 MB. Import takes PDF, DOCX, DOC, MD and TXT. Parse check takes PDF and DOCX. - One database. The server uses the same database as the web app when both run from the same checkout.
DATA_DIRmoves the SQLite file.DATABASE_URLselects PostgreSQL instead, see Use PostgreSQL Instead of SQLite.
Troubleshooting
Claude Desktop can’t start the server or can’t find uv
Put the absolute path of uv in command, as shown above, and restart Claude Desktop. A bare uv only works where your shell’s PATH is inherited.
PDF tools fail with “PDF rendering failed”
Start the web app. The message names the frontend address it tried, http://localhost:3000 by default. If yours runs elsewhere, set FRONTEND_BASE_URL in apps/backend/.env. Also run the Playwright Chromium step in Installation, unless Chrome or Edge is installed. verify_resume and tailor_and_verify still return the keyword score. tailor_and_verify has already saved the resume, so once the app is up, call verify_resume instead of saving again.
Claude sees no resumes, but the web app has them
The server is using a different database. Ask Claude to call get_status. It reports data_dir, the record counts and backend (sqlite or postgresql). If the counts don’t match your dashboard, the web app is running from a different checkout, or DATA_DIR or DATABASE_URL differ between the two. That is the case for Docker installs, since their data sits in the Docker volume.
“Database is busy. Retry the same call.”
Another write was in progress. Ask Claude to repeat the call.
Next Steps
- Installation for the local setup the server needs
- Features for what you can do in the web app with the same resumes
- Use PostgreSQL Instead of SQLite to point the app and the server at a PostgreSQL database