Skip to main content
Glama
README.md
# uk-visa-sponsor-mcp

[![CI](https://github.com/SAIDUMPALA01/uk-visa-sponsor-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/SAIDUMPALA01/uk-visa-sponsor-mcp/actions/workflows/ci.yml)
![Python 3.10+](https://img.shields.io/badge/python-3.10%2B-blue)
![MCP](https://img.shields.io/badge/Model%20Context%20Protocol-server-6f42c1)
![License: MIT](https://img.shields.io/badge/license-MIT-green)

**An MCP server and CLI that answer the two questions every international job seeker in the UK asks: *"Can this employer sponsor my visa?"* and *"Is this salary high enough for a Skilled Worker visa?"***

Plug it into Claude Desktop, Claude Code or any [Model Context Protocol](https://modelcontextprotocol.io) client, and your assistant can check the Home Office's official Register of Licensed Sponsors and the Skilled Worker salary rules in the middle of a conversation:

> **You:** I've got an offer from Northwind Analytics in London for £40,000 as a junior ML engineer. I'm on a Graduate visa. Can they sponsor me?
>
> **Assistant** *(calls `search_sponsors` and `check_offer_salary`)*: Northwind Analytics Ltd (London) holds an A-rated Skilled Worker licence. ML engineer roles usually fall under SOC 2134. Switching from a Graduate visa makes you a *new entrant*, so the minimum is the higher of £33,400 and 70% of the £54,700 going rate, which is £38,290. £40,000 meets it. A licence means they *can* sponsor, so confirm with them that they *will*, and check the current rules on GOV.UK.

*(Illustrative conversation; "Northwind Analytics" is a fictional company from the test data.)*

I built this because I needed it: I'm a recent MSc graduate in London on a Graduate visa, and checking every employer and offer by hand was slow and error-prone.

---

## Tools

| Tool | What it does |
|---|---|
| `search_sponsors(company, town?, route="Skilled Worker", limit=10)` | Fuzzy search of the official register. Handles "Ltd/PLC/Limited", "&" and typos, and filters by town and visa route |
| `check_offer_salary(soc_code, annual_salary, new_entrant=false, weekly_hours=37.5)` | Does a salary meet the Skilled Worker minimum? Returns the required amount, the shortfall and the reasoning |
| `list_occupations()` | Tech-related SOC 2020 codes with going rates and new-entrant minimums |
| `register_status()` | Organisations per route in the loaded register, and when it was downloaded |

Every salary result carries a disclaimer, and the server's instructions tell the model to pass it on.

---

## Install

```bash
pip install git+https://github.com/SAIDUMPALA01/uk-visa-sponsor-mcp.git
sponsorcheck fetch          # downloads the latest register (about 127,000 organisations as of mid-2026) from GOV.UK
```

**Claude Code**

```bash
claude mcp add uk-visa-sponsor -- sponsorcheck mcp
```

**Claude Desktop**: add to `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "uk-visa-sponsor": {
      "command": "sponsorcheck",
      "args": ["mcp"]
    }
  }
}
```

Set `SPONSORCHECK_REGISTER` if you keep the CSV somewhere other than `~/.cache/sponsorcheck/register.csv`.

## CLI

The same features work without an AI client:

```console
$ sponsorcheck salary 2134 36000 --new-entrant
2134 Programmers and software development professionals, £36,000, new_entrant route: DOES NOT MEET (short by £2,290)
  - needs at least £38,290 (the higher of the amounts below)
  - new-entrant floor £33,400
  - 70% of the going rate = £38,290

$ sponsorcheck search "deutsche bank" --town London
$ sponsorcheck occupations
```

Exit codes make it scriptable: `0` means a match was found or the salary meets the rule, `1` means it doesn't, `2` means an input error.

---

## How it works

- **Data**: `sponsorcheck fetch` looks up the current CSV through the public [GOV.UK Content API](https://content-api.publishing.service.gov.uk/) for the [register publication](https://www.gov.uk/government/publications/register-of-licensed-sponsors-workers), because the file URL changes with every update. The register has one row per organisation and route; rows are grouped into one record per organisation with all its routes and ratings.
- **Name matching**: names are normalised (case, punctuation, "&" → "and", legal suffixes such as Ltd/PLC/LLP/UK removed) and ranked with RapidFuzz's weighted ratio. Exact normalised matches always rank first, and matches below a score of 80 are dropped rather than shown as false hope.
- **Salary rules**: [`salary.py`](src/sponsorcheck/salary.py) encodes the rules for applications from 22 July 2025:
  - **Standard route**: at least £41,700 *and* the occupation's going rate.
  - **New-entrant route**: at least £33,400 *and* 70% of the going rate, plus an hourly minimum of £17.13.
  - Going rates assume a 37.5-hour week and are pro-rated for other hours.
  - Every constant is in one file, with its source.
- **MCP**: built on the official [`mcp` Python SDK](https://github.com/modelcontextprotocol/python-sdk) (v2), stdio transport. The tests start the real server process and talk to it with the SDK's client.
- **Quality**: 30 tests (salary edge cases, fuzzy matching, CSV parsing, mocked GOV.UK download, MCP tool calls, CLI). A weekly CI job downloads the live register to catch format changes early.

## Limits — please read

- **This is not legal advice.** Immigration rules change. The October 2026 Budget announced lower going rates (25th percentile) with no start date yet; when that happens, the figures in `salary.py` must be updated.
- Going rates were taken from secondary sources (listed in `salary.py`) because GOV.UK's Appendix Skilled Occupations could not be checked directly while building this. **Verify them before relying on a result.**
- Only the standard and new-entrant routes are modelled. PhD, shortage-list and transitional options are not.
- The Home Office decides the SOC code from a job's *duties*, not its title.
- A sponsor licence means an employer *can* sponsor. It doesn't mean it will sponsor a particular role.

## Development

```bash
pip install -e ".[dev]"
pytest
ruff check . && ruff format --check .
```

The test register (`tests/fixtures/register.csv`) uses fictional company names.

---

MIT licence. Built by **Sai Dumpala** — [GitHub](https://github.com/SAIDUMPALA01) · [LinkedIn](https://www.linkedin.com/in/sai-dumpala)