{
  "markdown": "# SponsorFinder MCP Server\n\nAn authless, read-only remote [MCP](https://modelcontextprotocol.io) server that lets AI assistants (Claude, ChatGPT, Cursor, …) check whether a company holds a **UK** or **Netherlands** work-visa sponsorship licence. It proxies the public [SponsorFinder](https://sponsorfinder.io) API, shaping responses into clean verdicts, and keeps the upstream API key server-side so clients connect with no credentials.\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)\n[![Node >=24](https://img.shields.io/badge/Node-%3E%3D24-339933?logo=node.js&logoColor=white)](https://nodejs.org)\n[![Built with MCP](https://img.shields.io/badge/Built%20with-Model%20Context%20Protocol-6E56CF)](https://modelcontextprotocol.io)\n\n## What it does\n\nSponsorFinder tracks two official government registers of licensed work-visa sponsors:\n\n- **UK** — the [Home Office register of licensed sponsors](https://www.gov.uk/government/publications/register-of-licensed-sponsors-workers), rebuilt from the CSVs the Home Office publishes (checked daily). Carries routes (e.g. Skilled Worker), ratings (A/B) and locations.\n- **Netherlands** — the [IND public register of recognised sponsors](https://ind.nl/en/public-register-recognised-sponsors), checked daily. Lists recognised sponsors and their sponsor type (WORK / EXCHANGE / STUDY / RESEARCH); much thinner than the UK data — no routes, ratings, or locations.\n\nThis MCP server exposes that data as four tools. It is **read-only** and **authless for clients**: the upstream `x-api-key` is a server-side secret that MCP clients never see. There is no OAuth, no per-user state, and no write tools.\n\n## Tools\n\n| Tool                    | Title                       | What it does                                                                                                                                                                                                                          | Key inputs                                                                                                                                                                     |\n| ----------------------- | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |\n| `check_sponsor_license` | Check Sponsorship Licence   | Primary tool. Resolves a company by name (typo-tolerant) and returns a verdict — `licensed`, `formerly_licensed`, `ambiguous`, or `not_found` — with routes, ratings, locations and register dates. Refuses to guess on weak matches. | `company_name` (2–100 chars, typos OK), `country` (`uk` \\| `nl` \\| `both`, default `both`)                                                                                     |\n| `search_sponsors`       | Search Sponsor Register     | Exploratory list search with optional filters. Returns a compact list plus a total count. For one specific company, prefer `check_sponsor_license`.                                                                                   | `query?`, `country` (`uk` \\| `nl`, default `uk`), `city?` (UK), `route?` (UK), `sponsor_type?` (NL: `WORK` \\| `EXCHANGE` \\| `STUDY` \\| `RESEARCH`), `limit` (1–20, default 10) |\n| `get_sponsor_details`   | Get Sponsor Details         | Full record for one organization by id: routes/ratings/locations/dates (UK) or sponsor type + KvK number (NL). Optionally includes register change history.                                                                           | `org_id` (int), `country` (`uk` \\| `nl`, default `uk`), `include_history` (bool, default `false`)                                                                              |\n| `get_register_info`     | About the Sponsor Registers | Register statistics, data freshness, a terminology glossary, and the legal disclaimer. Use it to explain what a licence, route, rating, or sponsor type means.                                                                        | none                                                                                                                                                                           |\n\nEvery tool is annotated `readOnlyHint: true` and returns both a human-readable text block and `structuredContent`, each stamped with the data-freshness date and a source note.\n\n## Example prompts\n\nNatural-language things you can ask an assistant once the server is connected:\n\n- \"Does Google hold a UK sponsorship licence?\"\n- \"Is ASML a recognised sponsor in the Netherlands?\"\n- \"Search UK Skilled Worker sponsors in Manchester.\"\n- \"List Dutch WORK-type sponsors matching 'shell'.\"\n- \"What does a B rating mean?\"\n\n**A note on name matching.** The fuzzy match tolerates typos (e.g. `googel uk`), but it needs a _reasonably complete_ name to resolve confidently — \"Google UK\" or \"Google UK Limited\" resolves cleanly, whereas a single bare word can match many companies. The server deliberately **refuses to guess on weak or tied matches**: instead of silently picking one, it returns an `ambiguous` verdict with the candidate list and asks you to disambiguate (or to call `get_sponsor_details` with the right id). Absence from a register is itself a meaningful answer: it means the company cannot currently sponsor that visa type.\n\n## Use it (hosted)\n\nThe server is hosted at:\n\n```\nhttps://mcp.sponsorfinder.io/mcp\n```\n\n**Claude Code**\n\n```bash\nclaude mcp add --transport http sponsorfinder https://mcp.sponsorfinder.io/mcp\n```\n\n**claude.ai** — Settings → Connectors → **Add custom connector** → paste the URL above. No authentication is required.\n\n**ChatGPT** — Settings → Connectors (or a custom GPT's Actions) → **Add** a custom/remote MCP connector and paste the URL above.\n\nAny MCP client that speaks Streamable HTTP can connect the same way — point it at `https://mcp.sponsorfinder.io/mcp`.\n\n## Run locally\n\n**Prerequisites:** Node.js 24 and pnpm 11.\n\n```bash\npnpm install\ncp .env.example .env\n# then edit .env and fill in:\n#   SPONSORFINDER_API_BASE   e.g. https://api.sponsorfinder.io\n#   SPONSORFINDER_API_KEY    your upstream x-api-key (server-side secret)\n```\n\nRun one of the two transports in watch mode:\n\n```bash\npnpm dev:stdio   # stdio transport (Claude Desktop / Claude Code / MCP Inspector)\npnpm dev:http    # Streamable HTTP on http://localhost:3001/mcp\n```\n\n**Add the local stdio build to Claude Code:**\n\n```bash\npnpm build\nclaude mcp add sponsorfinder -- node dist/entry/stdio.js\n```\n\n**Inspect the tools interactively** with the MCP Inspector against either transport:\n\n```bash\nnpx @modelcontextprotocol/inspector\n```\n\n## Configuration\n\nAll configuration is via environment variables (see `.env.example`):\n\n| Name                     | Required | Default | Description                                                                                                             |\n| ------------------------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------- |\n| `SPONSORFINDER_API_BASE` | yes      | —       | Base URL of the upstream SponsorFinder API, no trailing slash (e.g. `https://api.sponsorfinder.io`).                    |\n| `SPONSORFINDER_API_KEY`  | yes      | —       | Upstream `x-api-key` header value. **Server-side secret — never exposed to MCP clients**, tool output, errors, or logs. |\n| `PORT`                   | no       | `3001`  | HTTP port for the Node entry (`src/entry/node.ts`). Ignored by stdio and Cloudflare Workers.                            |\n| `UPSTREAM_TIMEOUT_MS`    | no       | `10000` | Upstream request timeout in milliseconds (aborted via `AbortSignal.timeout()`).                                         |\n\n`SPONSORFINDER_API_KEY` is the one true secret. MCP clients connect authless; the key lives only on the server (a Docker env var or a Cloudflare Workers secret) and is never surfaced to clients.\n\n## Self-host / deploy\n\nThe Web-standard core runs on both Node and Cloudflare Workers; only the entry file differs.\n\n**Docker (primary)** — image `ghcr.io/alirezahamid/sponsor-finder-mcp`, config in `Dockerfile` and `docker-compose.yml`:\n\n```bash\ndocker compose up -d\n```\n\nPut a reverse proxy (Caddy/nginx) in front of `mcp.sponsorfinder.io` and pass **POST, GET and DELETE** through to `/mcp`. Streamable HTTP needs response **buffering off** (`proxy_buffering off;` in nginx; Caddy's defaults are fine).\n\n**Cloudflare Workers** — config in `wrangler.jsonc`:\n\n```bash\nwrangler secret put SPONSORFINDER_API_KEY\npnpm deploy:worker\n```\n\n## Development\n\n| Script            | What it does                                                          |\n| ----------------- | --------------------------------------------------------------------- |\n| `pnpm typecheck`  | Type-check with `tsc --noEmit`.                                       |\n| `pnpm lint`       | Lint with ESLint.                                                     |\n| `pnpm test`       | Run unit tests (excludes smoke tests).                                |\n| `pnpm test:smoke` | Integration smoke tests against the real staging API (needs secrets). |\n| `pnpm build`      | Bundle to `dist/` with tsup.                                          |\n| `pnpm check`      | `typecheck` + `lint` + `test` in one go.                              |\n\n## Analytics (optional)\n\nThe server can report usage to **Google Analytics 4** via the server-side\n[Measurement Protocol](https://developers.google.com/analytics/devguides/collection/protocol/ga4).\nBecause an MCP server has no browser, a GA/GTM JavaScript tag cannot run in it — the\nserver sends events over HTTP instead. It works on both Node and Cloudflare Workers.\n\nAnalytics are **off** unless both `GA_MEASUREMENT_ID` and `GA_API_SECRET` are set.\nEach tool call emits one `mcp_tool_call` event with **categorical parameters** —\n`tool`, `status`, `verdict`, `country`, `mcp_client`, `latency_bucket`, `error_kind`.\nBy default **no company names or free-text queries are sent to GA**; the searched name\nis only included (as the `query` param) if you opt in with `CAPTURE_QUERY_NAMES` — see below.\n\nSetup:\n\n1. Create a GA4 property (free) and a Web data stream.\n2. In **Admin → Data streams → your stream → Measurement Protocol API secrets**, create a\n   secret. Copy the stream's **Measurement ID** (`G-XXXXXXXXXX`) and the secret value.\n3. Set `GA_MEASUREMENT_ID` and `GA_API_SECRET` (env / Docker / `wrangler secret`).\n4. In GA4, register the event params above as **custom dimensions**\n   (Admin → Custom definitions) so they appear in reports. Use `GA_DEBUG=true` to send to\n   GA's validation endpoint while testing.\n\nUnmet-demand analysis: setting `CAPTURE_QUERY_NAMES=true` records the searched company\nname to the server's structured logs **and** sends it to GA4 as the `query` event param\n(register a `query` custom dimension to see it). Off by default. Caveats: raw names are\nhigh-cardinality in GA (bucketed as `(other)`) and person-named queries may count as PII\nunder GA's terms — a private log store is usually the better home for this, and you should\nadd a privacy-policy line before enabling it.\n\n## How it works\n\nThe server is a thin, stateless proxy with response shaping. An MCP client connects over stdio or stateless Streamable HTTP; a small [Hono](https://hono.dev) app (with `@hono/mcp`) constructs an MCP server per request, calls the SponsorFinder API with the server-side key, validates every response with zod (a contract-drift guard), and shapes it into a compact verdict. Register stats and filter values are cached in-process with a short TTL. Because the core uses only Web-standard APIs (`fetch`, `URL`), the same code runs on Node and Cloudflare Workers — only `src/entry/*` differs.\n\n```\nMCP client (Claude / ChatGPT / Cursor)\n        │  stdio  or  stateless Streamable HTTP\n        ▼\nSponsorFinder MCP server  (Hono + @hono/mcp)\n   • 4 read-only tools, zod-validated\n   • x-api-key added server-side\n   • cached /status + /filters\n        │  HTTPS  (x-api-key)\n        ▼\nSponsorFinder API  →  UK Home Office register + Dutch IND register\n```\n\n## Data & disclaimer\n\nThe data comes from the official [UK gov.uk register of licensed sponsors](https://www.gov.uk/government/publications/register-of-licensed-sponsors-workers) and the [Dutch IND public register of recognised sponsors](https://ind.nl/en/public-register-recognised-sponsors), refreshed daily.\n\nThis tool is **informational only and is not legal advice**. Register data can lag official publications, and a licence does not guarantee a company will sponsor any given role. Always verify against the official sources before making decisions.\n\n## Contributing\n\nIssues and pull requests are welcome at [github.com/alirezahamid/sponsor-finder-mcp](https://github.com/alirezahamid/sponsor-finder-mcp). Please run `pnpm check` before opening a PR.\n\n> **Publishing note:** `server.json` is the manifest for the official MCP registry. Before running `mcp-publisher publish`, confirm the exact `$schema` URL against the current [registry.modelcontextprotocol.io](https://registry.modelcontextprotocol.io) docs — the schema version pinned here may have moved on.\n\n## License\n\n[MIT](./LICENSE) © 2026 Alireza Hamid\n",
  "bytes": 13548,
  "sha": "e3db6f263e2213f653d4bee827367d7746fd942ab8fe32b995881deef44e7640",
  "repo_slug": "alirezahamid/sponsor-finder-mcp",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/mcp_io_sponsorfinder_mcp_501d3158/readme"
}