Agentic House Search

io.github.asturksever由 GitHub 帳號 asturksever 發布v0.1.3更新於 Oct 24, 2026

UK neighbourhood research from government open data: postcode reports, comparisons, 45 datasets.

發布方自己的服務:agentic.no

已驗證Streamable HTTP可網頁執行位置與生活資料與分析

概覽

AI 產生的概覽

把英國郵遞區號轉成社區報告、比較結果與資料集指引的 MCP 伺服器,資料來自英國政府開放資料。

可以做什麼
  • 查詢郵遞區號對應的地理資訊:座標、地方政府、選區、LSOA/MSOA 編碼、警政轄區與貧困排名
  • 為單一郵遞區號產生涵蓋十一類內容的社區報告,包括人口、犯罪、貧困、房價、寬頻、5G、噪音、交通、生活機能、學校與規劃限制,可依類別篩選
  • 在兩到五個郵遞區號之間依指定類別逐項比較,並附上可比性說明
  • 依文字或類別搜尋收錄 45 個英國開放資料集的精選目錄
  • 取得單一資料集的完整條目,含端點、API 文件、授權、涵蓋範圍與更新頻率
適用情境
適合在搬家、買房或租屋前調查英國某個地區,或需要助理提供有出處的社區事實而非籠統印象時使用。也適合找出哪個英國開放資料集或 API 能回答某個房產或社區問題。
執行需求
可連線託管的 streamable HTTP 端點(免帳號、免 API 金鑰),或以 Node 20+ 在本機執行 npm 套件。本機 HTTP 模式預設綁定 127.0.0.1;自行架設時可選用 AHS_BASE_URL、AHS_JS_ROOT、ALLOWED_ORIGINS、API_KEYS 及流量限制設定。需要連上上游政府資料來源的網路。
安裝前請注意
伺服器為唯讀且不保存使用者狀態,但請求會送往英國政府公開資料服務,所查詢的郵遞區號會離開本機。數據描述的是區域而非門牌地址,且涵蓋範圍因英國各構成國而異;貧困排名不可跨地區比較。它不是測量、估價或產權調查工具。自行架設的 HTTP 模式在未設定 API_KEYS 時對所有呼叫者開放。

安裝

在 SourceWeft 中

  1. 開啟 儀表板中的 Agentic House Search,將其新增到工作區。
  2. 為需要使用其工具的對話啟用該服務。

Web executable,透過 Streamable HTTP。 遠端服務在工作區中設定後即可從網頁執行環境執行。

交給代理程式安裝

把這段提示詞貼上到 Claude Code、Codex、Cursor 等代理程式,或 SourceWeft 對話中。代理程式會讀取該伺服器的安裝指南,先向你展示發布者、端點和登入方式,經你同意後再把它新增到你的客戶端。金鑰不會寫進任何命令。

閱讀 https://sourceweft.com/mcp/io.github.asturksever%2Fagentic-house-search/install.md,並按其中說明把這個 MCP 伺服器接入我的客戶端。修改任何設定之前,先告訴我它的發布者、端點和登入方式,等我確認。不要把 API 金鑰寫進命令或我會提交的檔案;問我金鑰應從哪裡取得。

檢視代理程式所依據的安裝指南

其他 MCP 客戶端

把它新增到你客戶端的 mcpServers 設定中。

{
  "mcpServers": {
    "agentic-house-search": {
      "type": "http",
      "url": "https://agentic-house-search.vercel.app/mcp"
    }
  }
}

README

agentic-house-search

An MCP server for UK neighbourhood research. Give it a postcode, get back what the government's own open data says about that place — demographics, crime, deprivation, prices, fibre, 5G, noise, transport, amenities, schools and planning constraints — plus a searchable registry of the 45 datasets underneath.

It is the postcode report with an agent-shaped front door. Both run the same provider modules, so a threshold or a caveat is written once and shows up in both.

Connect

Nothing to install, no account, no API key. Paste this URL wherever your client asks for a connector, custom integration or MCP server URL:

https://agentic-house-search.vercel.app/mcp

The connect page has a copy button, one-click buttons for Cursor and VS Code, and the same instructions per client.

Claude Code:

bash
claude mcp add --transport http agentic-house-search https://agentic-house-search.vercel.app/mcp

Anything that connects by editing JSON — Claude Desktop (claude_desktop_config.json), a project .mcp.json, and most others:

json
{  "mcpServers": {    "agentic-house-search": {      "type": "http",      "url": "https://agentic-house-search.vercel.app/mcp"    }  }}

GET /health says whether the endpoint is up, which is more useful than a client that only reports "connection failed".

Or find it by name

This server is listed in the official MCP registry, so a client with registry support can add it without being given a URL at all. Search for agentic-house-search, or use the canonical name:

