Skip to main content
Glama

jobpipe

tests python MCP licence

An MCP server that lets Claude run a job-search pipeline, where the model's judgement is checked by code before it is allowed to count.

Claude does the one thing a model is good at here: reading a job description and judging fit. Everything else (sourcing, de-duplication, visa-sponsor checks, hard eligibility rules, storage, calibration) is plain, testable Python. And the model's scores are not trusted on faith: every score must quote the job description, and the server verifies the quote exists before the score counts.

It reads only public, unauthenticated sources. No LinkedIn scraping, no session cookies, no form submission.


Why this is interesting beyond job hunting

The pattern is general: use an LLM for judgement, and wrap it in deterministic controls that make the judgement auditable. It is the same idea I apply professionally when validating AI systems in financial services.

Control

How jobpipe implements it

Narrow the model's job

Deterministic rules reject impossible postings first, so the model only scores plausible ones

Ground every claim

Each rubric dimension needs a verbatim quote from the job description

Verify, don't trust

The server checks each quote really appears in the text; fabricated evidence voids that dimension (scores 0, weight still counts)

Allow honest "don't know"

A dimension can abstain; it leaves the denominator but blocks automatic progression

Measure it

You label postings by hand and get precision and recall per band

Audit trail

Nothing is silently discarded; every rejection keeps its rule and evidence

Related MCP server: job-search-mcp

How it works

flowchart LR
    A["Greenhouse / Lever / Ashby<br/>public JSON boards"] --> B[Normalise + dedupe]
    B --> C["UK sponsor register<br/>(GOV.UK CSV)"]
    C --> D["Deterministic rules<br/>no model"]
    D -->|REJECT, with reason| X[(kept for audit)]
    D -->|PASS / REVIEW| E["Claude scores<br/>against rubric"]
    E --> F{"Evidence check<br/>quote in JD?"}
    F -->|no| G[dimension voided]
    F -->|yes| H[score counts]
    G --> I[Band: AUTO_DRAFT / REVIEW / REJECT]
    H --> I
    I --> J["Your labels → precision / recall"]

The evidence check, concretely

The model returns, for each dimension, a score and a quote:

{"job_id": "greenhouse:examplecapital:123",
 "dimensions": {
   "quant_depth": {"score": 4, "abstain": false,
                   "evidence": "backtesting and benchmarking of pricing models"},
   "...": "one entry per rubric dimension"}}

record_assessment normalises typography and whitespace, then confirms the quote occurs in the stored description (a 95% fuzzy floor tolerates curly quotes and line breaks, nothing looser). If it does not, the dimension is voided and the job cannot reach AUTO_DRAFT however high its total. Fabricating evidence therefore lowers the score instead of being ignored. That is the difference between a prompt that asks for citations and a system that enforces them.

Live check (15 October 2026)

The parsers were run against three real public boards, one per ATS, using examples/live_check.py:

Board

ATS

Postings parsed

Empty descriptions

Missing dates

Monzo

Greenhouse

68

0

0

Palantir

Lever

315

0

0

Cohere

Ashby

116

0

0

Total

499

0

0

Deterministic pre-filter on those 499 (sponsor register not consulted in this check):

Verdict

Count

REJECT (hard rule failed)

216

REVIEW (soft rule failed)

200

PASS

83

The security-clearance rule fired 181 times (171 Palantir, 10 Cohere). Spot checks confirmed these were genuine clearance requirements, not keyword noise. So before a single token is spent, the model's workload drops from 499 postings to the 283 that are actually possible.

Tools exposed to Claude

Tool

Stage

fetch_jobs

Poll configured Greenhouse/Lever/Ashby boards, dedupe, store

refresh_sponsor_register

Download the current GOV.UK register (24h cache)

check_sponsorship

Match employers → CONFIRMED / AMBIGUOUS / NOT_FOUND

run_prefilter

Deterministic rules; rejects keep their reasons

get_rubric

Rubric text + JSON schema for scoring

next_to_score

Jobs that cleared the pre-filter

record_assessment

Validate evidence, compute band, store

