The full upstream README, mirrored here for reference. Install config, tool schemas, adoption signals, and an original overview live on the ATS Jobs — open roles and hiring changes listing page.
One API for six applicant tracking systems: Greenhouse, Lever, Ashby, Workable, Teamtailor and SmartRecruiters.
Give it a company website. It finds the job board itself, returns every open role, and on every run after that returns only what changed — roles opened, roles closed, titles moved, salaries changed — plus derived hiring signals.
No board tokens. No ATS knowledge required. No browser.
| Hosted on Apify | Self-hosted MCP server | |
|---|---|---|
| Setup | none | npx ats-jobs-mcp |
| State between runs | managed | local file |
| Scheduling, retries, storage | included | your own |
| Price | $1 per 1,000 jobs | free |
| Link | apify.com/feedworks/ats-jobs-api | this repo, mcp/ |
The logic is the same code in both. Pick whichever fits.
| Event | Meaning |
|---|---|
job_indexed | Baseline: an open role captured on the first run |
job_posted | A new opening appeared |
job_closed | An opening disappeared |
job_changed | Title, location, department or employment type changed |
salary_changed | Compensation changed |
hiring_accelerating | This month's postings are 2× or more the recent average |
first_role_in_function | First ever hire in sales, AI/ML, security, data — a new budget line opened |
hiring_freeze | Postings dropped to zero after steady hiring |
Every record carries provenance: source URL, HTTP status, fetch time, job count, truncation flag and a confidence value — so an agent can verify before it acts, instead of trusting a claim.
Four tools, usable by any MCP client — Claude Desktop, Cursor, VS Code, your own agent:
| Tool | Question it answers |
|---|---|
find_job_board | Which ATS does this company use, and what is its board token? |
list_jobs | What roles are open right now? |
detect_changes | What changed since the last time I looked? |
hiring_summary | What is this company hiring for — which functions, which locations? |
Claude Desktop config:
State lives in ~/.ats-jobs-mcp/state.json. Override with ATS_MCP_STATE.
Every source is polled with If-None-Match. When nothing changed, the ATS answers 304 with no body.
Measured on the hosted Actor at 512 MB:
| Path | Compute |
|---|---|
Nothing changed (304) | 0.000344 CU per run |
| Baseline, 143 jobs | 0.001386 CU |
That is why watching hundreds of companies every few hours costs cents rather than dollars — and why this project will never open a headless browser to read a job board.
job_closed events are suppressed — a paging artefact must never look like a company shutting down hiring.greenhouse · lever · ashby · workable · teamtailor · smartrecruiters
Detection order: a link on the company careers page → the board token guessed from the domain → Workable short links resolved through their redirect.
Companies that cannot be resolved return a source_unresolved record explaining why, instead of failing silently.
Recruitee and Personio are not listed because they are not verified working. Personio currently answers 429 to non-browser clients; Recruitee endpoints did not resolve in testing. This project does not claim coverage it cannot deliver.
MIT licensed. Contributions welcome, especially new ATS adapters — the interface is one url() and one parse() function per system, see src/adapters/index.js.