job-search-mcp
by jppoamaral
README.md
# job-search-mcp
A local [Model Context Protocol](https://modelcontextprotocol.io) server that turns Claude Desktop into a job-search connector.
## Credit
The search logic and fit-scoring rubric are ported from [MadsLorentzen/ai-job-search](https://github.com/MadsLorentzen/ai-job-search) — specifically its `linkedin-search` / `freehire-search` portal CLIs and its `job-application-assistant` job-evaluation skill. All credit for the original design goes to [Mads Lorentzen](https://github.com/MadsLorentzen). This repo reimplements that logic as a single self-contained Python MCP server (no bun/Node dependency) instead of the original bun/TypeScript CLIs, following the same connector pattern as the sibling [`resume-ats-mcp`](https://github.com/jppoamaral/resume-ats-mcp).
## What it does
Three tools, exposed over MCP:
| Tool | Input | Output |
|---|---|---|
| `search_jobs` | keywords, location, remote/hybrid/onsite, max age, source | matching postings from LinkedIn and/or freehire.me |
| `get_job_detail` | a result's `source` + `id`/URL | full posting text, seniority, employment type, salary (if known) |
| `evaluate_posting` | a job description + candidate profile (text or resume file) | an eligibility-keyword scan plus the five-dimension fit-scoring worksheet, for Claude to fill in |
**search_jobs** — queries LinkedIn's public `jobs-guest` API (HTML, no auth) and the freehire.me aggregator's public REST API (JSON, no auth; ~50 ATS platforms, global/remote coverage).
**get_job_detail** — fetches one posting's full text, for either source.
**evaluate_posting** — like `resume-ats`'s `evaluate_resume`, this tool does *not* compute a fit score itself. It regex-scans the posting for citizenship/PR/security-clearance/sponsorship language (quoting matched sentences) and assembles the ai-job-search framework's eligibility gate, scoring rubric, weighting, and thresholds — structured, deterministic material for Claude to reason over in the conversation, not a replacement for that reasoning.
## How the connector is registered
```json
{
"mcpServers": {
"job-search": {
"command": "/absolute/path/to/mcp-server-jobsearch/.venv/bin/python",
"args": ["/absolute/path/to/mcp-server-jobsearch/server.py"]
}
}
}
```
No `env` block is required — unlike `resume-ats`, this connector has no filesystem default to configure. Optionally set `FREEHIRE_API_URL` if self-hosting a freehire instance.
After editing `claude_desktop_config.json`, fully quit (Cmd+Q) and reopen Claude Desktop — it only reads the file at launch.
## Setup
```bash
cd mcp-server-jobsearch
python3 -m venv .venv
./.venv/bin/pip install -r requirements.txt
```
## Limitations
- LinkedIn's guest search endpoint is unauthenticated and undocumented; markup changes on LinkedIn's side can break parsing without notice.
- `search_jobs`'s `location` filter only applies to the LinkedIn source — freehire's location facets use a region/country taxonomy this client doesn't expose.
- The eligibility scan is keyword-based, not semantic: it flags sentences containing known phrases, it doesn't understand intent. Always verify before treating a match (or its absence) as final.
- Single-machine, single-user: this is a local stdio connector, not a hosted service.
## License
MIT
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues