@cyanheads/uk-legislation-mcp-server
Search and read UK legislation at any date, resolve citations, list amendments, track changes via MCP. STDIO or Streamable HTTP.
6 Tools • 1 Resource
Overview
The UK statute book from legislation.gov.uk: primary, secondary, and EU-origin legislation for the UK, England, Scotland, Wales, and Northern Ireland. Resolve citations, search by text or title, read any provision as it stands today, as enacted, or on a past date, and track amendments. No API key required.
Tools
Resources
The skill is served over MCP through the Agent Skills extension (io.modelcontextprotocol/skills, skill://{+path} template) and ships in skills/ in the npm package, the Docker image, and the .mcpb bundle. The tools do not depend on it.
Capability reference
uklaw_search_legislation tool
text (full text: AND/OR, "quoted phrases", stemming) and/or title (every word must occur), or neither to list by type and year; limit 1–50 (default 20) with page
- Filters:
types (codes such as ukpga, uksi, eur, or the groups all, primary, secondary, eu-origin, draft; default all, which excludes drafts), year or year_from / year_to (1267–2100), extent (england, wales, scotland, ni) with extent_match (applicable or exact), and as_of (YYYY-MM-DD); extent and as_of cannot be combined
- Each result carries the
item path to pass to uklaw_get_document; has_more flags another page, and title searches and listings add facets (type counts and the newest 25 years)
uklaw_get_document tool
item is a full path (ukpga/2018/12, uksi/2019/419, eur/2016/679, regnal ukpga/Eliz2/3-4/19) or a legislation.gov.uk URI; provision a path (section/45/2/f, schedule/2/paragraph/3) or shorthand (s. 45(2)(f), Sch. 2 para. 3); version current (default), enacted (or made, adopted, created), or a YYYY-MM-DD date; language en or cy
kind is full (Markdown text with its annotations), outline (provision paths to read next, 100 per call from outline_offset), or pdf_only (links.pdf); text over 20,000 characters, or an item with more than 25 leaf provisions, comes back as an outline (a provision with no smaller provisions to list is returned whole up to 40,000 characters and cut past that, with a notice linking the full text), and match_text lists an item's provisions that contain a term
editorial (document_status, outstanding_effects, caveat) and unapplied_effects (the first 20, at item or provision level; a provision read also lists the effects on its enclosing provisions and, on full text, the provisions inside it, and says when it could not check them) show how far the revised text can be relied on; version.available lists the versions to pass as version
uklaw_get_amendments tool
item full or partial (uksi, ukpga/2018); direction affected (default: changes made to it) or affecting (changes it makes); filters counterpart (the other item, full or partial), status (all, unapplied, applied; default all), and provision (needs a full item; scans up to 1,500 effects per call)
limit 1–100 (default 20), continued with next_cursor; each effect names both sides with their provisions, in_force dates, applied / outstanding, and notes; total counts effects before the provision filter, and scan reports its coverage
- Pre-1963 Acts are queried by calendar year (
ukpga/1925/20) and drafts are not indexed: both fail as regnal_item / draft_item, with the route to take instead
uklaw_track_changes tool
start_date (required) and end_date (defaults to start_date), a window of at most 31 days; filters content_type (legislation, changes, draft, associated-documents), direction (with changes only), category (primary, secondary, eu-origin; with legislation or associated-documents only), item, new_only, and event (published, withdrawn)
limit 1–80 (default 40), continued with next_cursor; mode is day_walk (days newest first, up to 4 upstream requests per call) or item_log (a full item path reads that item's own log and reports read_back_to)
- A
changes event carries no effect detail: uklaw_get_amendments on its item has it
uklaw_lookup_citation tool
- One
citation of up to 300 characters: a numbered citation, a short title, or a legislation.gov.uk URI, optionally with a provision (forms below)
- Returns the canonical
item path, plus provision_found for a cited provision, checked against the current version; a miss or an ambiguous title is found: false with guidance or up to 20 candidates, not an error
Any form can end with a provision (s. 45(2)(f), section 45, reg. 5, art. 28(3), r. 7, r. 3.4, Sch. 2 para. 3, Pt 3) or start with one followed by "of" or "of the": section 45 of the Data Protection Act 2018. uklaw_list_reference topic citation_formats returns the same list.
uklaw_list_reference tool
topic: types, type_groups, extents, versions, document_status, annotation_types, effects, provision_paths, citation_formats, publication_log, coverage, or attribution
- Offline, with no request to legislation.gov.uk; each entry is a
key, label, description, and optional details
skill://uk-legislation-guide/SKILL.md resource
- Markdown with YAML frontmatter: scope, identifier sources, the gates for in-force status, revised-text lag, container effects, dated reads, and date semantics, and workflows for commencement, point-in-time text, amendment history, and changes since a date
- Listed in
resources/list; the skill://{+path} template reads any file under it
Features
Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.
legislation.gov.uk-specific:
- Keyless client for legislation.gov.uk's API: CLML XML for documents, Atom feeds for search, effects, and the Publication Log
- Follows legislation.gov.uk's fair use policy: an identifying User-Agent on every request, one process-wide queue that spaces request starts (1 second apart by default) and adopts a longer robots.txt crawl delay set for this server, up to 60 seconds, and at most 4 upstream requests per tool call within a 45-second deadline
- Process-wide response cache, with lifetimes taken from upstream
max-age (capped at one hour) and If-Modified-Since revalidation
- Citation shorthand (
s. 45(2)(f), reg. 5, Sch. 2 para. 3) normalized to provision paths; pre-1963 regnal paths and Welsh-language text (language: "cy") supported
- PDF-only items are linked, never fetched, as legislation.gov.uk's robots.txt requires
Agent-friendly output:
- Every document read returns its editorial status with the text (
editorial.document_status, caveat, outstanding_effects) and the unapplied_effects touching it, so the caller can tell when the revised text is behind on amendments
uklaw_lookup_citation returns a miss as found: false with guidance or candidates, not as an error
- Each tool's typed error reasons (
provision_not_found, version_not_found, regnal_item, …) carry a recovery hint naming the next call
- Every response that returns legislation includes
attribution, the licence lines its content needs (see License)
- Upstream text is treated as data: legislation text, annotations, and effect notes are blockquoted in
content[], inline values are escaped, and URIs are percent-encoded
Getting started
Connect to the hosted instance, no install:
Every caller of the hosted instance shares one request queue, paced at one legislation.gov.uk request per second under its fair use policy. For sustained use, run your own instance.
Or run it locally:
For other clients, add this to the MCP config file:
No API key or account is needed. The legislation.gov.uk fair use policy asks non-browser clients to identify themselves, so set UK_LEGISLATION_CONTACT to an email or URL when you run a shared deployment. For Docker or a source build, see Running the server.
Configuration
See .env.example for the full list of optional overrides.
Running the server
Local development
Requires Bun v1.4.0 or higher (or Node.js v24+).
Docker
The image defaults to HTTP transport, stateless session mode, and logs to /var/log/uk-legislation-mcp-server. To run it over stdio from an MCP client, use "command": "docker" with "args": ["run", "-i", "--rm", "-e", "MCP_TRANSPORT_TYPE=stdio", "ghcr.io/cyanheads/uk-legislation-mcp-server:latest"]. To build locally, docker build -t uk-legislation-mcp-server .; OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
Project structure
Development guide
See CLAUDE.md for development guidelines and architectural rules. The short version:
- Handlers throw, framework catches — no
try/catch in tool logic
- Use
ctx.log for logging and ctx.fail with a declared reason for expected failures
- Register new tools in
allToolDefinitions in src/mcp-server/tools/definitions/index.ts
- Wrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields
Contributing
Issues are welcome. Run checks and tests before submitting:
License
This project is licensed under the Apache 2.0 License. See the LICENSE file for details.
Legislation content from legislation.gov.uk is © Crown and database right, licensed under the Open Government Licence v3.0. EU-origin items also carry a European Union credit (© European Union, 1998-2020, re-used under Commission Decision 2011/833/EU), and pre-1987 statutory instruments contributed to legislation.gov.uk by Westlaw UK carry a Westlaw credit. Every tool that returns legislation lists the lines that apply to its content in attribution.