io.github.asturksever/agentic-house-search

Anything resolving it programmatically can read the entry straight from the registry API — it carries both install paths, the hosted endpoint and the npm package, so a client can pick whichever it supports:

bash
curl -s "https://registry.modelcontextprotocol.io/v0/servers?search=agentic-house-search"

The listing's version tracks releases, so it is worth checking it against /health if a client reports something unexpected — a stale listing means the registry entry was not republished after a release, not that the server is wrong.

Or run it yourself

Free, ungated and with no dependency on the hosted deployment. Requires Node 20+.

bash
npx -y agentic-house-search              # stdionpx -y agentic-house-search --http       # streamable HTTP on 127.0.0.1:8848
json
{  "mcpServers": {    "agentic-house-search": {      "command": "npx",      "args": ["-y", "agentic-house-search"]    }  }}

Tools

ToolWhat it does
postcode_reportEleven categories for one postcode. Filter with categories to keep responses small.
postcode_lookupGeography only — coordinates, local authority, ward, constituency, LSOA/MSOA/OA codes, police force, deprivation rank. One fast call.
postcode_compareTwo to five postcodes side by side on chosen categories, with comparability caveats.
postcode_search_datasetsSearch the 45-dataset registry by text or category, paginated.
postcode_get_datasetOne registry entry in full: endpoint, API docs, licence, coverage, cadence.

Examples

"What's SW11 1AA like?"  → postcode_report(postcode="SW11 1AA")
"Which of these three has the best broadband and transport?"  → postcode_compare(postcodes=[...], categories=["broadband","transport"])
"Where would I get EPC data for a property?"  → postcode_search_datasets(query="EPC") → postcode_get_dataset(id="epc")

What the numbers mean

The point of this server is that every figure states what it actually describes. Agents summarising it should carry that through:

  • Geography varies by source. A census figure describes an LSOA — a neighbourhood of roughly 1,500 people, not an address. A crime count describes a 1 km square. Ofcom mobile coverage describes an entire local authority, because that is the finest grain Ofcom publishes; two postcodes in the same authority will always show identical mobile figures. Ofcom broadband is per postcode.
  • Coverage varies by UK nation, and is stated rather than hidden. Census tables are England & Wales; data.police.uk excludes Scotland; the Planning Data platform, Defra noise and the DfE school register are England-only. Those categories come back as out_of_coverage with the reason and a link to the devolved equivalent — never as a zero or an empty result.
  • Deprivation ranks are not comparable across nations. England, Wales, Scotland and Northern Ireland each rank their own areas against their own index over a different number of areas. The index and its size are always returned; postcode_compare refuses to let a cross-nation comparison pass without a caveat.
  • Police data depends on each force submitting. A very low count in a built-up area is more likely a gap than a quiet street, and the report says so when the count is implausibly low.
  • unavailable means not built yet, not "none" — currently the Defra noise extract, which needs a polygon join that has not been run.

This is not a survey, a valuation or a conveyancing search.

Configuration

VariableDefaultPurpose
AHS_BASE_URLthe published siteWhere to read the registry and pack extracts. Point it at http://localhost:8000/ to develop against a local checkout.
AHS_JS_ROOTunsetWhere the shared js/ provider modules live. A hint, not a requirement: with it unset the server checks next to the compiled output (the published package) and then ./js (a bundled function), and fails with the list of directories it tried. Only set it when neither is right.
ALLOWED_ORIGINSnoneComma-separated Origin allowlist for HTTP mode. Requests carrying any other Origin are rejected with 403.
API_KEYSunsetHTTP mode only. Comma-separated key or key:pro. Unset means every caller is anonymous and nothing is rejected.
RATE_LIMIT_ANONYMOUS60/hourHTTP mode only. A courtesy limit so one runaway agent cannot burn the upstream fair-use budgets.
RATE_LIMIT_PRO1000/hourHTTP mode only.

HTTP mode binds to 127.0.0.1 by default and is stateless: a fresh server per request, so it scales horizontally with no session affinity.

Running it yourself is free and ungated, and stays that way. stdio has no limits at all, and --http with no API_KEYS set is open. The rate limiting exists so that a shared deployment is a good neighbour to the government APIs underneath, not to nudge you toward a paid tier. There isn't one. See COMMERCIAL.md for where that boundary sits and what would have to be true before any of it were sold.

The hosted endpoint

https://agentic-house-search.vercel.app/mcp is this same package, built from this repository, deployed as a serverless function (api/mcp.mjs, vercel.json) on the same host as the website, which scripts/stage-site.mjs assembles into public/ at build time. It exists so that connecting takes a URL rather than a config file. It is unauthenticated because there is nothing to authenticate: every source is public open data and the server holds no per-user state.

