uk-legislation-mcp-server

v0.1.1 pre-1.0

Search and read UK legislation at any date, resolve citations, list amendments, track changes via MCP. STDIO or Streamable HTTP.

uk-legislation.caseyjhand.com/mcp
claude mcp add --transport http uk-legislation-mcp-server https://uk-legislation.caseyjhand.com/mcp
codex mcp add uk-legislation-mcp-server --url https://uk-legislation.caseyjhand.com/mcp
{
  "mcpServers": {
    "uk-legislation-mcp-server": {
      "url": "https://uk-legislation.caseyjhand.com/mcp"
    }
  }
}
gemini mcp add --transport http uk-legislation-mcp-server https://uk-legislation.caseyjhand.com/mcp
{
  "mcpServers": {
    "uk-legislation-mcp-server": {
      "command": "bunx",
      "args": [
        "mcp-remote",
        "https://uk-legislation.caseyjhand.com/mcp"
      ]
    }
  }
}
{
  "mcpServers": {
    "uk-legislation-mcp-server": {
      "type": "http",
      "url": "https://uk-legislation.caseyjhand.com/mcp"
    }
  }
}
curl -X POST https://uk-legislation.caseyjhand.com/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"curl","version":"1.0.0"}}}'

Tools

6

uklaw_search_legislation

open-world

Search the UK statute book on legislation.gov.uk by full text or title, or list legislation by type and year, filtered by geographical extent and point in time. Full-text search ranks by relevance; title searches and type/year listings run newest year first and carry type and year counts (facets) to narrow with. Each result gives the item path to pass to uklaw_get_document. For a known citation or short title, uklaw_lookup_citation is cheaper and exact.

read
scope read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "uklaw_search_legislation",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "text": {
      "description": "Full-text query. Supports AND/OR, \"quoted phrases\", and stemming. Omit for a title search or a listing.",
      "type": "string",
      "maxLength": 500
    },
    "title": {
      "description": "Words that must all occur in the title. For a known short title or citation, uklaw_lookup_citation is exact.",
      "type": "string",
      "maxLength": 300
    },
    "types": {
      "default": [
        "all"
      ],
      "description": "Type codes (ukpga, uksi, asp, eur, …) and/or groups (all, primary, secondary, eu-origin, draft). \"all\" covers UK and EU-origin legislation, excluding drafts, and absorbs any other value. uklaw_list_reference topic types lists the codes.",
      "maxItems": 39,
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "all",
          "primary",
          "secondary",
          "eu-origin",
          "draft",
          "ukpga",
          "ukla",
          "ukppa",
          "asp",
          "asc",
          "anaw",
          "mwa",
          "ukcm",
          "nia",
          "nisi",
          "apni",
          "mnia",
          "aosp",
          "aep",
          "aip",
          "apgb",
          "gbla",
          "gbppa",
          "uksi",
          "wsi",
          "ssi",
          "nisr",
          "ukci",
          "ukmd",
          "ukmo",
          "uksro",
          "nisro",
          "eur",
          "eudn",
          "eudr",
          "eut",
          "ukdsi",
          "sdsi",
          "nidsr"
        ]
      }
    },
    "year": {
      "description": "Calendar year (also for pre-1963 Acts numbered by regnal year). Not combinable with year_from/year_to.",
      "type": "integer",
      "minimum": 1267,
      "maximum": 2100
    },
    "year_from": {
      "description": "Earliest calendar year of a range; the other bound may be omitted.",
      "type": "integer",
      "minimum": 1267,
      "maximum": 2100
    },
    "year_to": {
      "description": "Latest calendar year of a range; the other bound may be omitted.",
      "type": "integer",
      "minimum": 1267,
      "maximum": 2100
    },
    "extent": {
      "description": "Geographical extent: england, wales, scotland, ni. An item matches when one of its provisions extends there. Cannot combine with as_of. legislation.gov.uk has not recorded provision-level extent for many recent items, so an empty result does not prove nothing extends there.",
      "maxItems": 4,
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "england",
          "wales",
          "scotland",
          "ni"
        ]
      }
    },
    "extent_match": {
      "description": "Used only with extent. applicable: a provision extends to any given extent; exact: a provision extends to exactly that set.",
      "default": "applicable",
      "type": "string",
      "enum": [
        "applicable",
        "exact"
      ]
    },
    "as_of": {
      "description": "Point in time YYYY-MM-DD: only legislation as it stood on that date (items not yet enacted or made are excluded). Omit for current law. Cannot combine with extent.",
      "type": "string",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
    },
    "limit": {
      "default": 20,
      "description": "Results per page (1–50).",
      "type": "integer",
      "minimum": 1,
      "maximum": 50
    },
    "page": {
      "default": 1,
      "description": "Page number (1–10,000).",
      "type": "integer",
      "minimum": 1,
      "maximum": 10000
    }
  },
  "required": [
    "types",
    "extent_match",
    "limit",
    "page"
  ],
  "additionalProperties": false
}
view source ↗

uklaw_get_document

open-world

Read one item or one provision of UK legislation from legislation.gov.uk — as it stands now (revised), as enacted/made, or as it stood on a date — in Markdown, with its editorial status, annotations (the applied amendment history), the unapplied effects touching it, the versions available, and attribution. Provision-level reads are the main path; an item-level read returns the whole text only for small items and otherwise an outline of provision paths to read next. With match_text (item level), returns the provisions whose text matches. Revised text is an editorial consolidation that can lag: read editorial.caveat and unapplied_effects before relying on it, and use uklaw_get_amendments for every recorded effect on an item, applied or not.

read
scope read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "uklaw_get_document",
    "arguments": {
      "item": "<item>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "item": {
      "type": "string",
      "minLength": 1,
      "maxLength": 500,
      "pattern": "^[^\\s/]*(?:\\/[^\\s/]*){2,}$",
      "description": "Item path {type}/{year}/{number} — ukpga/2018/12, uksi/2019/419, eur/2016/679, ukpga/Eliz2/3-4/19 — or any legislation.gov.uk URI (a URI carrying a provision, version, or /welsh is split into those parts; a version or /welsh in the URI applies unless the version or language input is set). Get it from uklaw_lookup_citation or uklaw_search_legislation."
    },
    "provision": {
      "description": "Provision path — section/45/2/f, regulation/5, article/28/3, schedule/2/paragraph/3, part/3/chapter/2, introduction — or citation shorthand (s. 45(2)(f), reg. 5, art. 28(3), Sch. 2 para. 3), normalized before the request. Omit to read the item; an item-level outline lists the paths.",
      "type": "string",
      "maxLength": 200,
      "pattern": "^[A-Za-z0-9.()/\\s-]+$"
    },
    "version": {
      "description": "current (the latest revised text, or the original text for an item never revised), enacted (made, adopted and created are synonyms — the original text), or a date YYYY-MM-DD for the text as it stood then. Omitted: the version in an item URI, else current. A future date returns the latest version, and a date on or after the made or enactment date of an item never revised returns its original text, with a notice; version.applied reports the version served.",
      "type": "string",
      "pattern": "^(current|enacted|made|adopted|created|\\d{4}-\\d{2}-\\d{2})$"
    },
    "language": {
      "description": "en, or cy for the Welsh text of Welsh legislation (asc, anaw, mwa, wsi). Omitted: cy when an item URI ends in /welsh, else en. English is returned, with a notice, when no Welsh text exists.",
      "type": "string",
      "enum": [
        "en",
        "cy"
      ]
    },
    "match_text": {
      "description": "Item level only (omit provision): return the outline of provisions whose text contains this term, e.g. \"processor\" — 100 entries per call; outline_offset reaches the rest.",
      "type": "string",
      "maxLength": 200
    },
    "outline_offset": {
      "default": 0,
      "description": "Where a returned outline starts: 0 lists entries 1–100, 100 the next 100. Applies only when kind is outline (ignored when text is returned); a notice names the next offset while entries remain.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    }
  },
  "required": [
    "item",
    "outline_offset"
  ],
  "additionalProperties": false
}
view source ↗

uklaw_get_amendments

open-world

