job-search-mcp
README.md
# job-search-mcp
Infrastructure for running a **job search with Claude Code**. Point it at a folder with your CV +
a small config; it discovers roles, fetches each company's **exact** application fields, drafts
**non-trivial** applications (positioning, not just autofill), and renders a **navigable, offline
dashboard** with one-click copy for every field. Nothing is auto-submitted — you review and send.
Works two ways: as a set of **Claude Code skills + an MCP server** (talk to Claude), or as a **CLI**.
---
## What it does
| Step | Module | Output |
|---|---|---|
| CV → structured profile JSON | `parse_cv.py` | `<data>/profile.json` |
| Discover roles (LinkedIn/Indeed/Naukri/Google) | `scrape_jobs.py` | `<data>/output/jobs.json` |
| Fetch a job's **exact** required fields | `ats.py` | Greenhouse + Ashby = full; Lever/Workday = standard |
| Fill an application against those fields | `generate_application.py` | `<data>/applications/*.json` |
| Make it **non-trivial** (reframe + product teardown + proof-map) | `nontrivial.py` | a `nontrivial` block per application |
| Render everything to one offline page | `build_dashboard.py` | `<data>/dashboard.html` |
**Design principle — human-in-the-loop.** It prepares applications; you submit them. Fully-automated
apply bots violate LinkedIn policy (permanent-ban risk) and are out of scope by design.
## Your data folder
You keep your inputs and outputs in one folder, separate from this repo. Point the tool at it with
`--data-dir` or the `JOBSEARCH_DATA` env var.
```
my-jobsearch/
profile.json # from parse-cv, or copy examples/profile.example.json
config.json # optional; copy examples/config.example.json
companies.json # optional; a curated target list (Claude can research one)
nontrivial_kits.json # optional; pre-authored per-company kits
output/jobs.json # written by the tool
applications/*.json # written by the tool
dashboard.html # written by the tool
```
## Setup
```bash
python3 -m venv .venv && source .venv/bin/activate # Python 3.10+
pip install -r requirements.txt
export ANTHROPIC_API_KEY=… # optional: LLM CV-parsing + auto-drafted non-trivial kits
```
## Use it — CLI
```bash
D=~/my-jobsearch
python -m src.cli --data-dir $D parse-cv --cv ~/MyCV.pdf # CV -> profile.json
python -m src.cli --data-dir $D scrape # -> output/jobs.json
python -m src.cli --data-dir $D apply --url "<job_url>" # -> applications/<company>.json (+ non-trivial kit)
python -m src.cli --data-dir $D dashboard # -> dashboard.html
open $D/dashboard.html # or: python -m http.server -d $D
```
## Use it — Claude Code (MCP + skills)
1. Add the MCP server (see `.mcp.json`) and set `JOBSEARCH_DATA` to your folder.
2. In a Claude Code session in this repo, just ask: *"find jobs"*, *"apply to <link>"*,
*"make this application non-trivial"*, *"build my dashboard"*. The skills in `.claude/skills/`
drive the backend; the MCP server (`src/mcp_server.py`) exposes the same as callable tools
(`get_profile`, `read_jobs`, `refresh_jobs`, `get_application_fields`, `generate_application`,
`make_nontrivial`, `score_triviality`, `build_dashboard`, `list_companies`).
## What "non-trivial" means
A *trivial* application restates your CV in the form's fields — the axis an ATS reduces to keywords.
A *non-trivial* one changes what the reader thinks they're hiring for: it **reframes** the role onto
an axis where you win, carries a **witness only you could produce** (a short teardown of *their*
product through your lens), and **maps every claim to a real fact in your CV** (the honesty gate —
unbacked claims are flagged, never invented). See `src/nontrivial.py` and the `make-nontrivial` skill.
## Tests
```bash
python -m tests.adversarial # offline
python -m tests.adversarial --net # + live ATS probes
```
## Honest caveats
- **Scraping ToS:** Naukri/LinkedIn/Indeed prohibit automated scraping. For personal, low-volume use
the practical risk is IP rate-limiting, not litigation — run modestly and pair with each board's own
saved-search alerts. If a board returns nothing, it's likely a temporary block.
- **Fetch failures are surfaced, never hidden.** If a company's real form can't be loaded, the template
is flagged `fetch_failed` and the dashboard shows a red banner — verify on the apply page.
- **Salary/notice/relocation** are marked `TODO_CONFIRM` and surfaced for review; the tool never guesses them.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessSyncing