
Uk Police Crime Mcp Server
io.github.cyanheadsv0.1.1Updated Oct 1, 2026
Search UK street crime, outcomes, stop and search, and neighbourhood teams (Scotland: BTP only).
Overview
Lets an assistant search UK street-level crime, police outcomes, stop and search records, and neighbourhood policing teams from data.police.uk.
- What it does
- Provides six tools over the open data.police.uk dataset: list reference data (forces, categories, published months, neighbourhood ids), search street-level crimes in a month by point, polygon, location, neighbourhood or whole force, search police outcomes, fetch the full outcome history of up to 25 crimes by persistent id, search stop and search records with up to eight filters, and find the force and neighbourhood team for a place. Results include counts, category and outcome breakdowns, paging, and typed failure reasons. Coverage is England, Wales, Northern Ireland and British Transport Police; Scotland only via BTP station records.
- When to use it
- Useful when an assistant needs to answer questions about recorded crime, police outcomes, stop and search, or local policing teams in England, Wales or Northern Ireland, or to cross-tabulate stop and search records by ethnicity, outcome, legislation or other fields. It fits research, journalism, civic and neighbourhood-level analysis rather than real-time incident or emergency information.
- Requirements
- Runs locally as a stdio process (or a local Streamable HTTP server) via npm package @cyanheads/uk-police-crime-mcp-server with Bun v1.4.0+ or Node.js v24+, or Docker. No API key is required. Network access to data.police.uk is needed. Optional environment variables include MCP_AUTH_MODE, MCP_HTTP_HOST, MCP_HTTP_PORT, MCP_HTTP_ENDPOINT_PATH and MCP_LOG_LEVEL.
Installation
In SourceWeft
- Open Uk Police Crime Mcp Server in the dashboard and add it to a workspace.
- Enable the server for the chats that should use its tools.
Desktop only via STDIO. STDIO servers start a local process, so they need the SourceWeft desktop host.
Other MCP clients
Follow the launch instructions in the repository.
README
@cyanheads/uk-police-crime-mcp-server
Search UK street-level crime, police outcomes, stop and search, and neighbourhood teams from data.police.uk: England, Wales and Northern Ireland forces, plus British Transport Police (Scotland's only coverage), via MCP. STDIO or Streamable HTTP.
Overview
Monthly street-level crime, police outcomes, and stop and search records from data.police.uk, plus the neighbourhood policing teams behind them. Coverage is the 43 territorial forces of England and Wales and the Police Service of Northern Ireland, plus British Transport Police, whose station records are the only coverage of Scotland. Search by point, polygon, map point, neighbourhood, or whole force; follow a crime's outcome history; find who polices a place. Runs as a stdio process or a local Streamable HTTP server. No API key required.
Tools
Capability reference
ukcrime_list_reference tool
topic:forces,categories,availability, orneighbourhoods(needsforce);name_containsfilters forces and neighbourhoods by name, andmonthnarrowsavailabilityto one rowavailabilityreturnslatest_month,earliest_month, and which forces published stop and search each month; withforce, the months that force did and did not publishforcesadds British Transport Police (btp) and each force's known coveragegaps; errors are typed (force_required,unknown_force,invalid_filter)
ukcrime_search_crimes tool
area:point(lat,lng; a 1-mile radius),polygon(3–2,500 vertices),location(location_id),neighbourhood(force+neighbourhood_id), orforce_unplaced(force: the crimes it could not place); optionalmonth(default: latest published) andcategory(default: every category)- Returns
total,by_category,by_outcome, up to 10top_locations, and a page ofcrimes, each with thepersistent_idthatukcrime_get_crime_outcomestakes;limitdefaults to 25 (max 200), andnext_offsetcontinues - Failures carry a typed
reason, such asmonth_not_published,unknown_category, orarea_too_large
ukcrime_search_outcomes tool
- Same areas as
ukcrime_search_crimesexceptforce_unplaced;monthis when the outcome was recorded, andcategorycounts only outcomes for crimes in that category - Returns
total,unfiltered_total,by_outcome(code, name, count),by_crime_month, and a page ofoutcomes, each with its crime;limitdefaults to 20 (max 200) - Police outcomes only: court results are not published, and the result says when a force publishes no outcomes
ukcrime_get_crime_outcomes tool
persistent_ids: 1–25 64-character ids fromukcrime_search_crimesorukcrime_search_outcomes; anti-social behaviour records carry none- Each crime comes back with every outcome, oldest first;
history_available: falsemarks a crime with no published history - Ids data.police.uk does not hold land in
not_found, failed lookups infailed, so one bad id never fails the batch
ukcrime_search_stops tool
area:point,polygon,location,neighbourhood, orforce(every stop the force published, placed or not); up to 8filtersontype,self_defined_ethnicity,officer_defined_ethnicity,outcome,object_of_search,legislation,age_range, orgender- Returns
total,unfiltered_total,unplaced,force_published, a breakdown per filterable field, and a page ofstops;limitdefaults to 15 (max 200) - Filters narrow the breakdowns and the page together, so filtering one field and reading another's breakdown is a cross-tab
ukcrime_find_neighbourhood tool
- Look up by
lat+lngor byforce+neighbourhood_id;includepickspriorities,team,events(the default three) andboundary - Returns the force, the team's description, contact channels and stations, current priorities, up to 10 upcoming events (
events_totalcounts all), and the boundary as a polygon string the search tools accept - Team entries carry only each officer's rank and name, as forces publish them; biographies and personal contact details are dropped by design. A point outside coverage returns
found: falsewithguidance
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.
data.police.uk-specific:
- Every location is an anonymised map point covering at least eight addresses, never the place a crime or stop happened; outputs label it that way
- Validates locally what the upstream would silently widen: unknown categories, months outside the window, misspelled force ids, and area fields the chosen area does not use
- Omitting
monthsearches the latest published month and echoes it; coverage gaps per force are dated and named in each result'snotice - One process-wide request pacer under data.police.uk's rate limit, with retries and in-process caches for reference data and area responses
Agent-friendly output:
- Every response carries the Open Government Licence attribution and a
data_noteon what the records can and cannot say - Counts come with the page: totals and breakdowns cover every matched record, while
limit/offset/next_offsetpage the rows - Typed failure reasons with a recovery hint, and a
noticethat separates "no data published" from "nothing happened"
Known limitations
- Only the latest 36 months are served; longer trends need the bulk archive at data.police.uk, which this server does not read
- Greater Manchester Police publishes no crime, outcome or stop and search data; searches there return only other forces' or British Transport Police records
- Northern Ireland has no outcomes and no stop and search, and every crime other than anti-social behaviour carries the placeholder outcome
Under investigation - Scotland is covered only by British Transport Police station records
- Court outcomes from June 2019 onward are not published
- data.police.uk can refuse an area holding more than about 10,000 records, whatever the category, and the point radius is fixed at one mile; dense city centres need polygons smaller than a borough
- The API says which forces published stop and search each month, but not which supplied crime data, so a force that skipped a month shows as a thin or empty area; a low or zero count can mean missing data
- Many stops carry a blank outcome, reported as
(not recorded); stopdatetimeis UTC while months follow UK local time
Getting started
Add the following to your MCP client configuration file.
Or with npx (no Bun required):
Or with Docker:
For Streamable HTTP, set the transport and start the server:
Prerequisites
- Bun v1.4.0 or higher (or Node.js v24+).
- No API key: data.police.uk is open and keyless.
Installation
- Clone the repository:
- Navigate into the directory:
- Install dependencies:
Configuration
The server reads no environment variables of its own. data.police.uk allows 15 requests a second with a burst of 30 per client IP; the server paces every request process-wide under that limit, so a hosted deployment shares one budget behind its egress IP, and requests queue for their turn.
See .env.example for the common framework overrides.
Running the server
Local development
-
Build and run the production version:
-
Run checks and tests:
Project structure
Development guide
See CLAUDE.md for development guidelines and architectural rules. The short version:
- Handlers throw, framework catches — no
try/catchin tool logic - Use
ctx.logfor logging,ctx.statefor storage - Register new tools and resources in the
createApp()arrays insrc/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.
Data: Contains public sector information licensed under the Open Government Licence v3.0. Source: data.police.uk. Every tool response carries this attribution; storing, caching and redistributing the data are permitted with it. This project is independent of the Home Office, data.police.uk and the police forces.
Source: README.md at commit 6e42476
Tools
0Version history
1- v0.1.1LatestOct 1, 2026