label_job

Your own APPLY / MAYBE / NO, for calibration

calibration_report

Precision and recall against your labels

list_pipeline

Current state

mark_applied

Outcome tracking

Typical session:

refresh_sponsor_register
fetch_jobs
check_sponsorship        (companies from the new jobs)
run_prefilter
next_to_score → get_rubric → score each → record_assessment
list_pipeline band=AUTO_DRAFT

Quick start

git clone https://github.com/Jayaramgokul/jobpipe.git && cd jobpipe
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
cp config.example.yaml config.yaml      # then list the boards you care about
python -m pytest tests/ -q              # 30 offline tests
python examples/live_check.py           # optional: hits three live boards

Connect it to Claude

Claude Code / Claude Desktop (local, stdio):

claude mcp add jobpipe -- /full/path/to/.venv/bin/python -m jobpipe.server

or in claude_desktop_config.json:

{
  "mcpServers": {
    "jobpipe": {
      "command": "/full/path/to/.venv/bin/python",
      "args": ["-m", "jobpipe.server"],
      "env": {
        "JOBPIPE_CONFIG": "/full/path/to/config.yaml",
        "JOBPIPE_DATA": "/full/path/to/data"
      }
    }
  }
}

As a remote connector: set JOBPIPE_TRANSPORT=streamable-http and run it behind a host that terminates TLS. A remote connector is reached from the cloud, so localhost will not work. Local stdio is the better default, because the pipeline data is personal.

Project layout

jobpipe/
  ats.py        fetch + normalise Greenhouse, Lever, Ashby; dedupe
  sponsors.py   GOV.UK sponsor register: download, cache, fuzzy match
  prefilter.py  deterministic HARD / SOFT rules with evidence snippets
  rubric.py     rubric, JSON schema, evidence verification, banding
  store.py      SQLite state, labels, calibration metrics
  server.py     MCP server exposing the 11 tools
tests/          30 offline tests (fixtures, no network)
examples/       live smoke test against real boards

Calibrate before trusting it

The weights and thresholds shipped here are a starting guess, not a measurement. Label 40 to 60 postings you have already judged by eye, then run calibration_report. Read precision and recall separately because they cost different things: a false positive wastes a tailoring cycle, a false negative loses a job you wanted. If AUTO_DRAFT precision is below about 0.85, tighten the weights or raise the threshold. If recall is below about 0.7, the threshold is too high.

Limitations, stated plainly

  • Workday is not covered. It has no public JSON feed, which excludes most of the Big Four and most large banks. Use email alerts for those.

  • Company-name matching is genuinely hard. The register holds legal entity names; boards carry brand names. AMBIGUOUS is returned deliberately rather than guessing from the top fuzzy score.

  • Register freshness matters. Ratings change without notice. Force a refresh before acting on anything important.

  • Being on the register is not an offer of sponsorship. It means the employer can sponsor, not that it will for a given role.

  • Board slugs rot. Companies migrate ATS and old boards 404 quietly; fetch_jobs reports these under board_errors.

  • The rubric is tuned to one profile (UK model risk and AI governance). The dimensions live in rubric.py and are meant to be edited.

Licence

MIT

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables running a job search with Claude Code: parses CV, discovers roles, fetches exact application fields, drafts non-trivial applications (positioning, not autofill), and renders an offline dashboard for review.
    -
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables searching and evaluating job postings from LinkedIn and freehire.me directly through Claude Desktop. Provides tools to search jobs, fetch full posting details, and assess candidate fit using eligibility scans and a scoring rubric.
    MIT
  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables Claude Desktop to manage a job search end-to-end: find and score job listings, tailor resumes, generate application messages, and track application history, while leaving final external actions to the user.
    -
  • A
    license
    A
    quality
    C
    maintenance
    Enables AI assistants to evaluate job postings under a UK visa constraint, including sponsor-licence checks with confidence grades, screening for seniority and hard requirements, and role searches that exclude recruitment agencies. It also tracks application history to help avoid duplicate applications.
    4
    46 npm
    MIT