resume-parser-ats 1.1.1 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,272 @@
1
+ # Contributing to Resume Parser
2
+
3
+ First off, thank you for considering contributing! 🎉
4
+
5
+ This project is a resume parsing agent skill, npm CLI tool, and MCP server. Contributions of all kinds are welcome: bug fixes, features, documentation improvements, test cases, and more.
6
+
7
+ ## Table of Contents
8
+
9
+ - [Code of Conduct](#code-of-conduct)
10
+ - [Getting Started](#getting-started)
11
+ - [Development Setup](#development-setup)
12
+ - [Project Structure](#project-structure)
13
+ - [Making Changes](#making-changes)
14
+ - [Running Tests](#running-tests)
15
+ - [Code Style](#code-style)
16
+ - [Commit Messages](#commit-messages)
17
+ - [Pull Requests](#pull-requests)
18
+ - [Reporting Bugs](#reporting-bugs)
19
+ - [Feature Requests](#feature-requests)
20
+
21
+ ## Code of Conduct
22
+
23
+ Be respectful, constructive, and inclusive. We're all here to make resume parsing better for everyone.
24
+
25
+ ## Getting Started
26
+
27
+ 1. **Fork** the repository on GitHub
28
+ 2. **Clone** your fork locally:
29
+ ```bash
30
+ git clone https://github.com/YOUR_USERNAME/resume-parser-skill.git
31
+ cd resume-parser-skill
32
+ ```
33
+ 3. **Install** dependencies:
34
+ ```bash
35
+ npm install
36
+ ```
37
+ 4. **Build** the project:
38
+ ```bash
39
+ npm run build
40
+ ```
41
+
42
+ ## Development Setup
43
+
44
+ ### Prerequisites
45
+
46
+ - **Node.js** >= 18 (tested on 18, 20, 22)
47
+ - **npm** >= 9
48
+
49
+ ### Key Commands
50
+
51
+ | Command | Description |
52
+ |---------|-------------|
53
+ | `npm install` | Install dependencies |
54
+ | `npm run build` | Compile TypeScript to `dist/` |
55
+ | `npm test` | Run all evaluation tests |
56
+ | `npm run lint` | Lint source files |
57
+ | `npm run dev` | Run index.ts directly with ts-node |
58
+ | `npm run mcp` | Start the MCP server locally |
59
+
60
+ ### Verify Everything Works
61
+
62
+ ```bash
63
+ # Build and test
64
+ npm run build && npm test
65
+
66
+ # Verify CLI
67
+ node bin/cli.js --help
68
+
69
+ # Quick parse test
70
+ node bin/cli.js parse "John Doe
71
+ john@example.com
72
+ (555) 123-4567
73
+ Software Engineer"
74
+ ```
75
+
76
+ ## Project Structure
77
+
78
+ ```
79
+ resume-parser-skill/
80
+ ├── resume-parser-ats/ # Agent skill directory (npx skills add)
81
+ │ ├── SKILL.md # Skill manifest & agent instructions
82
+ │ └── references/
83
+ │ └── algorithm.md # Full 4-step algorithm spec
84
+ ├── src/ # TypeScript source code
85
+ │ ├── index.ts # Main entry, exports, fullPipeline()
86
+ │ ├── tools/
87
+ │ │ ├── parse-resume.ts # Step 1-4 parsing engine
88
+ │ │ ├── analyze-resume.ts # ATS scoring & analysis
89
+ │ │ └── suggest-improvements.ts # Suggestion generator
90
+ │ └── prompts/
91
+ │ ├── parser-prompt.ts # Parsing prompt templates
92
+ │ └── insights-prompt.ts # Insights prompt templates
93
+ ├── bin/
94
+ │ └── cli.js # CLI entry point (npx resume-parser-ats)
95
+ ├── mcp-server/
96
+ │ └── server.ts # MCP server implementation
97
+ ├── test/evals/ # Test suites
98
+ │ ├── parse-resume.test.mjs
99
+ │ ├── analyze-resume.test.mjs
100
+ │ └── suggest-improvements.test.mjs
101
+ ├── AGENTS.md # Agent configuration (skills spec)
102
+ ├── package.json
103
+ ├── tsconfig.json
104
+ └── README.md
105
+ ```
106
+
107
+ ## Making Changes
108
+
109
+ ### Branch Naming
110
+
111
+ Use descriptive branch names:
112
+
113
+ ```
114
+ feature/add-bullet-point-parsing
115
+ fix/education-date-extraction
116
+ docs/mcp-setup-guide
117
+ test/strict-mode-edge-cases
118
+ ```
119
+
120
+ ### Code Changes
121
+
122
+ 1. **Create a branch** from `master`:
123
+ ```bash
124
+ git checkout -b feature/your-feature
125
+ ```
126
+
127
+ 2. **Make your changes** — follow the existing code patterns
128
+
129
+ 3. **Update tests** — add or modify tests in `test/evals/`
130
+
131
+ 4. **Update documentation** — if you add a feature, update:
132
+ - `SKILL.md` if it affects agent-facing instructions
133
+ - `README.md` if it affects user-facing docs
134
+ - `references/algorithm.md` if it changes the parsing algorithm
135
+
136
+ 5. **Verify** — build and test:
137
+ ```bash
138
+ npm run build && npm test
139
+ ```
140
+
141
+ ### Important Files to Update
142
+
143
+ | If you change... | Also update |
144
+ |---|---|
145
+ | Parsing logic in `src/tools/parse-resume.ts` | `resume-parser-ats/references/algorithm.md` |
146
+ | Output format of any tool | `resume-parser-ats/SKILL.md` and `README.md` |
147
+ | CLI commands or flags | `bin/cli.js` help text and `README.md` |
148
+ | MCP tool definitions | `mcp-server/server.ts` and `README.md` |
149
+ | Scoring or grading | `resume-parser-ats/SKILL.md` scoring tables |
150
+
151
+ ## Running Tests
152
+
153
+ ```bash
154
+ # Run all 86 tests
155
+ npm test
156
+
157
+ # Run specific test suite
158
+ node --test test/evals/parse-resume.test.mjs
159
+ node --test test/evals/analyze-resume.test.mjs
160
+ node --test test/evals/suggest-improvements.test.mjs
161
+
162
+ # Run a single test with verbose output
163
+ node --test test/evals/parse-resume.test.mjs --test-name-pattern "Step 1"
164
+ ```
165
+
166
+ Tests use Node.js built-in test runner (`node:test`) and assert module (`node:assert/strict`). No additional test framework needed.
167
+
168
+ ### Writing New Tests
169
+
170
+ Add test cases in the appropriate file under `test/evals/`:
171
+
172
+ ```javascript
173
+ import { describe, it } from "node:test";
174
+ import assert from "node:assert/strict";
175
+ import { parseResume } from "../../dist/src/tools/parse-resume.js";
176
+
177
+ describe("My New Feature", () => {
178
+ it("should handle the new case correctly", () => {
179
+ const result = parseResume({ rawText: "..." });
180
+ assert.equal(result.success, true);
181
+ assert.equal(result.data.profile.name, "Expected Name");
182
+ });
183
+ });
184
+ ```
185
+
186
+ ## Code Style
187
+
188
+ - **TypeScript** for all source code (`src/` and `mcp-server/`)
189
+ - **ES modules** with CommonJS compilation output
190
+ - **2-space indentation**
191
+ - Run `npm run lint` before committing — ESLint with TypeScript plugin
192
+
193
+ Key conventions:
194
+ - Use Zod for input validation schemas
195
+ - Always return `{ success: boolean, data: T, metadata: {...} }` format
196
+ - Include `warnings` array in metadata for non-fatal issues
197
+ - Feature scoring uses additive positive and negative scores
198
+
199
+ ## Commit Messages
200
+
201
+ Follow [Conventional Commits](https://www.conventionalcommits.org/):
202
+
203
+ ```
204
+ feat: add bullet-point parsing for experience sections
205
+ fix: handle edge case in date extraction for seasonal dates
206
+ docs: add MCP setup guide for Claude Desktop
207
+ test: add strict mode edge cases for phone parsing
208
+ refactor: simplify section grouping logic
209
+ chore: update dependencies
210
+ ```
211
+
212
+ Prefixes: `feat:`, `fix:`, `docs:`, `test:`, `refactor:`, `perf:`, `chore:`, `ci:`
213
+
214
+ ## Pull Requests
215
+
216
+ 1. **Push** your branch to your fork:
217
+ ```bash
218
+ git push origin feature/your-feature
219
+ ```
220
+
221
+ 2. **Open a Pull Request** against the `master` branch
222
+
223
+ 3. **Describe your changes** — what, why, and how to test
224
+
225
+ 4. **Ensure CI passes** — all tests must pass across Node 18, 20, 22
226
+
227
+ 5. **Respond to review feedback** promptly
228
+
229
+ ### PR Checklist
230
+
231
+ - [ ] Code compiles (`npm run build` succeeds)
232
+ - [ ] All tests pass (`npm test`)
233
+ - [ ] Lint passes (`npm run lint`)
234
+ - [ ] New features have tests
235
+ - [ ] Documentation updated (SKILL.md, README.md, algorithm.md as needed)
236
+ - [ ] Commit messages follow conventional commits format
237
+
238
+ ## Reporting Bugs
239
+
240
+ Open a [GitHub Issue](https://github.com/dhanushk-offl/resume-parser-skill/issues/new) with:
241
+
242
+ 1. **What you did** — exact command or input
243
+ 2. **What happened** — actual output or error
244
+ 3. **What you expected** — desired output
245
+ 4. **Environment** — Node.js version, OS, how you're using it (CLI, library, MCP, skill)
246
+
247
+ ## Feature Requests
248
+
249
+ Open a [GitHub Issue](https://github.com/dhanushk-offl/resume-parser-skill/issues/new) with:
250
+
251
+ 1. **Use case** — what problem does this solve?
252
+ 2. **Proposed solution** — how should it work?
253
+ 3. **Alternatives considered** — other approaches you thought of
254
+ 4. **Which interface** — does this affect the skill, CLI, library, or MCP?
255
+
256
+ ## Release Process
257
+
258
+ Maintainers only:
259
+
260
+ ```bash
261
+ # Bump version
262
+ npm version patch # or minor, major
263
+
264
+ # Push with tags
265
+ git push --follow-tags
266
+
267
+ # CI automatically publishes to npm and creates a GitHub release
268
+ ```
269
+
270
+ ---
271
+
272
+ Thank you for contributing! 💛
package/README.md CHANGED
@@ -1,279 +1,459 @@
1
+ <div align="center">
2
+
1
3
  # 📄 Resume Parser
2
4
 
3
- <p align="center">
4
- <strong>Deep resume parsing • ATS compatibility scoring • Actionable improvement insights</strong>
5
- </p>
5
+ **Deep resume parsing • ATS compatibility scoring • Actionable improvement insights**
6
6
 
7
- <p align="center">
8
- Made with ❤️ by <strong>Dhanush Kandhan</strong>
9
- </p>
7
+ 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.
10
8
 
11
- ---
9
+ Made with ❤️ by **Dhanush Kandhan**
10
+
11
+ [![npm version](https://img.shields.io/npm/v/resume-parser-ats.svg)](https://www.npmjs.com/package/resume-parser-ats)
12
+ [![CI](https://github.com/dhanushk-offl/resume-parser-skill/actions/workflows/ci.yml/badge.svg)](https://github.com/dhanushk-offl/resume-parser-skill/actions/workflows/ci.yml)
13
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)
12
14
 
13
- A powerful agent skill that deeply parses resumes using the **OpenResume 4-step algorithm**, extracts structured information (Name, Email, Phone, Education, Work Experience, Skills, Projects), evaluates ATS (Applicant Tracking System) compatibility, and provides prioritized, actionable suggestions to improve your resume.
15
+ </div>
16
+
17
+ ---
14
18
 
15
19
  ## ✨ Features
16
20
 
17
21
  - **🔍 Deep Parsing** — Extracts 10+ fields from raw text or PDF using a feature-scoring engine
18
- - **📊 ATS Scoring** — Grades your resume A+ through F with detailed per-field confidence ratings
22
+ - **📊 ATS Scoring** — Grades your resume A+ through F with per-field confidence ratings
19
23
  - **💡 Smart Suggestions** — Prioritized, categorized fixes (critical → low) with before/after examples
20
- - **🛠️ CLI & MCP Server** — Use interactively from the command line or as an MCP tool
21
- - **⚙️ Configurable Strictness** — Lenient, moderate, or strict ATS evaluation modes
22
- - **🔒 Zero Dependencies on Proprietary APIs** Runs entirely locally with no external calls
24
+ - **🤖 Agent Skill** — Install via `npx skills add` for pi, Claude Code, Codex, Gemini CLI, and more
25
+ - **🖥️ CLI** — Use directly from the command line
26
+ - **📡 MCP Server** Plug into Claude Desktop, ChatGPT, and other MCP-compatible apps
27
+ - **📖 Library** — Import as an npm package for programmatic use
28
+ - **⚙️ Configurable** — Lenient, moderate, or strict ATS evaluation modes
29
+ - **🔒 Privacy-first** — Runs entirely locally, no external API calls
30
+
31
+ ---
32
+
33
+ ## 🚀 Quick Start
34
+
35
+ Choose how you want to use Resume Parser:
23
36
 
24
- ## 📦 Installation
37
+ | Method | Install | Best for |
38
+ |--------|---------|----------|
39
+ | **Agent Skill** | `npx skills add dhanushk-offl/resume-parser-skill` | AI agents (pi, Claude Code, Codex, Gemini CLI) |
40
+ | **CLI** | `npm install -g resume-parser-ats` | Quick one-off resume analysis |
41
+ | **Library** | `npm install resume-parser-ats` | Building apps, batch processing |
42
+ | **MCP Server** | `npm install resume-parser-ats` | Claude Desktop, ChatGPT, Cursor |
43
+
44
+ ---
45
+
46
+ ## 🤖 1. Agent Skill
47
+
48
+ Install as an agent skill for automatic activation in AI coding assistants:
25
49
 
26
50
  ```bash
27
- # Clone the repo
28
- git clone https://github.com/dhanushk-offl/resume-parser-skill.git
29
- cd resume-parser-skill
51
+ npx skills add dhanushk-offl/resume-parser-skill
52
+ ```
53
+
54
+ Once installed, the skill activates automatically when you:
55
+
56
+ - Ask to parse, review, or analyze a resume
57
+ - Ask "is my resume ATS-friendly?"
58
+ - Ask for resume improvement suggestions
59
+ - Upload or reference a resume PDF
60
+
61
+ **Works with:** pi, Claude Code, OpenAI Codex, Gemini CLI, Cursor, Continue, and all [Agent Skills](https://agentskills.io) compatible tools.
30
62
 
31
- # Install dependencies
32
- npm install
63
+ ### What the Agent Gets
33
64
 
34
- # Build
35
- npm run build
65
+ | Tool | Description |
66
+ |------|-------------|
67
+ | `parse_resume` | Parse a resume PDF/text → structured data |
68
+ | `analyze_resume` | Parse + compute ATS compatibility score with per-field confidence |
69
+ | `suggest_improvements` | Parse + analyze + generate prioritized improvement suggestions |
70
+
71
+ ### Example Agent Prompts
72
+
73
+ ```
74
+ "Is my resume ATS-friendly? Here's the PDF path: ./my-resume.pdf"
75
+ "Parse this resume and extract the contact info"
76
+ "Analyze my resume for ATS compatibility with strict grading"
77
+ "What can I improve on my resume to get past ATS filters?"
36
78
  ```
37
79
 
38
- ## 🚀 Usage
80
+ ---
81
+
82
+ ## 🖥️ 2. CLI
39
83
 
40
- ### As a CLI Tool
84
+ Install globally for command-line use:
85
+
86
+ ```bash
87
+ npm install -g resume-parser-ats
88
+ ```
41
89
 
42
90
  ```bash
43
91
  # Parse a resume and output structured data
44
- npx resume-parser-ats parse resume.pdf
92
+ resume-parser-ats parse resume.pdf
45
93
 
46
94
  # Parse + analyze ATS compatibility
47
- npx resume-parser-ats analyze resume.pdf
95
+ resume-parser-ats analyze resume.pdf
48
96
 
49
- # Full pipeline: parse + analyze + actionable suggestions
50
- npx resume-parser-ats insights resume.pdf
97
+ # Full pipeline: parse + analyze + suggestions
98
+ resume-parser-ats insights resume.pdf
51
99
 
52
100
  # Parse from raw text
53
- npx resume-parser-ats parse "John Doe\njohn@email.com\nSoftware Engineer"
101
+ resume-parser-ats parse "John Doe\njohn@email.com\nSoftware Engineer"
54
102
 
55
103
  # Adjust ATS strictness
56
- npx resume-parser-ats analyze resume.pdf --strictness strict
104
+ resume-parser-ats analyze resume.pdf --strictness strict
57
105
 
58
106
  # Focus on specific areas
59
- npx resume-parser-ats insights resume.pdf --focus ats,formatting --json
107
+ resume-parser-ats insights resume.pdf --focus ats,formatting
108
+
109
+ # Output as JSON
110
+ resume-parser-ats insights resume.pdf --json
111
+ ```
112
+
113
+ Or use without installing:
114
+
115
+ ```bash
116
+ npx resume-parser-ats parse resume.pdf
60
117
  ```
61
118
 
62
- ### As a Library
119
+ ---
120
+
121
+ ## 📖 3. Library (npm Package)
122
+
123
+ Install as a dependency for programmatic use:
124
+
125
+ ```bash
126
+ npm install resume-parser-ats
127
+ ```
63
128
 
64
129
  ```typescript
65
130
  import { parseResume, analyzeResume, suggestImprovements } from "resume-parser-ats";
66
131
 
67
- // Step 1: Parse
68
- const parsed = parseResume({ rawText: "..." });
69
- console.log(parsed.data.profile.name); // "Jane Doe"
70
- console.log(parsed.data.profile.email); // "jane@example.com"
132
+ // Parse extract structured data
133
+ const parsed = parseResume({ filePath: "./resume.pdf" });
134
+ // or: parseResume({ rawText: "John Doe\njohn@email.com\n..." })
135
+
136
+ console.log(parsed.data.profile.name); // "Jane Doe"
137
+ console.log(parsed.data.profile.email); // "jane@example.com"
71
138
  console.log(parsed.data.education[0]?.school); // "MIT"
72
139
 
73
- // Step 2: Analyze ATS compatibility
140
+ // Analyze ATS compatibility scoring
74
141
  const analysis = analyzeResume({
75
- rawText: "...",
142
+ filePath: "./resume.pdf",
76
143
  parsedResume: parsed.data,
77
- strictness: "moderate",
144
+ strictness: "strict",
78
145
  });
146
+
79
147
  console.log(analysis.data.atsScore); // 72
80
148
  console.log(analysis.data.atsGrade); // "B-"
149
+ console.log(analysis.data.fieldAnalyses);
150
+ console.log(analysis.data.formatIssues);
81
151
 
82
- // Step 3: Get improvement suggestions
152
+ // Suggest prioritized improvement recommendations
83
153
  const suggestions = suggestImprovements({
84
- rawText: "...",
154
+ filePath: "./resume.pdf",
85
155
  parsedResume: parsed.data,
86
156
  analysisResult: analysis.data,
87
- focusAreas: ["ats", "content", "formatting", "structure"],
157
+ focusAreas: ["ats", "content", "formatting"],
88
158
  });
89
- console.log(suggestions.data.quickWins); // ["Fix your name format...", ...]
90
- console.log(suggestions.data.suggestions[0].title); // "Name is not parseable by ATS"
159
+
160
+ console.log(suggestions.data.quickWins);
161
+ console.log(suggestions.data.suggestions);
91
162
  ```
92
163
 
93
- ### As an MCP Server
164
+ ### Full Pipeline
94
165
 
95
- ```bash
96
- npm run mcp
166
+ ```typescript
167
+ import { fullPipeline } from "resume-parser-ats";
168
+
169
+ const { parsed, analyzed, suggestions } = fullPipeline({
170
+ filePath: "./resume.pdf",
171
+ strictness: "moderate",
172
+ });
173
+
174
+ console.log(`ATS Score: ${analyzed.data.atsScore}/100 (${analyzed.data.atsGrade})`);
97
175
  ```
98
176
 
99
- Starts a Model Context Protocol server exposing three tools:
177
+ ### TypeScript Types
100
178
 
101
- | Tool | Description |
102
- |------|-------------|
103
- | `parse_resume` | Parse a resume PDF or raw text and return structured data |
104
- | `analyze_resume` | Parse + compute ATS compatibility score with per-field confidence |
105
- | `suggest_improvements` | Parse + analyze + generate prioritized improvement suggestions |
179
+ All types are exported:
106
180
 
107
- ## 🧠 How It Works: The 4-Step Algorithm
181
+ ```typescript
182
+ import type {
183
+ ParseResumeInput,
184
+ ParseResumeOutput,
185
+ AnalyzeResumeInput,
186
+ AnalyzeResumeOutput,
187
+ SuggestImprovementsInput,
188
+ SuggestImprovementsOutput,
189
+ ParsedResume,
190
+ TextItem,
191
+ LineItem,
192
+ SectionItem,
193
+ } from "resume-parser-ats";
194
+ ```
108
195
 
109
- The parser follows the **OpenResume algorithm**, a proven methodology used by real ATS systems:
196
+ ---
110
197
 
111
- ### Step 1 Read Text Items
198
+ ## 📡 4. MCP Server
112
199
 
113
- Extracts all text items from the resume, including:
114
- - Text content
115
- - X/Y positions (relative to bottom-left origin)
116
- - Bold metadata
117
- - Newline markers
200
+ Use Resume Parser as a Model Context Protocol (MCP) server to give AI assistants direct access to the parsing tools.
118
201
 
119
- ### Step 2 — Group Into Lines
202
+ ### Claude Desktop
120
203
 
121
- Merges adjacent text items on the same Y-coordinate when their horizontal distance is less than the average character width. Groups by Y-coordinate to reconstruct the line-by-line reading order.
204
+ Add to your Claude Desktop config file:
122
205
 
123
- ### Step 3 — Group Into Sections
206
+ **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
207
+ **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
124
208
 
125
- Detects section titles using two heuristics:
126
- 1. **Primary**: Only text item in line + bold + ALL UPPERCASE
127
- 2. **Fallback**: Keyword match against known headers (EDUCATION, EXPERIENCE, SKILLS, etc.)
209
+ ```json
210
+ {
211
+ "mcpServers": {
212
+ "resume-parser": {
213
+ "command": "npx",
214
+ "args": ["-y", "resume-parser-ats", "--mcp"]
215
+ }
216
+ }
217
+ }
218
+ ```
128
219
 
129
- ### Step 4 Extract Attributes via Feature Scoring
220
+ Restart Claude Desktop. You can now ask Claude to parse and analyze resumes:
130
221
 
131
- Each attribute (Name, Email, Phone, etc.) has **feature sets** — matching functions with positive/negative scores. The text item with the highest total score wins. This is how real ATS systems rank candidates:
222
+ ```
223
+ "Can you analyze my resume for ATS compatibility? The file is at ~/Documents/my-resume.pdf"
224
+ ```
132
225
 
133
- | Feature (Name) | Score | Feature (Email) | Score |
134
- |---|---|---|---|
135
- | Contains only letters/spaces/periods | +3 | Matches email regex | +4 |
136
- | Is bolded | +2 | Contains @ symbol | +4 |
137
- | Is ALL UPPERCASE | +2 | Looks like a name (no @) | -1 |
138
- | Contains @ (probably email) | -4 | Contains digits (no @) | -2 |
139
- | Contains numbers (probably phone) | -4 | — | — |
226
+ ### ChatGPT / Codex (OpenAI)
140
227
 
141
- ## 📊 Use Cases
228
+ Add to your OpenAI MCP configuration:
142
229
 
143
- ### 1. 🎯 Job Seeker — ATS Optimization
230
+ ```json
231
+ {
232
+ "mcpServers": {
233
+ "resume-parser": {
234
+ "command": "npx",
235
+ "args": ["-y", "resume-parser-ats", "--mcp"]
236
+ }
237
+ }
238
+ }
239
+ ```
144
240
 
145
- > *Before applying to jobs, run your resume through the parser to see what an ATS actually extracts.*
241
+ ### Cursor
146
242
 
147
- ```bash
148
- npx resume-parser-ats insights my-resume.pdf --strictness strict --json
243
+ Add to `~/.cursor/mcp.json`:
244
+
245
+ ```json
246
+ {
247
+ "mcpServers": {
248
+ "resume-parser": {
249
+ "command": "npx",
250
+ "args": ["-y", "resume-parser-ats", "--mcp"]
251
+ }
252
+ }
253
+ }
149
254
  ```
150
255
 
151
- Identify critical issues like a missing email, unparseable name, or sections an ATS can't detect — and fix them *before* you apply.
256
+ ### Other MCP-Compatible Apps
152
257
 
153
- ### 2. 🏢 Recruiter Bulk Resume Screening
258
+ The server uses stdio transport. For any MCP-compatible application, configure:
154
259
 
155
- > *Programmatically parse and score hundreds of resumes to rank candidates by ATS readability.*
260
+ ```json
261
+ {
262
+ "mcpServers": {
263
+ "resume-parser": {
264
+ "command": "npx",
265
+ "args": ["-y", "resume-parser-ats", "--mcp"]
266
+ }
267
+ }
268
+ }
269
+ ```
156
270
 
157
- ```typescript
158
- import { parseResume, analyzeResume } from "resume-parser-ats";
159
- import fs from "fs";
271
+ If you have `resume-parser-ats` installed globally:
160
272
 
161
- const files = fs.readdirSync("resumes/");
162
- for (const file of files) {
163
- const parsed = parseResume({ filePath: `resumes/${file}` });
164
- const analysis = analyzeResume({
165
- filePath: `resumes/${file}`,
166
- parsedResume: parsed.data,
167
- strictness: "moderate",
168
- });
169
- console.log(`${file}: ATS Score ${analysis.data.atsScore}/100 (${analysis.data.atsGrade})`);
273
+ ```json
274
+ {
275
+ "mcpServers": {
276
+ "resume-parser": {
277
+ "command": "resume-parser-ats",
278
+ "args": ["--mcp"]
279
+ }
280
+ }
170
281
  }
171
282
  ```
172
283
 
173
- ### 3. 🤖 Agent Integration — AI-Powered Resume Coach
284
+ ### MCP Tools Available
174
285
 
175
- > *Embed the skill into an AI agent that reviews resumes and gives personalized coaching.*
286
+ | Tool | Description | Parameters |
287
+ |------|-------------|------------|
288
+ | `parse_resume` | Parse resume PDF/text → structured data | `filePath`, `rawText` |
289
+ | `analyze_resume` | Parse + ATS scoring | `filePath`, `rawText`, `strictness` |
290
+ | `suggest_improvements` | Parse + analyze + suggestions | `filePath`, `rawText`, `focusAreas` |
176
291
 
177
- ```typescript
178
- import { fullPipeline } from "resume-parser-ats";
292
+ ---
293
+
294
+ ## 🧠 How It Works: The 4-Step Algorithm
295
+
296
+ The parser implements the **OpenResume algorithm**, the same methodology used by real ATS systems:
179
297
 
180
- const result = fullPipeline({ rawText: resumeText, strictness: "strict" });
298
+ ### Step 1 Read Text Items from PDF
181
299
 
182
- // result.parsed structured data
183
- // result.analyzed — ATS score + field analysis
184
- // result.suggestions — prioritized actions
300
+ Extract every text item with position, bold, and newline metadata:
185
301
 
186
- // Feed to an LLM for natural-language coaching
187
- const prompt = `You are a resume coach. Here is the analysis:
188
- ${JSON.stringify(result.analyzed.data)}
189
- Suggest improvements in a friendly, encouraging tone.`;
302
+ ```typescript
303
+ { text: "John Doe", x1: 72, x2: 144, y: 720, bold: true, newLine: true }
190
304
  ```
191
305
 
192
- ### 4. 📈 Career Platform Resume Health Dashboard
306
+ ### Step 2 Group Text Items into Lines
307
+
308
+ Merge adjacent items when their horizontal gap is less than average character width. Group by Y-coordinate to reconstruct the natural reading order.
309
+
310
+ ### Step 3 — Group Lines into Sections
311
+
312
+ Detect section titles using two heuristics:
313
+ 1. **Primary**: Only text item in line + bold + ALL UPPERCASE
314
+ 2. **Fallback**: Keyword match (EDUCATION, EXPERIENCE, SKILLS, etc.)
315
+
316
+ ### Step 4 — Extract Attributes via Feature Scoring
193
317
 
194
- > *Show users a "resume health score" on your career platform dashboard.*
318
+ Each attribute has feature sets with scoring functions. The text item with the **highest total score** wins:
195
319
 
196
- - Parse on upload store `atsScore`, `atsGrade`, and `fieldAnalyses`
197
- - Display a visual dashboard with color-coded field ratings
198
- - Surface `quickWins` as a checklist
199
- - Track score improvements over time as users update their resumes
320
+ | Attribute | Core Pattern | Example |
321
+ |-----------|-------------|---------|
322
+ | Name | Only letters/spaces/periods | `John Doe` |
323
+ | Email | Email format | `john@email.com` |
324
+ | Phone | `(xxx) xxx-xxxx` | `(555) 123-4567` |
325
+ | Location | `City, ST` | `New York, NY` |
326
+ | School | Contains "University" etc. | `MIT` |
327
+ | Degree | Contains "B.S.", "M.A." etc. | `B.S. Computer Science` |
200
328
 
201
- ### 5. 🎓 University Career Center Student Resume Reviews
329
+ **Name scoring example**: Only letters (+3), bolded (+2), uppercase (+2), has @ (-4), has digit (-4)
330
+
331
+ See [`resume-parser-ats/references/algorithm.md`](resume-parser-ats/references/algorithm.md) for the full specification.
332
+
333
+ ---
334
+
335
+ ## 📊 ATS Compatibility Scoring
336
+
337
+ | Dimension | Weight | What it checks |
338
+ |-----------|--------|---------------|
339
+ | Name extraction | 20 pts | Can the parser identify a full name? |
340
+ | Email extraction | 20 pts | Is there a valid email address? |
341
+ | Phone extraction | 10 pts | Is there a parseable phone number? |
342
+ | Section detection | 15 pts | Are sections properly structured? |
343
+ | Education parsing | 10 pts | Are school, degree, and date parsed? |
344
+ | Experience parsing | 15 pts | Are company, title, and date parsed? |
345
+ | Skills parsing | 10 pts | Are skills extracted correctly? |
346
+
347
+ ### Grading Scale
348
+
349
+ | Grade | Score | Meaning |
350
+ |-------|-------|---------|
351
+ | A+ | 90-100 | Excellent — ATS will parse everything correctly |
352
+ | A | 85-89 | Great — minor issues only |
353
+ | B+ | 80-84 | Good — most fields parse correctly |
354
+ | B | 75-79 | Adequate — some sections need improvement |
355
+ | B- | 70-74 | Below average — multiple parsing issues |
356
+ | C+ | 65-69 | Needs work — significant ATS problems |
357
+ | C | 60-64 | Poor — many fields fail to parse |
358
+ | D | 50-59 | Bad — critical fields missing |
359
+ | F | 0-49 | Failing — unrecognizable as a resume |
360
+
361
+ ### Issue Severity Levels
362
+
363
+ - 🔴 **CRITICAL** — Name or email cannot be parsed (ATS will discard)
364
+ - 🟠 **HIGH** — Sections missing, dates unparseable, phone not found
365
+ - 🟡 **MEDIUM** — Skills not clean, formatting merge issues
366
+ - 🟢 **LOW** — Minor inconsistencies, optional fields missing
367
+
368
+ ---
369
+
370
+ ## 📊 Use Cases
202
371
 
203
- > *Automate initial resume screening for career centers at scale.*
372
+ ### 🎯 Job Seeker ATS Optimization
204
373
 
205
- - Batch-parse student resumes and generate summary reports
206
- - Flag common issues (missing dates, non-standard section headers)
207
- - Provide standardized improvement templates
374
+ Before applying, see what an ATS actually extracts:
208
375
 
209
- ### 6. 🔄 Resume Migration Tool
376
+ ```bash
377
+ resume-parser-ats insights my-resume.pdf --strictness strict --json
378
+ ```
210
379
 
211
- > *Convert resumes from one format to structured JSON for database ingestion.*
380
+ ### 🏢 Recruiter Bulk Resume Screening
212
381
 
213
382
  ```typescript
214
- import { parseResume } from "resume-parser-ats";
383
+ import { parseResume, analyzeResume } from "resume-parser-ats";
384
+ import fs from "fs";
215
385
 
216
- const result = parseResume({ filePath: "legacy-resume.pdf" });
217
- // result.data is a clean, typed JSON object ready for your database
386
+ const files = fs.readdirSync("resumes/");
387
+ for (const file of files) {
388
+ const parsed = parseResume({ filePath: `resumes/${file}` });
389
+ const analysis = analyzeResume({ parsedResume: parsed.data, strictness: "moderate" });
390
+ console.log(`${file}: ${analysis.data.atsScore}/100 (${analysis.data.atsGrade})`);
391
+ }
218
392
  ```
219
393
 
394
+ ### 📈 Career Platform — Resume Health Dashboard
395
+
396
+ Parse on upload → store ATS score → visualize → suggest improvements → track progress.
397
+
398
+ ### 🎓 University Career Center — Student Reviews
399
+
400
+ Batch-parse resumes, flag common issues, generate improvement templates.
401
+
402
+ ---
403
+
220
404
  ## 🏗️ Architecture
221
405
 
222
406
  ```
223
- resume-parser/
224
- ├── package.json # Project metadata & scripts
225
- ├── README.md # This file
226
- ├── LICENSE # MIT License — Dhanush Kandhan
227
- ├── AGENTS.md # Agent-facing configuration
228
- ├── SKILL.md # Skill definition for agent consumption
229
- ├── src/
230
- │ ├── index.ts # Main entry point + fullPipeline()
407
+ resume-parser-skill/
408
+ ├── resume-parser-ats/ # Agent skill (npx skills add)
409
+ ├── SKILL.md # Skill manifest & instructions
410
+ │ └── references/
411
+ │ └── algorithm.md # Full algorithm specification
412
+ ├── src/ # TypeScript source
413
+ ├── index.ts # Exports + fullPipeline()
231
414
  │ ├── tools/
232
- │ │ ├── parse-resume.ts # Step 1-4 parsing engine
233
- │ │ ├── analyze-resume.ts # ATS scoring & analysis
234
- │ │ └── suggest-improvements.ts # Fix suggestions generator
415
+ │ │ ├── parse-resume.ts # Step 1-4 parsing engine
416
+ │ │ ├── analyze-resume.ts # ATS scoring & analysis
417
+ │ │ └── suggest-improvements.ts # Suggestion generator
235
418
  │ └── prompts/
236
- │ ├── parser-prompt.ts # Prompt templates for parsing
237
- │ └── insights-prompt.ts # Prompt templates for insights
238
- ├── mcp-server/
239
- │ └── server.ts # MCP server implementation
419
+ │ ├── parser-prompt.ts # Parsing prompt templates
420
+ │ └── insights-prompt.ts # Insights prompt templates
240
421
  ├── bin/
241
- │ └── cli.js # CLI entry point
242
- └── test/
243
- └── evals/ # Evaluation test suites
244
- ├── parse-resume.test.js
245
- ├── analyze-resume.test.js
246
- └── suggest-improvements.test.js
422
+ │ └── cli.js # CLI entry point
423
+ ├── mcp-server/
424
+ └── server.ts # MCP server implementation
425
+ ├── test/evals/ # Test suites (86 tests)
426
+ ├── AGENTS.md # Agent configuration
427
+ ├── CONTRIBUTING.md # Contributing guide
428
+ ├── package.json
429
+ └── tsconfig.json
247
430
  ```
248
431
 
432
+ ---
433
+
249
434
  ## 🧪 Testing
250
435
 
251
436
  ```bash
252
- # Run all tests
437
+ # Run all 86 tests
253
438
  npm test
254
439
 
255
- # Run evaluation suites
256
- node --test test/evals/parse-resume.test.js
257
- node --test test/evals/analyze-resume.test.js
258
- node --test test/evals/suggest-improvements.test.js
259
- ```
440
+ # Run a specific suite
441
+ node --test test/evals/parse-resume.test.mjs
442
+ node --test test/evals/analyze-resume.test.mjs
443
+ node --test test/evals/suggest-improvements.test.mjs
260
444
 
261
- ## 🤝 Contributing
445
+ # Filter by test name
446
+ node --test test/evals/parse-resume.test.mjs --test-name-pattern "Step 1"
447
+ ```
262
448
 
263
- 1. Fork the repository
264
- 2. Create a feature branch (`git checkout -b feature/amazing-feature`)
265
- 3. Commit your changes (`git commit -m 'Add amazing feature'`)
266
- 4. Push to the branch (`git push origin feature/amazing-feature`)
267
- 5. Open a Pull Request
449
+ ---
268
450
 
269
451
  ## ☁️ CI/CD
270
452
 
271
- This project uses GitHub Actions for continuous integration and npm publishing:
272
-
273
453
  | Workflow | Trigger | What it does |
274
454
  |----------|---------|-------------|
275
- | **Build & Test** | Push/PR to `master` | Lint, build, and test across Node 18/20/22 |
276
- | **Publish to npm** | Tag push `v*` (e.g. `v1.0.0`) | Builds and publishes to npmjs with provenance |
455
+ | **Build & Test** | Push/PR to `master` | Lint, build, and test across Node 18, 20, 22 |
456
+ | **Publish to npm** | Tag push `v*` | Builds and publishes to npmjs with provenance |
277
457
 
278
458
  To publish a new version:
279
459
 
@@ -282,13 +462,30 @@ npm version patch # or minor, major
282
462
  git push --follow-tags
283
463
  ```
284
464
 
465
+ ---
466
+
467
+ ## 🤝 Contributing
468
+
469
+ See [CONTRIBUTING.md](./CONTRIBUTING.md) for:
470
+
471
+ - Development setup
472
+ - Project structure guide
473
+ - Code style and testing conventions
474
+ - Commit message format
475
+ - Pull request checklist
476
+
477
+ ---
478
+
285
479
  ## 📄 License
286
480
 
287
481
  MIT License — Copyright (c) 2025 **Dhanush Kandhan**. See [LICENSE](./LICENSE) for details.
288
482
 
289
483
  ---
290
484
 
291
- <p align="center">
292
- Made with ❤️ by <strong>Dhanush Kandhan</strong><br>
293
- <em>If this project helped you, consider giving it a ⭐ on GitHub!</em>
294
- </p>
485
+ <div align="center">
486
+
487
+ Made with ❤️ by **Dhanush Kandhan**
488
+
489
+ If this project helped you, consider giving it a ⭐ on [GitHub](https://github.com/dhanushk-offl/resume-parser-skill)!
490
+
491
+ </div>
package/bin/cli.js CHANGED
@@ -7,6 +7,7 @@
7
7
  * resume-parser-ats parse <file|text> Parse a resume and output structured data
8
8
  * resume-parser-ats analyze <file|text> Parse + analyze ATS compatibility
9
9
  * resume-parser-ats insights <file|text> Full pipeline: parse + analyze + suggestions
10
+ * resume-parser-ats --mcp Start MCP server for Claude/ChatGPT/Cursor
10
11
  */
11
12
 
12
13
  const path = require("path");
@@ -35,6 +36,7 @@ Options:
35
36
  --strictness <level> ATS strictness: lenient, moderate, strict (default: moderate)
36
37
  --focus <areas> Focus areas: ats,content,formatting,structure (default: all)
37
38
  --json Output raw JSON instead of formatted report
39
+ --mcp Start MCP server (for Claude Desktop, ChatGPT, Cursor, etc.)
38
40
  --help Show this help message
39
41
 
40
42
  Examples:
@@ -42,12 +44,37 @@ Examples:
42
44
  resume-parser-ats analyze resume.pdf --strictness strict
43
45
  resume-parser-ats insights resume.pdf --focus ats,formatting --json
44
46
  resume-parser-ats parse "John Doe\\njohn@email.com\\nSoftware Engineer"
47
+
48
+ MCP Server:
49
+ resume-parser-ats --mcp
50
+
51
+ Add to Claude Desktop config:
52
+ {
53
+ "mcpServers": {
54
+ "resume-parser": {
55
+ "command": "npx",
56
+ "args": ["-y", "resume-parser-ats", "--mcp"]
57
+ }
58
+ }
59
+ }
45
60
  `);
46
61
  }
47
62
 
48
63
  function main() {
49
64
  const args = process.argv.slice(2);
50
65
 
66
+ // Handle --mcp flag: start MCP server
67
+ if (args.includes("--mcp")) {
68
+ try {
69
+ require("../dist/mcp-server/server.js");
70
+ } catch (err) {
71
+ console.error("Error: MCP server not built. Run `npm run build` first.");
72
+ console.error(err.message);
73
+ process.exit(1);
74
+ }
75
+ return;
76
+ }
77
+
51
78
  if (args.length === 0 || args.includes("--help") || args.includes("-h")) {
52
79
  printUsage();
53
80
  process.exit(0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "resume-parser-ats",
3
- "version": "1.1.1",
3
+ "version": "1.2.1",
4
4
  "description": "An agent skill that deeply parses resumes, extracts structured data, and provides actionable insights to improve ATS compatibility and readability.",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "dist/src/index.d.ts",
@@ -18,8 +18,10 @@
18
18
  "files": [
19
19
  "dist/",
20
20
  "bin/",
21
+ "resume-parser-ats/",
21
22
  "README.md",
22
- "LICENSE"
23
+ "LICENSE",
24
+ "CONTRIBUTING.md"
23
25
  ],
24
26
  "keywords": [
25
27
  "resume",
@@ -27,7 +29,9 @@
27
29
  "ATS",
28
30
  "agent-skill",
29
31
  "resume-parser",
30
- "career"
32
+ "career",
33
+ "skills",
34
+ "npx-skills"
31
35
  ],
32
36
  "author": "dhanush",
33
37
  "license": "MIT",
@@ -0,0 +1,218 @@
1
+ ---
2
+ name: resume-parser-ats
3
+ description: >
4
+ Deeply parses resume PDFs using the OpenResume 4-step algorithm, extracts structured information
5
+ (Name, Email, Phone, Education, Work Experience, Skills, etc.), evaluates ATS compatibility,
6
+ and provides actionable improvement suggestions. Use when a user asks to parse, review, or
7
+ analyze a resume, check ATS-friendliness, or get resume improvement suggestions.
8
+ ---
9
+
10
+ # Resume Parser — ATS Intelligence
11
+
12
+ You are a resume parsing and ATS analysis specialist. When activated, deeply parse resumes and provide structured, actionable insights.
13
+
14
+ ## When to Activate
15
+
16
+ - User asks to parse, review, or analyze a resume
17
+ - User asks "is my resume ATS-friendly?"
18
+ - User asks for resume improvement suggestions
19
+ - User uploads or references a resume PDF
20
+ - User wants to compare what an ATS sees vs. their intended content
21
+
22
+ ## Tools Available
23
+
24
+ For programmatic use, install the npm package:
25
+
26
+ ```bash
27
+ npm install resume-parser-ats
28
+ ```
29
+
30
+ ### `parse_resume` — Extract structured data from a resume
31
+
32
+ ```bash
33
+ npx resume-parser-ats parse <file.pdf>
34
+ ```
35
+
36
+ ```javascript
37
+ import { parseResume } from "resume-parser-ats";
38
+ const result = parseResume({ filePath: "/path/to/resume.pdf" });
39
+ // or: parseResume({ rawText: "John Doe\njohn@email.com..." })
40
+ ```
41
+
42
+ **Input**: `{ filePath?: string, rawText?: string }`
43
+ **Output**: Structured data with profile, education, experience, skills, projects.
44
+
45
+ ---
46
+
47
+ ### `analyze_resume` — Parse + ATS compatibility scoring
48
+
49
+ ```bash
50
+ npx resume-parser-ats analyze <file.pdf> --strictness strict
51
+ ```
52
+
53
+ ```javascript
54
+ import { analyzeResume } from "resume-parser-ats";
55
+ const result = analyzeResume({ filePath: "/path/to/resume.pdf", strictness: "moderate" });
56
+ ```
57
+
58
+ **Input**: `{ filePath?, rawText?, strictness?: "lenient"|"moderate"|"strict" }`
59
+ **Output**: ATS score (0-100), letter grade (A+ to F), per-field confidence, section detection, format issues.
60
+
61
+ ---
62
+
63
+ ### `suggest_improvements` — Parse + analyze + prioritized suggestions
64
+
65
+ ```bash
66
+ npx resume-parser-ats insights <file.pdf> --strictness strict --focus ats,formatting
67
+ ```
68
+
69
+ ```javascript
70
+ import { suggestImprovements } from "resume-parser-ats";
71
+ const result = suggestImprovements({ filePath: "/path/to/resume.pdf", focusAreas: ["ats", "content"] });
72
+ ```
73
+
74
+ **Input**: `{ filePath?, rawText?, strictness?, focusAreas?: string[] }`
75
+ **Output**: Overall score, grade, quick wins, prioritized suggestions (critical → low), section analysis.
76
+
77
+ ---
78
+
79
+ ## Manual Parsing Algorithm
80
+
81
+ Use this algorithm when the npm package is unavailable or for understanding the parsing logic:
82
+
83
+ ### Step 1: Read Text Items from PDF
84
+
85
+ Extract all text items from the PDF. Each item includes:
86
+ - `text` — text content
87
+ - `x1`, `x2` — left/right X positions (origin at bottom-left)
88
+ - `y` — Y position from bottom
89
+ - `bold` — whether text is bold
90
+ - `newLine` — whether this item starts a new line
91
+
92
+ ### Step 2: Group Text Items into Lines
93
+
94
+ 1. **Merge adjacent items**: When `Distance = RightTextItem.X₁ - LeftTextItem.X₂` is less than average character width, merge them
95
+ 2. **Average character width**: Total character widths / total character count (exclude bold and newline elements)
96
+ 3. **Group by Y-coordinate**: Same Y = same line
97
+
98
+ ### Step 3: Group Lines into Sections
99
+
100
+ **Section title detection** (must satisfy ALL 3):
101
+ 1. It is the only text item in the line
102
+ 2. It is bolded
103
+ 3. Its letters are all UPPERCASE
104
+
105
+ **Fallback**: Keyword match against known headers:
106
+ PROFILE, SUMMARY, OBJECTIVE, ABOUT, EDUCATION, ACADEMIC, DEGREES, EXPERIENCE, WORK EXPERIENCE, EMPLOYMENT, PROFESSIONAL EXPERIENCE, SKILLS, TECHNICAL SKILLS, COMPETENCIES, PROJECTS, PORTFOLIO, CERTIFICATIONS, LICENSES, HONORS, AWARDS, VOLUNTEER, COMMUNITY, LEADERSHIP, PUBLICATIONS, RESEARCH, INTERESTS, ACTIVITIES, HOBBIES
107
+
108
+ Lines before any section title go into PROFILE.
109
+
110
+ ### Step 4: Extract Attributes via Feature Scoring
111
+
112
+ Each attribute has feature sets (matching function + score). The text item with the **highest total score** wins.
113
+
114
+ | Attribute | Core Feature | Regex |
115
+ |-----------|-------------|-------|
116
+ | Name | Only letters/spaces/periods | `/^[a-zA-Z\s\.]+$/` |
117
+ | Email | Email format | `/\S+@\S+\.\S+/` |
118
+ | Phone | Phone format | `/\(?\d{3}\)?[\s-]?\d{3}[\s-]?\d{4}/` |
119
+ | Location | City, ST format | `/[A-Z][a-zA-Z\s]+, [A-Z]{2}/` |
120
+ | URL | URL format | `/\S+\.[a-z]+\/\S+/` |
121
+
122
+ **Name scoring example**: Only letters (+3), bolded (+2), uppercase (+2), has @ (-4), has digit (-4), has comma (-4), has slash (-4)
123
+
124
+ **Subsection detection** (for Education, Work Experience):
125
+ - Primary: vertical line gap > typical line gap × 1.4
126
+ - Fallback: text item is bolded
127
+
128
+ See [references/algorithm.md](references/algorithm.md) for the full specification.
129
+
130
+ ---
131
+
132
+ ## ATS Compatibility Scoring
133
+
134
+ | Dimension | Weight |
135
+ |-----------|--------|
136
+ | Name extraction | 20 pts |
137
+ | Email extraction | 20 pts |
138
+ | Phone extraction | 10 pts |
139
+ | Section detection | 15 pts |
140
+ | Education parsing | 10 pts |
141
+ | Experience parsing | 15 pts |
142
+ | Skills parsing | 10 pts |
143
+
144
+ **Grading**: A+ (90-100), A (85-89), B+ (80-84), B (75-79), B- (70-74), C+ (65-69), C (60-64), D (50-59), F (0-49)
145
+
146
+ ## Issue Severity Levels
147
+
148
+ - **CRITICAL**: Name or email cannot be parsed → ATS will likely discard
149
+ - **HIGH**: Key sections missing, dates unparseable, phone not found
150
+ - **MEDIUM**: Skills not extracted cleanly, formatting merge issues
151
+ - **LOW**: Minor inconsistencies, optional fields missing
152
+
153
+ ## Output Format
154
+
155
+ Always provide results in this structured format:
156
+
157
+ ```
158
+ ## 📊 Resume Parsing Report
159
+
160
+ ### ATS Compatibility Score: XX/100 (Grade: X)
161
+
162
+ ### ✅ Successfully Parsed Fields
163
+ | Field | Parsed Value | Confidence |
164
+ |-------|-------------|------------|
165
+ | Name | John Doe | High |
166
+
167
+ ### ⚠️ Issues Found
168
+ | # | Severity | Field | Issue | Suggestion |
169
+ |---|----------|-------|-------|------------|
170
+ | 1 | CRITICAL | Email | ... | ... |
171
+
172
+ ### 📝 Priority Fixes
173
+ 1. **[Fix Title]**: Description of what to change and why
174
+ - Before: `current state`
175
+ - After: `suggested state`
176
+
177
+ ### 📋 Section-by-Section Analysis
178
+ #### Profile
179
+ - Analysis notes...
180
+ ```
181
+
182
+ ## Important Rules
183
+
184
+ 1. **Always run all 4 parsing steps** — do not skip steps
185
+ 2. **Always provide the ATS compatibility score** — this is the primary metric
186
+ 3. **Every suggestion must be actionable** — not "improve formatting" but "Move the date to the same line as the company name"
187
+ 4. **Prioritize Name and Email extraction** — if they fail, flag as CRITICAL
188
+ 5. **Explain WHY** each suggestion matters in ATS terms
189
+ 6. **Compare parsed output vs. likely intended content** — surface discrepancies
190
+ 7. **Never modify the original file** — this is a read-only analysis tool
191
+ 8. **If a PDF cannot be parsed**, fall back to raw text and note the limitation
192
+ 9. **Flag when text items break unexpectedly** (e.g., phone numbers split across items)
193
+
194
+ ## Programmatic Access
195
+
196
+ ### As an npm Library
197
+
198
+ ```bash
199
+ npm install resume-parser-ats
200
+ ```
201
+
202
+ ```typescript
203
+ import { parseResume, analyzeResume, suggestImprovements } from "resume-parser-ats";
204
+
205
+ const result = parseResume({ filePath: "resume.pdf" });
206
+ ```
207
+
208
+ ### As an MCP Server
209
+
210
+ Start the MCP server for use with Claude Desktop, ChatGPT, Cursor, and other MCP-compatible apps:
211
+
212
+ ```bash
213
+ resume-parser-ats --mcp
214
+ # or
215
+ npx resume-parser-ats --mcp
216
+ ```
217
+
218
+ See README for full MCP configuration instructions.
@@ -0,0 +1,126 @@
1
+ # OpenResume 4-Step Parsing Algorithm
2
+
3
+ This document provides the full technical reference for the resume parsing algorithm.
4
+
5
+ ## Step 1: Read Text Items from PDF
6
+
7
+ Extract all text items from the PDF using `pdfjs-dist`. Each text item includes:
8
+
9
+ | Field | Type | Description |
10
+ |-------|------|-------------|
11
+ | `text` | string | The text content |
12
+ | `x1` | number | Left X position |
13
+ | `x2` | number | Right X position |
14
+ | `y` | number | Y position (from page bottom) |
15
+ | `bold` | boolean | Whether the text is bold |
16
+ | `newLine` | boolean | Whether this item starts a new line |
17
+
18
+ X,Y coordinates are relative to the bottom-left corner (origin 0,0).
19
+
20
+ ## Step 2: Group Text Items into Lines
21
+
22
+ 1. **Merge adjacent items** when `Distance = RightTextItem.X₁ - LeftTextItem.X₂` is less than average character width
23
+ 2. Average character width = total character widths / total character count (exclude bold and newline elements)
24
+ 3. **Group by Y-coordinate** to form lines (same Y = same line)
25
+
26
+ This reconstructs the line-by-line reading order that may be lost in PDF extraction.
27
+
28
+ ## Step 3: Group Lines into Sections
29
+
30
+ ### Section Title Detection (primary heuristic — must satisfy ALL 3):
31
+
32
+ 1. It is the only text item in the line
33
+ 2. It is bolded
34
+ 3. Its letters are all UPPERCASE
35
+
36
+ ### Fallback Heuristic: Keyword matching
37
+
38
+ Known section titles: PROFILE, SUMMARY, OBJECTIVE, ABOUT, EDUCATION, ACADEMIC, DEGREES, EXPERIENCE, WORK EXPERIENCE, EMPLOYMENT, PROFESSIONAL EXPERIENCE, SKILLS, TECHNICAL SKILLS, COMPETENCIES, PROJECTS, PORTFOLIO, CERTIFICATIONS, LICENSES, HONORS, AWARDS, VOLUNTEER, COMMUNITY, LEADERSHIP, PUBLICATIONS, RESEARCH, INTERESTS, ACTIVITIES, HOBBIES
39
+
40
+ - Group all lines under their closest preceding section title
41
+ - Lines before any section title go into the PROFILE section
42
+
43
+ ## Step 4: Extract Resume Attributes using Feature Scoring
44
+
45
+ Each attribute has **feature sets** (matching function + score). Run every text item through all feature sets for an attribute. The text item with the **highest total feature score** is extracted as that attribute.
46
+
47
+ ### Subsection Detection (for Education, Work Experience, etc.)
48
+
49
+ - **Primary**: vertical line gap > typical line gap × 1.4
50
+ - **Fallback**: text item is bolded
51
+
52
+ ### Feature Scoring Tables
53
+
54
+ #### Name
55
+
56
+ | Feature | Score |
57
+ |---------|-------|
58
+ | Contains only letters, spaces or periods | +3 |
59
+ | Is bolded | +2 |
60
+ | Contains all uppercase letters | +2 |
61
+ | Contains @ (may be email) | -4 |
62
+ | Contains number (may be phone) | -4 |
63
+ | Contains , (may be address) | -4 |
64
+ | Contains / (may be URL) | -4 |
65
+
66
+ #### Email
67
+
68
+ | Feature | Score |
69
+ |---------|-------|
70
+ | Matches email regex `\S+@\S+\.\S+` | +5 |
71
+ | Contains @ | +2 |
72
+
73
+ #### Phone
74
+
75
+ | Feature | Score |
76
+ |---------|-------|
77
+ | Matches phone regex `\(?\d{3}\)?[\s-]?\d{3}[\s-]?\d{4}` | +5 |
78
+
79
+ #### Location
80
+
81
+ | Feature | Score |
82
+ |---------|-------|
83
+ | Matches city,state regex `[A-Z][a-zA-Z\s]+, [A-Z]{2}` | +5 |
84
+
85
+ #### URL
86
+
87
+ | Feature | Score |
88
+ |---------|-------|
89
+ | Matches URL regex `\S+\.[a-z]+\/\S+` | +5 |
90
+
91
+ #### School
92
+
93
+ | Feature | Score |
94
+ |---------|-------|
95
+ | Contains school keyword (College, University, School, Institute, Academy) | +4 |
96
+
97
+ #### Degree
98
+
99
+ | Feature | Score |
100
+ |---------|-------|
101
+ | Contains degree keyword (Associate, Bachelor, Master, Doctorate, B.S., B.A., M.S., M.A., Ph.D.) | +4 |
102
+
103
+ #### GPA
104
+
105
+ | Feature | Score |
106
+ |---------|-------|
107
+ | Matches GPA regex `[0-4]\.\d{1,2}` | +5 |
108
+
109
+ ## ATS Compatibility Scoring Framework
110
+
111
+ | Dimension | Weight |
112
+ |-----------|--------|
113
+ | Name extraction | 20 pts |
114
+ | Email extraction | 20 pts |
115
+ | Phone extraction | 10 pts |
116
+ | Section detection | 15 pts |
117
+ | Education parsing | 10 pts |
118
+ | Experience parsing | 15 pts |
119
+ | Skills parsing | 10 pts |
120
+
121
+ ### Issue Severity Levels
122
+
123
+ - **CRITICAL**: Name or email cannot be parsed (ATS will likely discard)
124
+ - **HIGH**: Key sections missing, dates unparseable, phone not found
125
+ - **MEDIUM**: Skills not extracted cleanly, formatting merge issues
126
+ - **LOW**: Minor inconsistencies, optional fields missing