uk-tenders-mcp
You can find, filter, score, and research UK public-sector tenders and companies using read-only MCP tools.
Search open UK public-sector tenders across Find a Tender and Contracts Finder, with optional filters for days, limit, source, regions, and keywords; results are deduplicated, exclude expired deadlines, and include buyer, value, deadline, days_left, and source_url.
List available bid profiles and the value ranges each profile covers.
Score tenders as GO, MAYBE, or NO-GO against a bid profile, returning score reasons, buyer, value, deadline, days_left, and source_url; NO-GO results can be included on request.
Look up a UK company on Companies House by company number, returning status, incorporation date, SIC codes, insolvency history, overdue-accounts status, and source_url.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@uk-tenders-mcp score this week's tenders for rail and civils, show GOs with links"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
uk-tenders-mcp
Read-only MCP tools that let an AI agent find this week's UK public-sector tenders across Find a Tender and Contracts Finder, score them against a bid profile, and check a company on Companies House. Every result has a source link, a buyer, a value and a deadline.
Built by Ahmed Osman as a public, cleaned-up version of the tender-intelligence work I run in production. It uses public data only.
What a run looks like
A live run on 4 Nov 2026, last 7 days, rail_civils profile:
Sources: Find a Tender 445 open tenders, Contracts Finder 41 (cross-listed duplicates merged)
Scored: 471 GO 13 MAYBE 3 NO-GO 455 in about 6 seconds
GO 13 Roads North of the Thames - Bridge Bearings £500,000 8 days left
GO 13 Samlesbury Enterprise Zone - Foul Water Drainage £2,000,000 22 days left
GO 12 HS2 Saltley Viaduct gabion wall £1,000,000 8 days left
GO 11 Lime Tree Wood landslip repair works £1,440,000 29 days left
...Version 0.1 read Contracts Finder alone and found 21 tenders in 3 days, none of them a GO. Since the Procurement Act 2023, most notices go to Find a Tender, which carries about ten times as many open tenders in a typical week.
Related MCP server: koko-call-mcp
Tools
Tool | What it's for | Returns |
| "What tenders are out for bridge works in London this week?" "What else has this buyer got out?" | Open notices from both sources, soonest deadline first, filtered by keyword, region and buyer |
| "Which of this week's tenders are worth bidding for?" | GO and MAYBE first with score, reasons, buyer, value, deadline and days left; NO-GO counted but hidden unless asked |
| "What can you score against?" | Bid profiles and the value range each one bids in |
| "Is this subcontractor still active? Any insolvency history?" | Status, SIC codes, insolvency history, overdue accounts |
Every result carries source_url, and every tender result says which sources answered.
Design decisions
Two sources, one list. Both sites publish OCDS. Notices on both are merged into one record, and the Find a Tender record is kept because it carries more fields. It is marked
also_listed_on: ["Contracts Finder"].Fast despite a slow API. Find a Tender pages with a cursor, so one long window is about 25 sequential calls a week. The window is split into one-day slices fetched in parallel (4 at a time), which brings a week down from about 40 seconds to about 6. Results are cached for 10 minutes, so a search followed by a score costs one fetch.
Only live tenders. Find a Tender mixes every notice type: awards, plans, cancellations. Only tender and tender-update notices are kept, the newest release per procurement wins, cancelled procurements are dropped, and so are tenders whose deadline has passed.
Partial results say so. If one source fails, the other still answers and the result says which one failed. Find a Tender rate-limits heavy use (HTTP 429), so requests back off and retry, honouring
Retry-After; if some day slices still fail, the days that answered are kept and the result reportsmissing_days. A partial result is cached for 1 minute rather than 10, so the next call tries again.Task-shaped, read-only and capped. Four tools that match what people ask.
daysandlimitare clamped, and descriptions are trimmed, so one call cannot flood the model's context.Grounded by design. A missing company returns
found: falserather than a guess. The server tells the agent to cite sources and never fill gaps from memory.Explainable scoring. Rules, not a black box: keywords, anchor terms, exclusions, works CPV codes, the buyer's own works/services/goods label, value range, SME suitability and time left to bid. Every verdict lists its reasons.
How scoring decides
Rule | Effect |
Excluded term (rolling stock, catering, cleaning services…) | NO-GO |
No anchor term anywhere | NO-GO |
Anchor only in passing: not in the title, no works CPV, fewer than two keywords | NO-GO |
Value more than 10x the profile's ceiling | NO-GO: programme-scale, worth a look only as a subcontractor |
Study, system or supply signals with no works CPV or works category | NO-GO |
Keywords | +2 each, up to +6 |
Works CPV (4520, 4522-4524, 45111) / related services CPV (71311, 71312) | +4 / +2 |
Buyer classes it as works / goods | +2 / -3 |
Value in range / out of range | +2 / -3 |
Suitable for SMEs | +1 |
Closes in under 7 days | -2 |
GO at 7 or more, MAYBE at 4 or more.
Bugs the live data caught
Each of these came from a real run, became a labelled eval case and a regression test, and cannot come back silently:
"Platform" (3 Nov). "Candidate Assessment Services" scored MAYBE because "platform" matched an online assessment platform. Now only rail-specific phrases count.
"Station" (4 Nov). An ambulance station refurbishment and a bus station cleaning contract came through, because bare "station" was an anchor term.
Passing mentions (4 Nov). A town festival scored GO on "track record" and a note about site drainage. Now an anchor must be in the title, or backed by a works CPV or two keywords, and "track" only counts in rail phrases.
Programme scale (4 Nov). A £450m rail works framework scored GO on keywords and CPV alone. Notices above 10x the profile ceiling are now NO-GO with a subcontracting note.
Regions (4 Nov). National frameworks showed as "North East" because buyers tick every region and the first was taken. Now all regions are kept, and labelled "England-wide" or "UK-wide" where that applies.
Evaluation
eval/run_eval.py scores a labelled set and prints a confusion matrix. It fails if accuracy drops below 80%, or if any NO-GO case is scored GO, because a false GO wastes bid effort.
Profile: rail_civils Cases: 33 Accuracy: 94% False GO: 0
expected \ got GO MAYBE NO-GO
GO 8 0 0
MAYBE 1 5 0
NO-GO 0 1 18How to read it honestly:
13 cases were written alongside the first rules. 18 are real Find a Tender notices that I labelled by hand and used while tuning this version, so they show the rules behave as intended, not that they generalise.
The 2 misses are held-out: real notices scored after the rules were frozen, which I disagreed with on review. An asbestos refurbishment of a market scores GO (I'd say MAYBE), and a materials-and-tools supply framework scores MAYBE (I'd say NO-GO). They stay in the file as open misses rather than being tuned away.
On the fresh 4 Nov run, I agreed with 14 of the 16 tenders the tool flagged GO or MAYBE.
The next step is labels from real bid and pass decisions, with this rules version as the baseline any learned model has to beat.
Quick start
git clone https://github.com/atz1man/uk-tenders-mcp
cd uk-tenders-mcp
uv sync --extra dev # or: pip install -e ".[dev]"
uv run pytest # 34 tests, no network needed
uv run python eval/run_eval.py # scoring evaluationCompanies House lookups need a free API key from the Companies House developer hub. Copy .env.example to .env, or set COMPANIES_HOUSE_API_KEY in your MCP client config. The tender sources need no key.
Use it in Claude Desktop
Add this to claude_desktop_config.json:
{
"mcpServers": {
"uk-tenders": {
"command": "uv",
"args": ["--directory", "/absolute/path/to/uk-tenders-mcp", "run", "uk-tenders-mcp"],
"env": { "COMPANIES_HOUSE_API_KEY": "your-key" }
}
}
}Then ask: "Score this week's tenders for rail and civils in the North West and show me the GOs with deadlines and links."
Project layout
src/uk_tenders_mcp/
server.py MCP server, the four tools, caching and filters
sources.py Find a Tender and Contracts Finder (OCDS), merging, Companies House
scoring.py bid profiles and GO / MAYBE / NO-GO rules
models.py typed records (Pydantic)
tests/ 34 tests, all offline via a mocked HTTP transport
eval/ labelled set (including real notices) and evaluation script
.github/ CI: tests and evaluation on every pushLimits and next steps
Two profiles (
rail_civils,fire_safety). Profiles are plain data, so adding one is a few lines plus labelled cases.Cross-source matching uses title and buyer, so a notice retitled between sites will appear twice.
Notices with no deadline are kept, and marked with
days_left: null.No write tools, by design. Anything that acts, such as registering interest, would be a separate server, off by default, with human approval.
Built with
Python 3.11+, the MCP Python SDK (v2), httpx, Pydantic, pytest. Licensed MIT.
Available Tools
4 toolsget_companyARead-only
Look up a UK company on Companies House by its company number (for example 00445790).
Returns status, incorporation date, SIC codes, insolvency history and whether accounts are overdue, with a source_url. Use before stating anything about a company's status; never infer it.
Inputs: company_number (required). Returns: object
list_profilesARead-only
List the bid profiles that score_tenders can use, with what each one covers.
Inputs: no named parameters. Returns: object
score_tendersARead-only
Score this week's open tenders GO / MAYBE / NO-GO against a bid profile, with reasons.
Use when the user asks which tenders are worth bidding for. Call list_profiles for valid names.
Searches Find a Tender and Contracts Finder. Returns GO then MAYBE, highest score first, at most
limit (1-50), each with buyer, value, deadline, days_left, reasons and a source_url. NO-GO
results are counted but left out unless include_no_go is true.
Inputs: days, limit, profile, regions, +1 more. Returns: object
search_tendersARead-only
Find open UK public-sector tenders published or updated in the last days days (1-30).
Searches Find a Tender and Contracts Finder together, removes notices listed on both, and drops
tenders whose deadline has passed. Optional filters: keywords (any match in title or description)
and regions (for example ["London", "South East"]). Returns at most limit (1-50), soonest
deadline first, each with buyer, value, deadline, days_left and a source_url to cite.
Inputs: days, limit, source, regions, +1 more. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 4 tools
Each tool targets a distinct step in the workflow: browsing profiles, finding tenders, ranking them, and checking a company. The only soft overlap is between search_tenders and score_tenders, since both query the same sources and return similar fields, but the descriptions clearly separate 'find tenders' from 'which are worth bidding for'.
All four tools follow a clean verb_noun snake_case pattern (list_profiles, search_tenders, score_tenders, get_company). The verb choice is also semantically accurate (list vs search vs score vs get), so names are both consistent and predictable.
Four tools is lean but each has a clear role in a coherent pipeline: profiles -> search -> score, plus an external company lookup. It sits at the low end of the comfortable range; a tender-detail or source-listing tool would round out the surface without bloat.
Core discovery and qualification are covered, but there is no way to fetch a full tender notice (only summary fields with a source_url), no profile creation/editing, and get_company requires a company number with no name-based lookup. These gaps force agents to leave the server or ask the user for data mid-workflow.
Maintenance
Related MCP Connectors
UK public procurement data for AI agents: tenders, contracts, buyer and supplier profiles.
Government tender search for AI agents. UK, EU and US procurement opportunities.
B2B, GovCon & LegalTech MCP server for live RFPs, contract parsing, compliance & proposal tools.
Open UK and EU public tenders (Find a Tender, TED) with go/no-go screening. Paid tier via L402.
Related MCP Servers
- AlicenseAqualityBmaintenanceUK due diligence MCP server — Companies House, corporate research, compliance checks18169 PyPI3MIT
- AlicenseNot gradedqualityAmaintenanceRead-only MCP server for searching Japanese government procurement bid notices (官公需) from the SME Agency's KKJ portal. Includes AI ranking, PDF requirement extraction, and CSV/calendar export.49 npmApache 2.0

oro-intel-mcpofficial
AlicenseNot gradedqualityDmaintenanceUK public procurement data for AI agents. Tenders, contracts, buyer and supplier profiles over MCP and REST. 250 free credits.MIT- AlicenseAqualityCmaintenanceEnables AI agents to find, score, and monitor government contract opportunities across UK, EU, and US with AI-powered relevance scoring.2103 npm1MIT