Both HTTP hosts share src/http.ts, so the hosted endpoint and your own --http cannot drift apart in how they speak the protocol.

Deploying it

This repository is the deployment. Vercel builds from GitHub: connect the repo once, and every push to main redeploys the endpoint. There is no CLI step, no separate copy of the source and nothing to remember to run — the same push that updates the website updates the MCP server, and a revert reverts both.

Setup is once, in Vercel's Add New → Project → Import Git Repository. Two things matter:

  • Name the project agentic-house-search. vercel.json carries every other setting, but not the project name, and the project name is what the URL is made of. Any other name and the documented URL is a lie — change it in connect.html, server.json, both READMEs and index.html, or alias a domain onto it.
  • Leave the framework preset on "Other." The build command and output are already in vercel.json; a preset would override them.

The build runs npm ci && npm run build in mcp/, and AHS_JS_ROOT=js tells the bundled function where the provider modules landed. .vercelignore keeps the website's own files out of the upload, since Pages serves those and / here redirects there.

npm run smoke:http drives the same entrypoint locally and runs in CI on every push, so a deployment that would break should go red in Actions first.

server.json is the entry for the official MCP registry, which is how a client can offer this server by name rather than by URL. Publish it with the registry's own CLI (brew install mcp-publisher), from the repository root:

bash
mcp-publisher login githubmcp-publisher publish

Publish to npm first. The registry proves you own the package you point it at by reading mcpName out of the published npm package and comparing it with server.json#name — so it validates what npm already has, not what is in this repo. A version listed in server.json that npm has never seen fails, and because npm will not accept the same version twice, the fix is another bump. npm run check:versions compares both fields locally and runs in CI.

Development

bash
npm installnpm run build      # tsc, then copy ../js into dist/jsnpm run smoke      # drives the built server over stdio and checks every toolnpm run smoke:http # drives the serverless entrypoint the hosted endpoint usesnpm run inspect    # MCP Inspector

npm run build copies the repo's js/ provider modules into dist/js. That copy is deliberate: the alternative is reimplementing eleven providers, their thresholds and their coverage gates in TypeScript, which is exactly how the website and the server would start disagreeing about the same postcode.

evaluation.xml holds ten verified questions for testing whether a model can actually use these tools. Every answer comes from fixed geography, a dated statistical release or the registry — never a live figure that moves monthly.

Licence and attribution

This server is CC0. The data is not: it is public sector information under the Open Government Licence v3.0, plus OS and Royal Mail rights in the postcode geography, and OpenStreetMap contributors (ODbL) for amenities. Every response carries the attribution — please keep it attached.

來源:mcp/README.md,提交 6884ed6

工具

5

postcode_report

UK postcode neighbourhood report

Full neighbourhood report for one UK postcode, assembled live from UK government open data. Covers eleven categories: demographics (Census 2021), crime (data.police.uk), deprivation (IMD/WIMD/SIMD/NIMDM), property prices (HM Land Registry), broadband and 5G (Ofcom), noise (Defra), transport, amenities (OpenStreetMap), schools (DfE register: name, phase and distance only, no Ofsted grades) and planning constraints (Planning Data platform, Environment Agency). Every figure carries the geography it describes (a postcode, an LSOA of ~1,500 people, or a whole local authority), the period it covers, and a benchmark where one exists. Read those: a crime count describes a 1 km square, and Ofcom mobile coverage describes an entire local authority, not the street. Args: - postcode (string): UK postcode, spaces optional - categories (string[], optional): subset to fetch; omit for all eleven - include_sources (boolean): append publisher and licence per category (default false) - response_format ('markdown' | 'json'): default 'markdown' Returns: Per category: a status, a one-paragraph summary, the facts (label, value, band, benchmark, geography, period, source id) and any caveats. Statuses that are normal rather than failures: - "out_of_coverage": the dataset genuinely does not cover this nation. Census tables are England & Wales; police.uk excludes Scotland; Planning Data, Defra noise and the DfE school register are England-only. The reason and the devolved equivalent are given. - "unavailable": a pre-built extract has not been generated for this area yet (noise, currently). - "partial": some sources answered and some did not; check notes. Examples: - "What's SW11 1AA like?" -> postcode="SW11 1AA" - "Is the broadband any good at M1 1AE?" -> postcode="M1 1AE", categories=["broadband","mobile"] - "Crime and schools near LA23 1AA" -> postcode="LA23 1AA", categories=["crime","schools"] Errors: - "No such postcode" with suggestions when the postcode

輸入參數postcode必填categoriesinclude_sourcesresponse_format

postcode_lookup

Look up UK postcode geography

Resolve a UK postcode to its geography — coordinates, local authority, ward, constituency, LSOA/MSOA/output area, police force, rural-urban class and deprivation rank. One fast call with no downstream data fetching. Use it to check a postcode exists, to get the codes needed for other datasets, or when you only need where somewhere is rather than what it is like. Args: - postcode (string): UK postcode, spaces optional - response_format ('markdown' | 'json'): default 'markdown' Returns: Coordinates, administrative geography, statistical geography codes (LSOA/MSOA/OA — these are the keys most UK open datasets are published against), and the deprivation rank with the index it came from. Examples: - "Where is SW11 1AA?" -> postcode="SW11 1AA" - "What LSOA covers M1 1AE?" -> postcode="M1 1AE" - "Is XY1 2AB a real postcode?" -> postcode="XY1 2AB" (returns an error with suggestions) Don't use when: you want data about the area — use postcode_report instead. Note: deprivation ranks are NOT comparable between UK nations. Each nation ranks its own areas against its own index, over a different number of areas; the index and its size are returned so you do not compare them by mistake.

輸入參數postcode必填response_format

postcode_compare

Compare UK postcodes side by side

Compare two to five UK postcodes on chosen categories, aligned measure by measure. Fetches each postcode's report concurrently and lines the facts up in a table, so you can answer "which of these is better connected / quieter / cheaper" in one call instead of several. Args: - postcodes (string[]): 2-5 UK postcodes - categories (string[]): 1-6 of demographics, crime, deprivation, prices, broadband, mobile, noise, transport, amenities, schools, environment - response_format ('markdown' | 'json'): default 'markdown' Returns: One row per measure with a column per postcode, each cell carrying the value, its band, and the category status for that postcode. Caveats collect anything that makes a row not strictly comparable. Comparability warnings you must respect, and which this tool surfaces: - Deprivation ranks from different UK nations are NOT comparable — different indices over different numbers of areas. - A measure missing for one postcode because the dataset does not cover that nation is not a low score; the cell says "out_of_coverage". - Ofcom mobile figures describe a whole local authority, so two postcodes in the same authority will always be identical. - Crime counts describe a 1 km square and depend on each police force submitting data; a very low count can be a gap rather than a quiet street. Examples: - "Which has better broadband, SW11 1AA or M1 1AE?" -> postcodes=[...], categories=["broadband"] - "Compare these three on crime and schools" -> categories=["crime","schools"] Don't use when: you have one postcode (use postcode_report) or want the underlying datasets (use postcode_search_datasets).

輸入參數postcodes必填categories必填response_format

postcode_search_datasets

Search the UK open-data registry

Search a curated registry of 45 UK open datasets and APIs for property and neighbourhood research. Each entry records the dataset's home page, its machine-readable endpoint, format, licence, geographic coverage, update cadence, and the concrete questions it can answer. Use it to find the right source for something this server does not report directly — EPC ratings, planning applications, flood risk, council tax bands, bus timetables, air quality, ground stability, land ownership. Args: - query (string, optional): free text over name, publisher, category, endpoint and questions - category (string, optional): category prefix, e.g. "Crime", "Transport", "Environment" - limit (number): 1-45, default 10 - offset (number): pagination offset, default 0 - response_format ('markdown' | 'json'): default 'markdown' Returns: { total, count, offset, has_more, next_offset, datasets: [{ id, dataset, publisher, category, api, licence, coverage, update_frequency }] } Examples: - "Where do I get EPC data?" -> query="EPC" - "What flood datasets are there?" -> query="flood" - "List every transport source" -> category="Transport", limit=20 Follow up with postcode_get_dataset for the full entry including API docs and the questions it answers.

輸入參數limitqueryoffsetcategoryresponse_format

postcode_get_dataset

Get one registry dataset entry

Full registry entry for one dataset, by id. Returns everything needed to call the source yourself: its home page, machine-readable endpoint, API documentation, format, licence, geographic coverage, update cadence, and the concrete questions it can answer. Args: - id (string): registry id, e.g. "police-street-crime", "land-registry-ppd", "ea-flood" - response_format ('markdown' | 'json'): default 'markdown' Examples: - "How do I call the police API?" -> id="police-street-crime" - "What licence is Price Paid under?" -> id="land-registry-ppd" Errors: - Returns the closest matching ids when the id is not found.

輸入參數id必填response_format

版本歷史

1
  1. v0.1.3最新Sep 16, 2026

評分

已滿足適用檢查項的 90%

該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。

  • 近 30 天內可連通必需25 分
  • 已宣告認證方式必需10 分
  • 已列出工具必需15 分
  • 描述必需15 分
  • 圖示10 分
  • 文件15 分
  • 授權條款10 分

    請在儲存庫或註冊中心條目中宣告授權條款。

其他 Agentic 整合