JobLens MCP
The JobLens MCP server connects AI assistants to live job market data and local resume analysis tools, enabling real-time job search and career matching via ToS-compliant APIs.
Search Live Job Postings: Query real job listings by role/keywords, location, and country. Returns structured data including title, company, salary, and description via the Adzuna API.
List Job Categories: Retrieve supported job categories for a given country to discover available search filters.
Parse a Local Resume: Extract skills, email, and phone number from a local PDF or
.txtfile — all processing happens on-device.Match Resume to a Job: Score (0–100) how well a parsed resume fits a specific job description based on skill overlap, with a breakdown of matched and missing skills.
Search and Match in One Call: Combine job search and resume matching into a single operation, returning results ranked by match score (highest first).
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@JobLens MCPSearch for remote data engineer jobs and tell me which ones best match my resume at /Users/me/resume.pdf."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
JobLens MCP
A Model Context Protocol (MCP) server that gives Claude (or any MCP-compatible AI assistant) structured, live context about jobs and careers: search real job postings, parse a resume locally, and score how well a resume matches a given job — all through official, ToS-compliant APIs and local file parsing. No scraping. No stored platform passwords. No automated browser logins.
Table of Contents
Related MCP server: IAM MCP Server
Why This Exists
Most "LinkedIn scraper" MCP servers automate a real login through Selenium and scrape profile/job pages — which violates LinkedIn's Terms of Service and puts a user's account at risk of a ban.
JobLens solves the same underlying problem — giving an AI assistant rich job-market context — using a free, official job-search API and local resume parsing instead. Same outcome, zero ToS risk.
Features
Feature | Description |
🔍 Live Job Search | Query real job postings (title, company, location, salary, description) via the Adzuna Jobs API |
📄 Resume Parsing | Extract skills, email, and phone from a local PDF/text resume — entirely on-device |
🎯 Resume-to-Job Match Scoring | Transparent skill-overlap score (0–100) between a parsed resume and any job description, with matched/missing skills listed |
⚡ Search + Match | One call searches jobs and ranks them by fit to your resume |
Architecture
joblens-mcp/
├── src/joblens_mcp/
│ ├── server.py # MCP server + tool definitions (FastMCP)
│ ├── jobsource.py # Adzuna API client (swap for any job-board API)
│ └── resume.py # Local resume parsing + match scoring
├── main.py # Entry point
├── pyproject.toml
└── requirements.txtjobsource.py is intentionally isolated from server.py — swapping
Adzuna for USAJobs, Indeed's Publisher API, RemoteOK, or Jooble means
editing one file, not the MCP tool layer.
Installation
Prerequisites
Python 3.10+
A free Adzuna API
app_idandapp_key(instant signup, no scraping involved)
1. Clone the repository
git clone https://github.com/rohith-jpg/joblens-mcp
cd joblens-mcp2. Set up environment & install dependencies
Using uv (recommended):
curl -LsSf https://astral.sh/uv/install.sh | sh
uv venv
source .venv/bin/activate # macOS/Linux
uv pip install -e .Or with plain pip:
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt3. Add your API credentials
cp .env.example .env
# then edit .env with your ADZUNA_APP_ID and ADZUNA_APP_KEY4. Run the server
uv run main.py
# or
python main.pyConfigure Claude Desktop
Add this to your Claude Desktop config (Settings → Developer → Edit Config):
{
"mcpServers": {
"joblens": {
"command": "/path/to/uv",
"args": ["--directory", "/path/to/joblens-mcp", "run", "main.py"],
"env": {
"ADZUNA_APP_ID": "your_app_id",
"ADZUNA_APP_KEY": "your_app_key"
}
}
}
}Restart Claude Desktop, then look for the tools (hammer) icon to confirm JobLens is connected.
Example Prompts
"Search for remote data engineer jobs and tell me which ones best match my resume at
/Users/me/resume.pdf.""Parse my resume and tell me what skills I'm missing for a Senior Backend Engineer role."
"What job categories does the search API support for the UK?"
Roadmap
Additional job-board sources (USAJobs, RemoteOK, Greenhouse public job boards)
cover_letter_drafttool using match results to draft a tailored cover letterCaching/rate-limit handling for high-volume searches
License
MIT — see LICENSE.
Acknowledgements
Built using the Model Context Protocol Python SDK and the Adzuna Jobs API.
Note: This project deliberately avoids any LinkedIn scraping or automated login. All data sources used are official, public APIs or files the user provides locally.
Available Tools
5 toolslist_job_categoriesA
List the job categories the search API supports for a given country.
| Name | Required | Description | Default |
|---|---|---|---|
| country | No | us |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided; description simply states a read operation without detailing side effects, authentication needs, or output structure. Adequate for a simple list tool but limited transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Single sentence, no unnecessary words, front-loaded with core action.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Tool is simple, output schema exists, and description sufficiently covers purpose. Lacks details on output format but overall complete for basic usage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema has 0% description coverage; description adds context that country parameter filters categories but does not clarify format, allowed values, or behavior beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states the verb (list), resource (job categories), and scope (for a given country). It distinguishes from sibling tools which focus on resume matching, parsing, and job searching.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implies usage for retrieving categories per country but lacks explicit guidance on when to prefer this tool over alternatives or when not to use it.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
match_resume_to_jobA
Score how well a parsed resume matches a job description, based on skill-keyword overlap. Returns a 0-100 score plus matched/missing skills.
Args: file_path: absolute path to the resume file (parsed automatically if not cached) job_description: the job posting text to match against
| Name | Required | Description | Default |
|---|---|---|---|
| file_path | Yes | ||
| job_description | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full disclosure burden. It reveals that the tool returns a numeric score plus lists of matched/missing skills, and notes that resumes are parsed automatically if not already cached. This is transparent about core behavior, though it does not mention caching side effects or error handling.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the primary action ('Score how well a parsed resume matches...') and is reasonably concise. Minor redundancy exists ('parsed automatically if not cached' repeats the idea), but overall it efficiently conveys key information in under 50 words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no annotations, no output schema, and only 2 parameters, the description adequately covers inputs and outputs. However, it lacks details on error cases (e.g., invalid file path), expected file format, and the structure of the returned score object. This is minimally viable but leaves gaps for an agent to handle unexpected situations.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, yet the description adds meaningful context for both parameters: file_path is an absolute path to the resume file (with auto-parsing note) and job_description is the job posting text. This provides value beyond the raw type declarations, though more explicit file format constraints could improve clarity.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that the tool scores how well a parsed resume matches a job description based on skill-keyword overlap, returning a 0-100 score and lists of matched/missing skills. It distinguishes from siblings like parse_resume (which only parses) and search_and_match (which likely searches jobs broadly) by focusing specifically on pairwise matching.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description does not provide any guidance on when to use this tool versus alternatives such as search_and_match or parse_resume. It lacks explicit context for usage selection, leaving the agent to infer intent without comparative criteria.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
parse_resumeA
Parse a local resume file (PDF or .txt) into structured data: extracted skills, email, and phone number. The file never leaves your machine — this just reads it locally.
Args: file_path: absolute path to the resume file on disk
| Name | Required | Description | Default |
|---|---|---|---|
| file_path | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full burden. It discloses that the operation is local and no data leaves the machine, which is helpful. However, it lacks details on error handling, file size limits, or permissions, which would improve transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise with two sentences and an arg description. No unnecessary words, and it front-loads the key information (purpose and local nature).
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple tool with one parameter and no output schema, the description covers the essential aspects: what it does, privacy guarantee, and parameter clarification. It could mention return format or error conditions, but given its simplicity, it is sufficiently complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description adds meaning by specifying that 'file_path' is an absolute path to a local file on disk. This goes beyond the schema's minimal 'File Path' title and type string, though it could include more details like accepted formats.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('Parse'), the resource ('local resume file'), and the output ('structured data: extracted skills, email, and phone number'). It distinguishes from siblings like 'search_jobs' or 'match_resume_to_job', which involve searching or matching rather than parsing.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description specifies when to use the tool (when you have a local resume file) and notes that the file never leaves the machine, which is a privacy guideline. However, it does not explicitly state when not to use it or suggest alternative tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_and_matchA
Convenience tool: search live jobs, then rank each result by how well it matches the given resume. Returns jobs sorted by match score (desc).
Args: file_path: absolute path to the resume file query: role or keywords to search for location: city/region filter (optional) country: 2-letter country code (default "us") results_per_page: how many postings to fetch before ranking
| Name | Required | Description | Default |
|---|---|---|---|
| file_path | Yes | ||
| query | Yes | ||
| location | No | ||
| country | No | us | |
| results_per_page | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full burden. It discloses that the tool searches, ranks by match score, and returns sorted results. It also notes that 'results_per_page' controls how many postings are fetched before ranking. However, it omits potential error states or file format constraints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a brief intro followed by a clean list of parameters. Every sentence adds value; no fluff. Front-loaded with purpose, making it easy to scan.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has 5 parameters (2 required) and an output schema exists. The description covers the workflow and all parameters adequately. It could mention behavior on invalid input or no matches, but given the output schema, it is largely complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the description must compensate. It provides clear, concise explanations for each parameter (e.g., 'file_path: absolute path to the resume file', 'query: role or keywords'). This adds meaning beyond the schema titles, though it does not detail constraints like valid file formats.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's function: 'search live jobs, then rank each result by how well it matches the given resume.' It specifies the output ('sorted by match score') and distinguishes it from siblings like 'search_jobs' and 'match_resume_to_job'.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The tool is labeled as 'Convenience tool,' implying it combines search and matching. While it doesn't explicitly state when not to use it or list alternatives, the presence of sibling tools (e.g., 'search_jobs', 'match_resume_to_job') allows agents to infer appropriate usage contexts.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_jobsB
Search live job postings.
Args: query: role or keywords, e.g. "machine learning engineer" location: city/region filter, e.g. "Atlanta, GA" (optional) country: 2-letter country code Adzuna supports (default "us") results_per_page: how many postings to return (max ~50)
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | ||
| location | No | ||
| country | No | us | |
| results_per_page | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full burden. It mentions a maximum of ~50 results per page but does not disclose authentication needs, rate limits, error handling, or other behavioral traits expected for a data retrieval tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with a brief opening and an Args list. It is concise, with no extraneous information, though it could be slightly more streamlined.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return value details are not required. Parameter descriptions are complete, but missing usage guidelines and behavioral transparency reduces overall completeness. For a tool with moderate complexity, this is adequate but has clear gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, and the description effectively compensates by explaining each parameter: query with example, location as optional with example, country with default and context (Adzuna supported), and results_per_page with max limit. This adds significant meaning beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states 'Search live job postings', which is a clear verb+resource combination. It distinguishes from sibling tools like list_job_categories or parse_resume, but does not explicitly contrast with search_and_match, leaving minor ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit guidance on when to use this tool versus alternatives. The description implies usage for searching job postings but does not provide when-not-to-use or exclude scenarios, leaving the agent without sufficient context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v0.1.0- First observed
list_job_categories - First observed
match_resume_to_job - First observed
parse_resume - First observed
search_and_match - First observed
search_jobs
TDQS
Scored across 5 tools
Each tool has a distinct purpose: listing categories, parsing resumes, matching a resume to a job, searching jobs, and a convenience combiner. The descriptions clearly differentiate them, even the combined search_and_match is clearly a hybrid of search_jobs and match_resume_to_job.
All tool names follow a consistent verb_noun pattern in snake_case, e.g., list_job_categories, parse_resume, search_jobs. The naming is predictable and easy to interpret.
With 5 tools, the server is well-scoped for its purpose: listing categories, parsing, matching, searching, and a combined tool. Each tool earns its place without redundancy or bloat.
The tool set covers the core workflow of parsing, matching, and searching jobs. A minor gap is the lack of a tool to list supported countries or retrieve job details by ID, but the existing tools handle primary use cases effectively.
Maintenance
Related MCP Connectors
Unified jobs search over official feeds + ATS boards (USAJOBS, Adzuna, Muse, Greenhouse, Lever...)
Analyze job listings against your resume, track applications, and generate cover letters.
Career assistant: resumes, job-match analysis, interview results and career memory.
Search jobs, tailor your resume, write cover letters, and file applications for you.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceEnables users to search for jobs, retrieve profiles, and fetch feed posts through the LinkedIn API. It also provides tools for analyzing and extracting data from PDF resumes.-
- AlicenseNot gradedqualityCmaintenanceProcesses and manages applicant resumes, facilitates job searches, generates job-specific resumes, and creates tailored cover letters.1MIT
- FlicenseNot gradedqualityBmaintenanceEnables AI clients to manage resumes, match job descriptions, and generate tailored PDF resumes.3-
- AlicenseNot gradedqualityAmaintenanceEnables AI agents to discover, filter, and track job openings based on the user's local resume, without uploading data to the cloud.15MIT