List the effects — amendments, repeals, revocations, commencements, modifications — recorded against an item (direction affected) or made by an item (direction affecting), from legislation.gov.uk's changes feeds. Filter by the other item (counterpart), by applied status (unapplied = the outstanding work on the revised text), and by provision. item may be partial (ukpga/2018 = all effects on 2018 Acts). Each effect names both sides with provision links, in-force dates, and why it is not applied. For the applied history of one provision in prose, read its annotations with uklaw_get_document.

read
scope read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "uklaw_get_amendments",
    "arguments": {
      "item": "<item>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "item": {
      "type": "string",
      "minLength": 1,
      "maxLength": 500,
      "pattern": "^\\S+$",
      "description": "Item path or legislation.gov.uk URI (ukpga/2018/12), or a partial path: a type (uksi) or type and year (ukpga/2018). Get a full path from uklaw_lookup_citation or uklaw_search_legislation. A pre-1963 Act takes its calendar year (ukpga/1925/20, not ukpga/Geo5/15-16/20); its effects name the regnal path, and two sessions in one year can share a number. Drafts (ukdsi, sdsi, nidsr) are not in the changes feeds."
    },
    "direction": {
      "description": "affected: changes made to item. affecting: changes item makes to other legislation.",
      "default": "affected",
      "type": "string",
      "enum": [
        "affected",
        "affecting"
      ]
    },
    "counterpart": {
      "description": "Restrict to effects involving this other item (full or partial item path, without a provision, e.g. uksi/2019/419 or uksi/2026) — the amending item for direction affected, the amended item for affecting. A pre-1963 Act takes its calendar year, not its regnal path; drafts are not in the changes feeds.",
      "type": "string",
      "minLength": 1,
      "maxLength": 500,
      "pattern": "^\\S+$"
    },
    "status": {
      "description": "unapplied: effects not yet applied to the revised text; applied: already applied; all: both.",
      "default": "all",
      "type": "string",
      "enum": [
        "all",
        "unapplied",
        "applied"
      ]
    },
    "provision": {
      "description": "Keep only effects touching this provision of item (path or shorthand, e.g. section/45 or s. 45), including effects on the whole item. Needs a full item path. legislation.gov.uk cannot filter by provision, so each call scans up to 1,500 effects; continue with next_cursor.",
      "type": "string",
      "maxLength": 200,
      "pattern": "^[A-Za-z0-9.()/\\s-]+$"
    },
    "limit": {
      "default": 20,
      "description": "Effects per page, or with provision the most matches returned (1–100, default 20).",
      "type": "integer",
      "minimum": 1,
      "maximum": 100
    },
    "cursor": {
      "description": "next_cursor from the previous call, passed with the other inputs unchanged; omit for the first page.",
      "type": "string",
      "maxLength": 500,
      "pattern": "^[A-Za-z0-9_-]+$"
    }
  },
  "required": [
    "item",
    "direction",
    "status",
    "limit"
  ],
  "additionalProperties": false
}
view source ↗

uklaw_track_changes

open-world

Read the legislation.gov.uk Publication Log for a date window of up to 31 days: new items, new revised versions, newly recorded effects, and withdrawals, newest first — the compliance-monitoring view of "what changed". Filter by content type, effect direction, category, an item or type/year, first-time items only, or event. With a full item path it reads that item's own log, usually in one call; otherwise it walks the window day by day, newest first, so a broad window may need several calls. A changes event carries no effect detail — uklaw_get_amendments with that item has it. Continue with next_cursor.

