pendevster

job-search-mcp

Community pendevster
Updated

job-search-mcp

An MCP server for job hunting under a visa constraint.

If you need sponsorship, most job search tooling answers the wrong question. It tellsyou a role exists. It does not tell you whether the employer can legally hire you, orwhether the "mid-level" title is hiding a senior brief, or that the company posting therole is a recruitment agency that holds no licence at all.

This server answers those questions. It exposes four tools over the Model ContextProtocol so an AI assistant can check them itselfinstead of guessing.

Tools

Tool Answers
check_sponsor Does this employer hold a UK Skilled Worker licence, and how much can I trust the match?
screen_posting Are there hard bars here? Is the title telling the truth about seniority?
search_roles What is live right now, minus the agencies?
application_history Have I already applied here?

Why confidence grading exists

The obvious way to check a sponsor licence is to search the register for the companyname. That is how this started, and it is wrong often enough to be dangerous.

Company names collide. To match Pimberly against its registered name PimberlySoftware Development Limited, you have to strip words like "Software" and "Limited".That same normalisation turns Minerva Defence into minerva, which matches thirteenunrelated companies: a furnishing business, a credit agency, a supported-livingprovider.

So check_sponsor returns a confidence grade rather than a boolean:

  • high — the distinctive part of the name matched exactly, once.
  • verify — something matched, but it could be coincidence. Confirm the employer'sregistered legal entity, then look that name up.
  • none — nothing matched. This is not proof they cannot sponsor. Many licensedemployers trade under a name unlike their registered one.

Real cases that shaped this:

Searched Matched What was true
Minerva Defence 13 unrelated "Minerva" rows MINERVA DEFENCE LTD is not on the register, nor its former name PARABELLUM TECHNOLOGIES LTD
Prevail Prevail Technology Limited (Poole) The employer is Prevail Partners Ltd, which is absent. Same town, different company
MAGIC MAGIC SOFTWARE SERVICES LTD Right answer, wrong evidence. The employer is MAGIC TECH LTD, also licensed
TransPerfect PERFECT DIGITAL LTD Matched on the word "perfect"
eFinancialCareers eFinancialCareers Ltd Correct and useless: licensed, but a job board. Roles under its name belong to unnamed third parties

Why screen_posting reads the body, not the title

A posting titled "Software Engineer" opened with "As a Senior Software Engineer youwill" and asked for someone to join "the founding team". Another titled "SoftwareEngineer (Java Mid)" named a senior grade three paragraphs down. Title-based filteringmisses both.

screen_posting also catches hard bars that no amount of tailoring survives:

You must be a UK citizen and have lived in the UK for the past 10 years.
You must already hold high-level UK security clearance.

and the one that matters most when you need sponsorship, from a company thatholds an A-rated licence:

We are unable to offer visa sponsorship for this role. Candidates who need visa
sponsorship now or will need it in the future will not be considered.

A licence means a company can sponsor. It does not mean it will.

Why search_roles returns a funnel

UK job boards are dominated by recruitment agencies, and an agency does not hold thesponsor licence for a role it advertises. Filtering them out is essential and brutal:a typical search drops from seven results to one.

One result with no explanation looks like a bug. So the tool returns what each stageremoved:

{
  "totalFromSource": 7,
  "funnel": { "fromSource": 7, "afterAgencyFilter": 2, "afterSalaryAndAge": 1 },
  "notes": ["5 of 7 results were recruitment agencies or job boards. ..."]
}

Unpublished salaries are kept, never filtered out. Silence about pay is not evidenceof low pay.

Install

npm install && npm run build

Download the current register (about 11 MB, updated regularly):

https://www.gov.uk/government/publications/register-of-licensed-sponsors-workers

Save it as data/register.csv, or point SPONSOR_REGISTER_PATH at it.

Claude Desktop / Claude Code

{
  "mcpServers": {
    "job-search": {
      "command": "node",
      "args": ["/absolute/path/to/job-search-mcp/dist/index.js"],
      "env": {
        "SPONSOR_REGISTER_PATH": "/absolute/path/to/data/register.csv",
        "REED_API_KEY_FILE": "/absolute/path/to/.reed-api-key"
      }
    }
  }
}
Variable Required Purpose
SPONSOR_REGISTER_PATH no Register CSV. Defaults to ./data/register.csv
REED_API_KEY_FILE for search_roles Path to a file containing the key. Preferred: the secret lives in one place and the client config holds only a path
REED_API_KEY alternative The key inline. Simpler, but copies the secret into your MCP config
APPLICATION_LEDGER_PATH no NDJSON application history

No credential is ever read from a file inside the repo, and the register is gitignored.

Or with the Claude Code CLI:

claude mcp add job-search --scope user \
  --env SPONSOR_REGISTER_PATH=/path/to/data/register.csv \
  --env REED_API_KEY_FILE=/path/to/.reed-api-key \
  -- node /path/to/job-search-mcp/dist/index.js

Tests

npm test

54 tests. Every fixture is a real posting or a real register entry that defeated anearlier version of this code. The Reed tests mock fetch, so the suite runs offlineand costs no API quota.

Two bugs the suite caught while it was being written:

  • £40,000-85,000 parsed as a flat £40,000, because the second figure omits thecurrency symbol. Against a salary threshold, that is the difference between "clearsit" and "does not".
  • An agency filter written as \brecruit\b never matched Recruitment orConsultancy. Roughly fifty agencies passed straight through.

Design notes

core() deliberately destroys information. Stripping descriptors is what makesbrand-to-legal-name matching work, and it is exactly what causes false positives. Theconfidence grade prices that trade-off instead of hiding it.

Absence is not a negative. none carries a caveat saying so. The costliest error inthis domain is concluding that an unlisted employer cannot sponsor.

Read-only. The server reads the application ledger; it never writes to it. Recordingan outcome is a decision a person should make.

Licence

MIT

MCP Server · Populars

MCP Server · New

    Get-Concord-AI

    Concord MCP

    Live messaging for coding agents

    Community Get-Concord-AI
    alijancb

    Subio MCP

    Open-source MCP server for discovering fast-growing internet conversations with Subio

    Community alijancb
    ruezo

    MCP Video Digest (视频内容提取总结)

    MCP Server for transcribing videos via video links and summarizing video content

    Community ruezo
    LastSearch-HQ

    LastSearch

    Reliable research infrastructure for AI agents. Evidence-backed web search with citations, confidence scores, and Clarity anti-hallucination. MCP server, REST API, Python SDK.

    Community LastSearch-HQ
    gtfodevs

    Autonomo MCP

    Tired of 'it works' lies? Autonomo MCP makes your AI prove it—on real hardware, right in your editor.

    Community gtfodevs