Skip to main content
Glama
README.md
# UK Postcode Intel

An MCP server that returns structured area information for a UK postcode from official open government data.

The headline tool, `full_area_intelligence`, fetches several sources in parallel and returns one JSON report. Six cheaper tools expose the same sources individually, or as a lighter bundle.

## Hosted endpoint

- MCP (Streamable HTTP): <https://uk-postcode-intel.mcpize.run/mcp>
- Public listing: <https://mcpize.com/mcp/uk-postcode-intel>

The hosted endpoint charges per tool call in USDC on Base, using the [x402](https://www.x402.org/) protocol. Payment goes to `0xd9784f8122af988E51b3183F725b0b53BCb8278A`. The asset is USD Coin on Base (`0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913`). No account or API key is required. An unpaid `tools/call` returns HTTP 402 with the payment requirement.

## Tools and prices

| Tool | Price per call | Description |
|---|---|---|
| `full_area_intelligence` | $0.15 | Complete area report: summary, location, deprivation, Census 2021 demographics, crime, flood, house prices (postcode and neighbours), food hygiene, plus source status and attribution. |
| `area_report` | $0.05 | Lighter bundle: location, crime, flood, nearby food hygiene, and Land Registry sales at the postcode. |
| `house_prices` | $0.02 | Recorded residential sale prices at the postcode (England and Wales), with median, min and max. |
| `postcode_lookup` | $0.01 | Coordinates, council, ward, constituency, region, and LSOA/MSOA codes via postcodes.io. |
| `crime_summary` | $0.01 | Latest month of street crime within about one mile, by category, with top streets and outcomes. |
| `flood_warnings` | $0.01 | Live Environment Agency flood alerts or warnings and nearby river gauges (England). |
| `food_hygiene_nearby` | $0.01 | Nearest food businesses with Food Standards Agency hygiene ratings, plus the rating distribution. |

Prices are in US dollars, charged as USDC. On the wire, `maxAmountRequired` is in 6-decimal USDC units: `150000` ($0.15), `50000` ($0.05), `20000` ($0.02) and `10000` ($0.01).

`full_area_intelligence` includes a plain-English `summary`; location (coordinates, ward, council, constituency, region, LSOA/MSOA, rural-urban class); deprivation (England: IoD 2025 IMD and domain deciles; other UK nations: a national rank from the ONS Postcode Directory where published); Census 2021 demographics for the neighbourhood compared with the council and the nation (England and Wales); street crime; live flood alerts (England); HM Land Registry sold prices at the postcode and neighbouring postcodes within about 400 m, including a 5-year median and median by property type; and nearby FSA ratings. Sources are fetched in parallel with a timeout. If one source is down or out of coverage, it is recorded under `sources_status` and the rest of the report is still returned.

### Coverage

| Source | Coverage |
|---|---|
| Location (postcodes.io / ONSPD) | United Kingdom |
| IoD 2025 IMD and domain deciles | England (bundled MHCLG extract) |
| National deprivation rank from ONSPD | Wales, Scotland, Northern Ireland (where published) |
| Census 2021 demographics | England and Wales |
| Street crime (data.police.uk) | England, Wales and Northern Ireland |
| Live flood alerts and gauges | England |
| Land Registry Price Paid | England and Wales |
| FSA food hygiene ratings | Requested for any UK postcode |

Some police forces do not currently publish street-level data to data.police.uk (the code notes Greater Manchester Police as an example). A zero crime count does not mean the area is crime-free.

## How to call the hosted server

### MCP client

Point an MCP client that supports Streamable HTTP at the hosted endpoint:

```json
{
  "mcpServers": {
    "uk-postcode-intel": {
      "type": "http",
      "url": "https://uk-postcode-intel.mcpize.run/mcp"
    }
  }
}
```

For Cline, use `"type": "streamableHttp"` and follow [llms-install.md](llms-install.md).

An x402-capable client will settle the 402 payment requirement and retry the tool call. A client that does not handle x402 can still complete the initialize handshake and list tools; unpaid tool calls will fail with HTTP 402.

### Raw HTTP

Send `Content-Type: application/json` and `Accept: application/json, text/event-stream`. The gateway may respond with Server-Sent Events. Capture the `mcp-session-id` response header from `initialize` and send it on later requests.

```bash
ENDPOINT=https://uk-postcode-intel.mcpize.run/mcp

# 1. Initialize and read mcp-session-id
curl -sS -D /tmp/pci-headers.txt \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":0,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"demo","version":"1"}}}' \
  "$ENDPOINT"

SID=$(awk -F': ' 'tolower($1)=="mcp-session-id"{print $2}' /tmp/pci-headers.txt | tr -d '\r')

# 2. notifications/initialized
curl -sS \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "mcp-session-id: $SID" \
  -d '{"jsonrpc":"2.0","method":"notifications/initialized"}' \
  "$ENDPOINT"

# 3. Unpaid tools/call — expect HTTP 402
curl -sS -D - \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -H "mcp-session-id: $SID" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"postcode_lookup","arguments":{"postcode":"SW1A 1AA"}}}' \
  "$ENDPOINT"
```

A 402 response includes an `accepts` entry with `maxAmountRequired` (6-decimal USDC units), `payTo` (`0xd9784f8122af988E51b3183F725b0b53BCb8278A`), `asset` (Base USDC `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913`) and `network` (`base`).

`scripts/verify_402.py` runs this check against all seven tools on the live gateway.

## Run locally

Requires [uv](https://docs.astral.sh/uv/) and Python 3.11+ (`.python-version` pins 3.13).

```bash
git clone https://github.com/halfabillion/uk-postcode-intel
cd uk-postcode-intel
uv sync
uv run uk-postcode-intel
```

The server listens on `http://localhost:8080` (override with `PORT`). Health check: `http://localhost:8080/health`. MCP: `http://localhost:8080/mcp`. Optional environment variables are listed in `.env.example`.

A local process does not apply x402 charges; those are enforced by the hosted gateway. Official upstream APIs are called at request time and may rate-limit or be unavailable.

`Makefile` targets: `make dev`, `make install`, `make run`, `make test`, `make lint`, `make format`, `make clean`.

## Tests

Default tests are offline. They cover postcode normalisation, registration of all seven tools, the bundled IoD 2025 deprivation lookup, census-response shaping, summary text, and graceful degradation when upstream sources fail. They do not call live APIs.

```bash
uv sync
uv run pytest
```

Live tests hit the upstream APIs and are skipped unless `LIVE=1` is set:

```bash
LIVE=1 uv run pytest
```

## Licence

This software is released under the MIT Licence, Copyright (c) 2026 Ali Ghaedi. See [LICENSE](LICENSE).

Data returned by the tools, and the bundled IoD 2025 extract, are not covered by the MIT licence. See [DATA_LICENSES.md](DATA_LICENSES.md) for sources, attributions and third-party terms (including OS, Royal Mail, ONS, MHCLG, data.police.uk, Environment Agency, the Food Standards Agency and HM Land Registry).