read
scope read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "uklaw_track_changes",
    "arguments": {
      "start_date": "<start_date>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "start_date": {
      "type": "string",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$",
      "description": "First event date of the window, YYYY-MM-DD (UK local time)."
    },
    "end_date": {
      "description": "Last event date, YYYY-MM-DD; defaults to start_date. The window is at most 31 days.",
      "type": "string",
      "pattern": "^\\d{4}-\\d{2}-\\d{2}$"
    },
    "content_type": {
      "description": "legislation (documents published), changes (effects recorded), draft, or associated-documents. Omit for all.",
      "type": "string",
      "enum": [
        "legislation",
        "changes",
        "draft",
        "associated-documents"
      ]
    },
    "direction": {
      "description": "With content_type changes only: effects recorded against (affected) or made by (affecting) the item.",
      "type": "string",
      "enum": [
        "affected",
        "affecting"
      ]
    },
    "category": {
      "description": "Item category: primary, secondary, or eu-origin. With content_type legislation or associated-documents only.",
      "type": "string",
      "enum": [
        "primary",
        "secondary",
        "eu-origin"
      ]
    },
    "item": {
      "description": "A full item path (ukpga/2018/12) or legislation.gov.uk URI reads that item's own log; a type (uksi) or type and year (uksi/2026) narrows the day walk. Get a full path from uklaw_lookup_citation or uklaw_search_legislation.",
      "type": "string",
      "minLength": 1,
      "maxLength": 500,
      "pattern": "^\\S+$"
    },
    "new_only": {
      "default": false,
      "description": "true: only events for items appearing on legislation.gov.uk for the first time.",
      "type": "boolean"
    },
    "event": {
      "description": "Only published or only withdrawn events. Omit for both.",
      "type": "string",
      "enum": [
        "published",
        "withdrawn"
      ]
    },
    "limit": {
      "default": 40,
      "description": "Most events returned by this call (1–80).",
      "type": "integer",
      "minimum": 1,
      "maximum": 80
    },
    "cursor": {
      "description": "next_cursor from the previous call, passed with the other inputs unchanged; omit to start from end_date.",
      "type": "string",
      "maxLength": 500,
      "pattern": "^[A-Za-z0-9_-]+$"
    }
  },
  "required": [
    "start_date",
    "new_only",
    "limit"
  ],
  "additionalProperties": false
}
view source ↗

uklaw_lookup_citation

open-world

Resolve a citation or short title to the canonical legislation.gov.uk item and provision: "Data Protection Act 2018 s. 45", "2018 c. 12", "S.I. 2019/419", "S.S.I. 2020/123", "S.R. 2020/12", "2020 asp 13", "Regulation (EU) 2016/679 art. 28", a legislation.gov.uk URI, or a short title. Returns the item path to pass to uklaw_get_document, and when a provision is given, whether it exists in the current version. A miss or an ambiguous title is a result with found false plus guidance or candidates, not an error. To find legislation by topic or by partial title words rather than a known citation, use uklaw_search_legislation.

read
scope read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "uklaw_lookup_citation",
    "arguments": {
      "citation": "<citation>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "citation": {
      "type": "string",
      "minLength": 1,
      "maxLength": 300,
      "description": "A citation (\"2018 c. 12\", \"S.I. 2019/419 reg. 5\", \"Regulation (EU) 2016/679 art. 28\"), a short title (\"Data Protection Act 2018 s. 45(2)(f)\"), or a legislation.gov.uk URI. uklaw_list_reference topic citation_formats lists the accepted forms."
    }
  },
  "required": [
    "citation"
  ],
  "additionalProperties": false
}
view source ↗

uklaw_list_reference

Decode the vocabulary the other uklaw_* tools take and return: legislation type codes (ukpga, uksi, eur, …) with their labels, categories and enacted keywords; type groups; extents; version keywords; document status; annotation letters (F, C, I, M, E, P, X); effect record fields; provision path forms and shorthand; accepted citation formats; Publication Log vocabulary and read modes; data coverage; and the attribution lines. Offline — no request to legislation.gov.uk.

read
scope read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "uklaw_list_reference",
    "arguments": {
      "topic": "<topic>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "topic": {
      "type": "string",
      "enum": [
        "types",
        "type_groups",
        "extents",
        "versions",
        "document_status",
        "annotation_types",
        "effects",
        "provision_paths",
        "citation_formats",
        "publication_log",
        "coverage",
        "attribution"
      ],
      "description": "Which table to return: types, type_groups, extents, versions, document_status, annotation_types, effects, provision_paths, citation_formats, publication_log, coverage, or attribution."
    }
  },
  "required": [
    "topic"
  ],
  "additionalProperties": false
}
view source ↗