Deep resume parsing • ATS compatibility scoring • Actionable improvement insights
An agent skill, CLI tool, npm library, and MCP server that deeply parses resumes using the OpenResume 4-step algorithm, extracts structured information (Name, Email, Phone, Education, Work Experience, Skills, Projects), evaluates ATS compatibility, and provides prioritized, actionable suggestions.
Made with ❤️ by Dhanush Kandhan
- 🔍 Deep Parsing — Extracts 10+ fields from raw text or PDF using a feature-scoring engine
- 📊 ATS Scoring — Grades your resume A+ through F with per-field confidence ratings
- 💡 Smart Suggestions — Prioritized, categorized fixes (critical → low) with before/after examples
- 🤖 Agent Skill — Install via
npx skills addfor pi, Claude Code, Codex, Gemini CLI, and more - 🖥️ CLI — Use directly from the command line
- 📡 MCP Server — Plug into Claude Desktop, ChatGPT, and other MCP-compatible apps
- 📖 Library — Import as an npm package for programmatic use
- ⚙️ Configurable — Lenient, moderate, or strict ATS evaluation modes
- 🔒 Privacy-first — Runs entirely locally, no external API calls
Choose how you want to use Resume Parser:
| Method | Install | Best for |
|---|---|---|
| Agent Skill | npx skills add dhanushk-offl/resume-parser |
AI agents (pi, Claude Code, Codex, Gemini CLI) |
| CLI | npm install -g resume-parser-ats |
Quick one-off resume analysis |
| Library | npm install resume-parser-ats |
Building apps, batch processing |
| MCP Server | claude mcp add resume-parser -- npx -y resume-parser-ats --mcp |
Claude Code, Codex, Claude Desktop, Cursor |
Install as an agent skill for automatic activation in AI coding assistants:
npx skills add dhanushk-offl/resume-parserOnce installed, the skill activates automatically when you:
- Ask to parse, review, or analyze a resume
- Ask "is my resume ATS-friendly?"
- Ask for resume improvement suggestions
- Upload or reference a resume PDF
Works with: pi, Claude Code, OpenAI Codex, Gemini CLI, Cursor, Continue, and all Agent Skills compatible tools.
| Tool | Description |
|---|---|
parse_resume |
Parse a resume PDF/text → structured data |
analyze_resume |
Parse + compute ATS compatibility score with per-field confidence |
suggest_improvements |
Parse + analyze + generate prioritized improvement suggestions |
"Is my resume ATS-friendly? Here's the PDF path: ./my-resume.pdf"
"Parse this resume and extract the contact info"
"Analyze my resume for ATS compatibility with strict grading"
"What can I improve on my resume to get past ATS filters?"
Install globally for command-line use:
npm install -g resume-parser-ats# Parse a resume and output structured data
resume-parser-ats parse resume.pdf
# Parse + analyze ATS compatibility
resume-parser-ats analyze resume.pdf
# Full pipeline: parse + analyze + suggestions
resume-parser-ats insights resume.pdf
# Parse from raw text
resume-parser-ats parse "John Doe\njohn@email.com\nSoftware Engineer"
# Adjust ATS strictness
resume-parser-ats analyze resume.pdf --strictness strict
# Focus on specific areas
resume-parser-ats insights resume.pdf --focus ats,formatting
# Output as JSON
resume-parser-ats insights resume.pdf --jsonOr use without installing:
npx resume-parser-ats parse resume.pdfInstall as a dependency for programmatic use:
npm install resume-parser-atsimport { parseResume, analyzeResume, suggestImprovements } from "resume-parser-ats";
// Parse — extract structured data
const parsed = parseResume({ filePath: "./resume.pdf" });
// or: parseResume({ rawText: "John Doe\njohn@email.com\n..." })
console.log(parsed.data.profile.name); // "Jane Doe"
console.log(parsed.data.profile.email); // "jane@example.com"
console.log(parsed.data.education[0]?.school); // "MIT"
// Analyze — ATS compatibility scoring
const analysis = analyzeResume({
filePath: "./resume.pdf",
parsedResume: parsed.data,
strictness: "strict",
});
console.log(analysis.data.atsScore); // 72
console.log(analysis.data.atsGrade); // "B-"
console.log(analysis.data.fieldAnalyses);
console.log(analysis.data.formatIssues);
// Suggest — prioritized improvement recommendations
const suggestions = suggestImprovements({
filePath: "./resume.pdf",
parsedResume: parsed.data,
analysisResult: analysis.data,
focusAreas: ["ats", "content", "formatting"],
});
console.log(suggestions.data.quickWins);
console.log(suggestions.data.suggestions);import { fullPipeline } from "resume-parser-ats";
const { parsed, analyzed, suggestions } = fullPipeline({
filePath: "./resume.pdf",
strictness: "moderate",
});
console.log(`ATS Score: ${analyzed.data.atsScore}/100 (${analyzed.data.atsGrade})`);All types are exported:
import type {
ParseResumeInput,
ParseResumeOutput,
AnalyzeResumeInput,
AnalyzeResumeOutput,
SuggestImprovementsInput,
SuggestImprovementsOutput,
ParsedResume,
TextItem,
LineItem,
SectionItem,
} from "resume-parser-ats";Use Resume Parser as a Model Context Protocol (MCP) server to give AI assistants direct access to the parsing tools.
One command to add to each app:
# Claude Code
claude mcp add resume-parser -- npx -y resume-parser-ats --mcp
# OpenAI Codex
codex mcp add resume-parser -- npx -y resume-parser-ats --mcpThat's it. Restart the app and the tools are available.
claude mcp add resume-parser -- npx -y resume-parser-ats --mcpAdd to a specific scope:
# User scope (available in all projects)
claude mcp add --scope user resume-parser -- npx -y resume-parser-ats --mcp
# Project scope (available in current project only)
claude mcp add --scope project resume-parser -- npx -y resume-parser-ats --mcpRemove with:
claude mcp remove resume-parsercodex mcp add resume-parser -- npx -y resume-parser-ats --mcpRemove with:
codex mcp remove resume-parserAdd to your Claude Desktop config file:
macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
Windows: %APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"resume-parser": {
"command": "npx",
"args": ["-y", "resume-parser-ats", "--mcp"]
}
}
}Restart Claude Desktop. You can now ask Claude to parse and analyze resumes:
"Can you analyze my resume for ATS compatibility? The file is at ~/Documents/my-resume.pdf"
Add to ~/.cursor/mcp.json:
{
"mcpServers": {
"resume-parser": {
"command": "npx",
"args": ["-y", "resume-parser-ats", "--mcp"]
}
}
}The server uses stdio transport. For any MCP-compatible application, configure:
{
"mcpServers": {
"resume-parser": {
"command": "npx",
"args": ["-y", "resume-parser-ats", "--mcp"]
}
}
}If you have resume-parser-ats installed globally:
{
"mcpServers": {
"resume-parser": {
"command": "resume-parser-ats",
"args": ["--mcp"]
}
}
}| Tool | Description | Parameters |
|---|---|---|
parse_resume |
Parse resume PDF/text → structured data | filePath, rawText |
analyze_resume |
Parse + ATS scoring | filePath, rawText, strictness |
suggest_improvements |
Parse + analyze + suggestions | filePath, rawText, focusAreas |
The parser implements the OpenResume algorithm, the same methodology used by real ATS systems:
Extract every text item with position, bold, and newline metadata:
{ text: "John Doe", x1: 72, x2: 144, y: 720, bold: true, newLine: true }Merge adjacent items when their horizontal gap is less than average character width. Group by Y-coordinate to reconstruct the natural reading order.
Detect section titles using two heuristics:
- Primary: Only text item in line + bold + ALL UPPERCASE
- Fallback: Keyword match (EDUCATION, EXPERIENCE, SKILLS, etc.)
Each attribute has feature sets with scoring functions. The text item with the highest total score wins:
| Attribute | Core Pattern | Example |
|---|---|---|
| Name | Only letters/spaces/periods | John Doe |
| Email format | john@email.com |
|
| Phone | (xxx) xxx-xxxx |
(555) 123-4567 |
| Location | City, ST |
New York, NY |
| School | Contains "University" etc. | MIT |
| Degree | Contains "B.S.", "M.A." etc. | B.S. Computer Science |
Name scoring example: Only letters (+3), bolded (+2), uppercase (+2), has @ (-4), has digit (-4)
See resume-parser-ats/references/algorithm.md for the full specification.
| Dimension | Weight | What it checks |
|---|---|---|
| Name extraction | 20 pts | Can the parser identify a full name? |
| Email extraction | 20 pts | Is there a valid email address? |
| Phone extraction | 10 pts | Is there a parseable phone number? |
| Section detection | 15 pts | Are sections properly structured? |
| Education parsing | 10 pts | Are school, degree, and date parsed? |
| Experience parsing | 15 pts | Are company, title, and date parsed? |
| Skills parsing | 10 pts | Are skills extracted correctly? |
| Grade | Score | Meaning |
|---|---|---|
| A+ | 90-100 | Excellent — ATS will parse everything correctly |
| A | 85-89 | Great — minor issues only |
| B+ | 80-84 | Good — most fields parse correctly |
| B | 75-79 | Adequate — some sections need improvement |
| B- | 70-74 | Below average — multiple parsing issues |
| C+ | 65-69 | Needs work — significant ATS problems |
| C | 60-64 | Poor — many fields fail to parse |
| D | 50-59 | Bad — critical fields missing |
| F | 0-49 | Failing — unrecognizable as a resume |
- 🔴 CRITICAL — Name or email cannot be parsed (ATS will discard)
- 🟠 HIGH — Sections missing, dates unparseable, phone not found
- 🟡 MEDIUM — Skills not clean, formatting merge issues
- 🟢 LOW — Minor inconsistencies, optional fields missing
Before applying, see what an ATS actually extracts:
resume-parser-ats insights my-resume.pdf --strictness strict --jsonimport { parseResume, analyzeResume } from "resume-parser-ats";
import fs from "fs";
const files = fs.readdirSync("resumes/");
for (const file of files) {
const parsed = parseResume({ filePath: `resumes/${file}` });
const analysis = analyzeResume({ parsedResume: parsed.data, strictness: "moderate" });
console.log(`${file}: ${analysis.data.atsScore}/100 (${analysis.data.atsGrade})`);
}Parse on upload → store ATS score → visualize → suggest improvements → track progress.
Batch-parse resumes, flag common issues, generate improvement templates.
resume-parser/
├── resume-parser-ats/ # Agent skill (npx skills add)
│ ├── SKILL.md # Skill manifest & instructions
│ └── references/
│ └── algorithm.md # Full algorithm specification
├── src/ # TypeScript source
│ ├── index.ts # Exports + fullPipeline()
│ ├── tools/
│ │ ├── parse-resume.ts # Step 1-4 parsing engine
│ │ ├── analyze-resume.ts # ATS scoring & analysis
│ │ └── suggest-improvements.ts # Suggestion generator
│ └── prompts/
│ ├── parser-prompt.ts # Parsing prompt templates
│ └── insights-prompt.ts # Insights prompt templates
├── bin/
│ └── cli.js # CLI entry point
├── mcp-server/
│ └── server.ts # MCP server implementation
├── test/evals/ # Test suites (86 tests)
├── AGENTS.md # Agent configuration
├── CONTRIBUTING.md # Contributing guide
├── package.json
└── tsconfig.json
We have big plans. Here's what's coming — and where we need your help:
A CLI-based tool for creating resumes in multiple formats (PDF, HTML, Markdown, LaTeX) — with templates, theming, and interactive prompts. No more fighting with Word formatting.
Improved parsing of various PDF encodings directly in the terminal — resolving canvas rendering issues, CID font mapping, and other common ATS-breaking PDF problems that current parsers silently fail on.
An agent-based orchestration layer that intelligently routes different resume formats and encodings through the optimal parsing path, with fallback strategies and self-healing extraction.
Automatically adjust parsing weights, keyword extraction, and skill identification based on a target Job Description — so the parser focuses on what matters for that role.
Continuing to refine our implementation toward (and beyond) the full OpenResume parsing spec — including bullet-point extraction, date-range normalization, multi-column layout detection, and cross-section reference resolution.
We're actively looking for contributors! If any of these areas excite you — whether it's PDF internals, parsing algorithms, CLI design, or agent orchestration — check out CONTRIBUTING.md and open an issue. Every contribution matters.
See CONTRIBUTING.md for the full guide:
- Development setup & prerequisites
- Project structure
- Code style & testing conventions
- Commit message format
- Pull request checklist
Found a bug or have an idea? Open an issue!
MIT License — Copyright (c) 2026 Dhanush Kandhan. See LICENSE for details.
Made with ❤️ by Dhanush Kandhan
If this project helped you, consider giving it a ⭐ on GitHub!