homedata-mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,14 @@
1
+ # Changelog
2
+
3
+ All notable changes to the Node.js edition of the Homedata MCP server.
4
+
5
+ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
+
7
+ ## [0.1.0] - 2026-05-11
8
+
9
+ ### Added
10
+ - Initial release of the Node.js / TypeScript edition.
11
+ - Feature-parity with `homedata-mcp` 0.2.0 on PyPI: same 15 working tools plus the `lookup_council_tax` stub, same env-var auth (`HOMEDATA_API_KEY`), same base URL.
12
+ - Ships both `homedata-mcp` (stdio MCP server) and `homedata` (CLI) binaries from a single package.
13
+ - Built on the official `@modelcontextprotocol/sdk`; communicates over stdio with any MCP-compatible client (Claude Desktop, Claude Code, Cursor, Codex, Cline, Continue.dev, Windsurf, Zed).
14
+ - TypeScript source with full `.d.ts` types — package can be imported as a library too: `import { HomedataClient, tools } from "homedata-mcp"`.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Homedata Ltd
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,111 @@
1
+ # Homedata MCP — Node.js / npm
2
+
3
+ The official Homedata MCP server and CLI for the [Model Context Protocol](https://modelcontextprotocol.io). Brings 29M UK addresses with EPC, sale history, planning applications, flood risk, comparables, demographics, crime, schools, broadband and transport into any MCP-compatible AI tool — Claude Desktop, Claude Code, Cursor, Codex, Cline, Continue.dev, Windsurf, Zed and more.
4
+
5
+ Behaviour is identical to the [Python edition (`homedata-mcp`)](https://pypi.org/project/homedata-mcp/) — same tools, same data, same env-var auth. Pick the one that matches your stack.
6
+
7
+ > Data sourced from Home.co.uk's 30-year panel of partners, the Environment Agency, ONS Census 2021, the Valuation Office Agency, Ofcom, Ofsted, data.police.uk and HM Land Registry.
8
+
9
+ ---
10
+
11
+ ## Install
12
+
13
+ ```bash
14
+ npm install -g homedata-mcp
15
+ ```
16
+
17
+ Or run on demand with `npx`:
18
+
19
+ ```bash
20
+ npx homedata-mcp # starts the MCP server (stdio)
21
+ npx homedata --help # CLI
22
+ ```
23
+
24
+ Get a free Homedata API key at [homedata.co.uk/developer](https://homedata.co.uk/developer) — no card required to start.
25
+
26
+ ```bash
27
+ export HOMEDATA_API_KEY=hd_live_xxx
28
+ ```
29
+
30
+ ---
31
+
32
+ ## Wire it into Claude Desktop
33
+
34
+ Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
35
+
36
+ ```json
37
+ {
38
+ "mcpServers": {
39
+ "homedata": {
40
+ "command": "npx",
41
+ "args": ["-y", "homedata-mcp"],
42
+ "env": {
43
+ "HOMEDATA_API_KEY": "your_api_key_here"
44
+ }
45
+ }
46
+ }
47
+ }
48
+ ```
49
+
50
+ Restart Claude Desktop and ask "what's the EPC rating for UPRN 100021421083?". Same pattern works for Cursor, Codex, Cline, Continue.dev, Windsurf, and Zed — see [homedata.co.uk/mcp](https://homedata.co.uk/mcp) for per-client guides.
51
+
52
+ ---
53
+
54
+ ## CLI
55
+
56
+ The package also installs a `homedata` command for shell use, scripting, and CI:
57
+
58
+ ```bash
59
+ homedata property 100021421083
60
+ homedata epc 100021421083 --field current_energy_efficiency
61
+ homedata search "10 downing street" --postcode SW1A2AA
62
+ homedata flood 100021421083 --compact
63
+ homedata batch 100021421083 100022121211
64
+ ```
65
+
66
+ Pass `--field <dotted.path>` to extract a single value (good for shell pipelines) and `--compact` for single-line JSON.
67
+
68
+ ---
69
+
70
+ ## Tools
71
+
72
+ | Tool | Description |
73
+ |---|---|
74
+ | `lookup_property(uprn)` | Property attributes + EPC summary + last sold price |
75
+ | `lookup_epc(uprn)` | Full Energy Performance Certificate |
76
+ | `lookup_flood_risk(uprn)` | Flood risk assessment |
77
+ | `get_property_sales(uprn)` | Historical sales (HMLR) |
78
+ | `search_property_listings(uprn)` | Past + current listing events |
79
+ | `get_comparables(uprn, count?)` | Nearest N comparable properties |
80
+ | `get_planning_applications(uprn)` | Planning applications near a UPRN |
81
+ | `get_schools(uprn, radius_m?)` | Schools near a UPRN |
82
+ | `get_transport(uprn, radius_m?)` | Transport options near a UPRN |
83
+ | `get_crime(postcode, date?)` | Recorded crime in the postcode |
84
+ | `get_demographics(postcode)` | ONS Census 2021 profile |
85
+ | `get_broadband(postcode)` | Ofcom broadband availability |
86
+ | `get_postcode_profile(postcode)` | Aggregated postcode profile |
87
+ | `search_address(query, postcode?)` | Free-text address search |
88
+ | `batch_property_lookup(uprns)` | Batch lookup (max 50) |
89
+ | `lookup_council_tax(uprn)` | _In development — currently returns a 503 stub_ |
90
+
91
+ ---
92
+
93
+ ## Privacy
94
+
95
+ The MCP server runs locally on your machine. Your queries go directly from your machine to `api.homedata.co.uk` — your AI vendor never sees the property data.
96
+
97
+ ---
98
+
99
+ ## Links
100
+
101
+ * Homedata: <https://homedata.co.uk>
102
+ * Pricing: <https://homedata.co.uk/pricing>
103
+ * Developer dashboard: <https://homedata.co.uk/developer>
104
+ * Python edition: <https://pypi.org/project/homedata-mcp/>
105
+ * Issues: <https://github.com/wehomemove/homedata-mcp-node/issues>
106
+
107
+ ---
108
+
109
+ ## License
110
+
111
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * homedata — command line interface mirroring the Python CLI.
4
+ *
5
+ * Same data as the MCP server but for human shells, scripting, and CI.
6
+ * Usage:
7
+ * homedata property 100021421083
8
+ * homedata epc 100021421083 --field current_energy_efficiency
9
+ * homedata search "10 downing street" --postcode SW1A2AA
10
+ * homedata batch 100021421083 100022121211
11
+ */
12
+ export {};
13
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;;;;;;;GASG"}
package/dist/cli.js ADDED
@@ -0,0 +1,171 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * homedata — command line interface mirroring the Python CLI.
4
+ *
5
+ * Same data as the MCP server but for human shells, scripting, and CI.
6
+ * Usage:
7
+ * homedata property 100021421083
8
+ * homedata epc 100021421083 --field current_energy_efficiency
9
+ * homedata search "10 downing street" --postcode SW1A2AA
10
+ * homedata batch 100021421083 100022121211
11
+ */
12
+ import { HomedataClient, HomedataError } from "./client.js";
13
+ import * as t from "./tools.js";
14
+ import { VERSION } from "./index.js";
15
+ function parseArgv(argv) {
16
+ const out = { positional: [], flags: {} };
17
+ for (let i = 0; i < argv.length; i++) {
18
+ const a = argv[i];
19
+ if (a.startsWith("--")) {
20
+ const key = a.slice(2);
21
+ const next = argv[i + 1];
22
+ if (next === undefined || next.startsWith("--")) {
23
+ out.flags[key] = true;
24
+ }
25
+ else {
26
+ out.flags[key] = next;
27
+ i++;
28
+ }
29
+ }
30
+ else if (!out.command) {
31
+ out.command = a;
32
+ }
33
+ else {
34
+ out.positional.push(a);
35
+ }
36
+ }
37
+ return out;
38
+ }
39
+ function printHelp() {
40
+ console.log(`homedata ${VERSION} — UK property data CLI
41
+
42
+ Usage: homedata <command> [args] [--field PATH] [--compact]
43
+
44
+ Commands:
45
+ property <uprn> Look up a property by UPRN.
46
+ epc <uprn> Get EPC for a UPRN.
47
+ flood <uprn> Get flood risk for a UPRN.
48
+ sales <uprn> Historical sales (HMLR).
49
+ listings <uprn> Past + current listings.
50
+ comparables <uprn> [--count N] Nearest N comparables (default 20).
51
+ planning <uprn> Planning applications near a UPRN.
52
+ schools <uprn> [--radius N] Schools near a UPRN (default 1000m).
53
+ transport <uprn> [--radius N] Transport near a UPRN (default 800m).
54
+ crime <postcode> [--date YYYY-MM] Recorded crime in a postcode.
55
+ demographics <postcode> ONS Census 2021 profile.
56
+ broadband <postcode> Ofcom broadband availability.
57
+ postcode <postcode> Aggregated postcode profile.
58
+ search <query> [--postcode PC] Free-text address search.
59
+ batch <uprn> <uprn> ... Batch property lookup (max 50).
60
+
61
+ Flags:
62
+ --field <dotted.path> Extract a single value from the response (e.g. last_sold_price).
63
+ --compact Single-line JSON output (good for jq, pipes).
64
+ --version Show version.
65
+ --help Show this help.
66
+
67
+ Set HOMEDATA_API_KEY in your environment. Get a free key at https://homedata.co.uk/developer.`);
68
+ }
69
+ function format(data, compact, field) {
70
+ if (field) {
71
+ let cursor = data;
72
+ for (const part of field.split(".")) {
73
+ if (cursor && typeof cursor === "object" && part in cursor) {
74
+ cursor = cursor[part];
75
+ }
76
+ else {
77
+ return "";
78
+ }
79
+ }
80
+ if (cursor && typeof cursor === "object")
81
+ return JSON.stringify(cursor, null, compact ? 0 : 2);
82
+ return String(cursor);
83
+ }
84
+ return JSON.stringify(data, null, compact ? 0 : 2);
85
+ }
86
+ async function run(args) {
87
+ if (args.flags["help"] || args.flags["h"] || !args.command) {
88
+ printHelp();
89
+ return 0;
90
+ }
91
+ if (args.flags["version"] || args.flags["v"]) {
92
+ console.log(`homedata ${VERSION}`);
93
+ return 0;
94
+ }
95
+ let client;
96
+ try {
97
+ client = HomedataClient.fromEnv(VERSION);
98
+ }
99
+ catch (err) {
100
+ if (err instanceof HomedataError) {
101
+ console.error(`error: ${err.message}`);
102
+ return 2;
103
+ }
104
+ throw err;
105
+ }
106
+ const p = args.positional;
107
+ let data;
108
+ switch (args.command) {
109
+ case "property":
110
+ data = await t.lookup_property(client, p[0]);
111
+ break;
112
+ case "epc":
113
+ data = await t.lookup_epc(client, p[0]);
114
+ break;
115
+ case "flood":
116
+ data = await t.lookup_flood_risk(client, p[0]);
117
+ break;
118
+ case "sales":
119
+ data = await t.get_property_sales(client, p[0]);
120
+ break;
121
+ case "listings":
122
+ data = await t.search_property_listings(client, p[0]);
123
+ break;
124
+ case "planning":
125
+ data = await t.get_planning_applications(client, p[0]);
126
+ break;
127
+ case "comparables":
128
+ data = await t.get_comparables(client, p[0], Number(args.flags["count"] ?? 20));
129
+ break;
130
+ case "schools":
131
+ data = await t.get_schools(client, p[0], Number(args.flags["radius"] ?? 1000));
132
+ break;
133
+ case "transport":
134
+ data = await t.get_transport(client, p[0], Number(args.flags["radius"] ?? 800));
135
+ break;
136
+ case "crime":
137
+ data = await t.get_crime(client, p[0], args.flags["date"]);
138
+ break;
139
+ case "demographics":
140
+ data = await t.get_demographics(client, p[0]);
141
+ break;
142
+ case "broadband":
143
+ data = await t.get_broadband(client, p[0]);
144
+ break;
145
+ case "postcode":
146
+ data = await t.get_postcode_profile(client, p[0]);
147
+ break;
148
+ case "search":
149
+ data = await t.search_address(client, p[0], args.flags["postcode"]);
150
+ break;
151
+ case "batch":
152
+ data = await t.batch_property_lookup(client, p);
153
+ break;
154
+ default:
155
+ console.error(`unknown command: ${args.command}`);
156
+ printHelp();
157
+ return 2;
158
+ }
159
+ console.log(format(data, args.flags["compact"] === true, args.flags["field"]));
160
+ if (data && typeof data === "object" && "error" in data) {
161
+ return 1;
162
+ }
163
+ return 0;
164
+ }
165
+ run(parseArgv(process.argv.slice(2)))
166
+ .then((code) => process.exit(code))
167
+ .catch((err) => {
168
+ console.error("[homedata] fatal:", err);
169
+ process.exit(1);
170
+ });
171
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Thin HTTP client for the Homedata API (Loki).
3
+ * Mirrors the Python implementation 1:1 so both packages have identical behaviour.
4
+ */
5
+ export declare class HomedataError extends Error {
6
+ }
7
+ export interface HomedataResponse {
8
+ [key: string]: unknown;
9
+ }
10
+ export declare class HomedataClient {
11
+ private readonly apiKey;
12
+ private readonly baseUrl;
13
+ private readonly timeoutMs;
14
+ private readonly userAgent;
15
+ constructor(opts: {
16
+ apiKey: string;
17
+ baseUrl?: string;
18
+ timeoutMs?: number;
19
+ version?: string;
20
+ });
21
+ static fromEnv(version?: string): HomedataClient;
22
+ get(path: string, params?: Record<string, string | number | undefined>): Promise<HomedataResponse>;
23
+ post(path: string, body: unknown): Promise<HomedataResponse>;
24
+ private _request;
25
+ }
26
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,qBAAa,aAAc,SAAQ,KAAK;CAAG;AAE3C,MAAM,WAAW,gBAAgB;IAE/B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAEvB,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE;IAY5F,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,cAAc;IAM1C,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAYlG,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,gBAAgB,CAAC;YAIpD,QAAQ;CAyCvB"}
package/dist/client.js ADDED
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Thin HTTP client for the Homedata API (Loki).
3
+ * Mirrors the Python implementation 1:1 so both packages have identical behaviour.
4
+ */
5
+ const DEFAULT_BASE_URL = "https://api.homedata.co.uk";
6
+ const DEFAULT_TIMEOUT_MS = 10_000;
7
+ export class HomedataError extends Error {
8
+ }
9
+ export class HomedataClient {
10
+ apiKey;
11
+ baseUrl;
12
+ timeoutMs;
13
+ userAgent;
14
+ constructor(opts) {
15
+ if (!opts.apiKey) {
16
+ throw new HomedataError("HOMEDATA_API_KEY is required. Get a key at https://homedata.co.uk/developer");
17
+ }
18
+ this.apiKey = opts.apiKey;
19
+ this.baseUrl = (opts.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, "");
20
+ this.timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
21
+ this.userAgent = `homedata-mcp-node/${opts.version ?? "0.1.0"}`;
22
+ }
23
+ static fromEnv(version) {
24
+ const apiKey = (process.env.HOMEDATA_API_KEY ?? "").trim();
25
+ const baseUrl = (process.env.HOMEDATA_BASE_URL ?? "").trim() || undefined;
26
+ return new HomedataClient({ apiKey, baseUrl, version });
27
+ }
28
+ async get(path, params) {
29
+ const url = new URL(this.baseUrl + path);
30
+ if (params) {
31
+ for (const [k, v] of Object.entries(params)) {
32
+ if (v !== undefined && v !== null) {
33
+ url.searchParams.set(k, String(v));
34
+ }
35
+ }
36
+ }
37
+ return this._request("GET", url.toString());
38
+ }
39
+ async post(path, body) {
40
+ return this._request("POST", this.baseUrl + path, body);
41
+ }
42
+ async _request(method, url, body) {
43
+ const controller = new AbortController();
44
+ const timer = setTimeout(() => controller.abort(), this.timeoutMs);
45
+ try {
46
+ const resp = await fetch(url, {
47
+ method,
48
+ headers: {
49
+ Authorization: `Api-Key ${this.apiKey}`,
50
+ Accept: "application/json",
51
+ "User-Agent": this.userAgent,
52
+ ...(body ? { "Content-Type": "application/json" } : {}),
53
+ },
54
+ body: body ? JSON.stringify(body) : undefined,
55
+ signal: controller.signal,
56
+ });
57
+ let parsed;
58
+ try {
59
+ parsed = await resp.json();
60
+ }
61
+ catch {
62
+ parsed = await resp.text().catch(() => "");
63
+ }
64
+ if (!resp.ok) {
65
+ return { error: "api_error", status_code: resp.status, detail: parsed };
66
+ }
67
+ if (typeof parsed === "object" && parsed !== null && !Array.isArray(parsed)) {
68
+ return parsed;
69
+ }
70
+ return { data: parsed };
71
+ }
72
+ catch (err) {
73
+ if (err.name === "AbortError") {
74
+ return {
75
+ error: "timeout",
76
+ status_code: 504,
77
+ detail: `Homedata API did not respond within ${this.timeoutMs}ms`,
78
+ };
79
+ }
80
+ return { error: "network_error", status_code: 0, detail: String(err) };
81
+ }
82
+ finally {
83
+ clearTimeout(timer);
84
+ }
85
+ }
86
+ }
87
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Public API of the package — re-exports the client and tool functions
3
+ * so users can `import { HomedataClient, lookup_property } from "homedata-mcp"`
4
+ * if they want to integrate the data layer directly into their own code.
5
+ */
6
+ export { HomedataClient, HomedataError } from "./client.js";
7
+ export type { HomedataResponse } from "./client.js";
8
+ export * as tools from "./tools.js";
9
+ export declare const VERSION = "0.1.0";
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5D,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,KAAK,KAAK,MAAM,YAAY,CAAC;AAEpC,eAAO,MAAM,OAAO,UAAU,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Public API of the package — re-exports the client and tool functions
3
+ * so users can `import { HomedataClient, lookup_property } from "homedata-mcp"`
4
+ * if they want to integrate the data layer directly into their own code.
5
+ */
6
+ export { HomedataClient, HomedataError } from "./client.js";
7
+ export * as tools from "./tools.js";
8
+ export const VERSION = "0.1.0";
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5D,OAAO,KAAK,KAAK,MAAM,YAAY,CAAC;AAEpC,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC"}
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * MCP server entry point.
4
+ *
5
+ * Wires the Homedata tools into the official @modelcontextprotocol/sdk
6
+ * server, communicates over stdio with the host AI client (Claude Desktop,
7
+ * Cursor, Codex, Cline, Continue.dev, Windsurf, Zed, etc.).
8
+ *
9
+ * Auth: reads HOMEDATA_API_KEY from the environment. The MCP runs locally
10
+ * on the user's machine — their property-data queries never go through
11
+ * the AI vendor.
12
+ */
13
+ export {};
14
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";AACA;;;;;;;;;;GAUG"}
package/dist/server.js ADDED
@@ -0,0 +1,143 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * MCP server entry point.
4
+ *
5
+ * Wires the Homedata tools into the official @modelcontextprotocol/sdk
6
+ * server, communicates over stdio with the host AI client (Claude Desktop,
7
+ * Cursor, Codex, Cline, Continue.dev, Windsurf, Zed, etc.).
8
+ *
9
+ * Auth: reads HOMEDATA_API_KEY from the environment. The MCP runs locally
10
+ * on the user's machine — their property-data queries never go through
11
+ * the AI vendor.
12
+ */
13
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
14
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
15
+ import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
16
+ import { z } from "zod";
17
+ import { HomedataClient, HomedataError } from "./client.js";
18
+ import * as t from "./tools.js";
19
+ import { VERSION } from "./index.js";
20
+ const uprnSchema = z.object({ uprn: z.string().describe("UPRN (Unique Property Reference Number)") });
21
+ const postcodeSchema = z.object({ postcode: z.string().describe("UK postcode, e.g. 'SW1A 2AA'") });
22
+ const uprnRadiusSchema = z.object({
23
+ uprn: z.string(),
24
+ radius_m: z.number().int().min(100).max(10_000).optional(),
25
+ });
26
+ const comparablesSchema = z.object({
27
+ uprn: z.string(),
28
+ count: z.number().int().min(1).max(200).default(20),
29
+ });
30
+ const crimeSchema = z.object({
31
+ postcode: z.string(),
32
+ date: z.string().optional().describe("Optional YYYY-MM month filter."),
33
+ });
34
+ const searchSchema = z.object({
35
+ query: z.string().describe("Address fragment, e.g. '10 downing street'"),
36
+ postcode: z.string().optional(),
37
+ });
38
+ const batchSchema = z.object({
39
+ uprns: z.array(z.string()).min(1).max(50),
40
+ });
41
+ const TOOL_DEFS = [
42
+ { name: "lookup_property", description: "Look up a UK property by UPRN. Returns property type, EPC summary, last sold price, and core attributes.", schema: uprnSchema },
43
+ { name: "lookup_epc", description: "Get the Energy Performance Certificate for a UPRN — current and potential ratings, floor area, fuel type.", schema: uprnSchema },
44
+ { name: "lookup_flood_risk", description: "Get flood risk assessment for a UPRN.", schema: uprnSchema },
45
+ { name: "get_property_sales", description: "Historical sales for a UPRN (HM Land Registry).", schema: uprnSchema },
46
+ { name: "search_property_listings", description: "Past and current listings (sales and rentals) for a UPRN.", schema: uprnSchema },
47
+ { name: "get_comparables", description: "The N nearest comparable properties to a UPRN by geographic proximity.", schema: comparablesSchema },
48
+ { name: "get_planning_applications", description: "Planning applications near a UPRN.", schema: uprnSchema },
49
+ { name: "get_schools", description: "Schools near a UPRN within the given radius.", schema: uprnRadiusSchema },
50
+ { name: "get_transport", description: "Transport (rail, tube, bus) near a UPRN.", schema: uprnRadiusSchema },
51
+ { name: "get_crime", description: "Recorded crime in the area of the given postcode.", schema: crimeSchema },
52
+ { name: "get_demographics", description: "ONS Census 2021 demographic profile for the given postcode.", schema: postcodeSchema },
53
+ { name: "get_broadband", description: "Ofcom broadband availability for the given postcode.", schema: postcodeSchema },
54
+ { name: "get_postcode_profile", description: "Aggregated profile for a postcode — demographics, broadband, schools, transport, crime.", schema: postcodeSchema },
55
+ { name: "search_address", description: "Search for an address by free text.", schema: searchSchema },
56
+ { name: "batch_property_lookup", description: "Look up multiple UPRNs in one request (max 50).", schema: batchSchema },
57
+ { name: "lookup_council_tax", description: "Council tax band for a UPRN (in development — currently returns a 503 stub).", schema: uprnSchema },
58
+ ];
59
+ async function main() {
60
+ let client;
61
+ try {
62
+ client = HomedataClient.fromEnv(VERSION);
63
+ }
64
+ catch (err) {
65
+ if (err instanceof HomedataError) {
66
+ console.error(err.message);
67
+ process.exit(1);
68
+ }
69
+ throw err;
70
+ }
71
+ const server = new Server({ name: "homedata", version: VERSION }, { capabilities: { tools: {} } });
72
+ server.setRequestHandler(ListToolsRequestSchema, async () => ({
73
+ tools: TOOL_DEFS.map((t) => ({
74
+ name: t.name,
75
+ description: t.description,
76
+ inputSchema: zodToJsonSchema(t.schema),
77
+ })),
78
+ }));
79
+ server.setRequestHandler(CallToolRequestSchema, async (req) => {
80
+ const args = req.params.arguments ?? {};
81
+ const result = await dispatch(req.params.name, args, client);
82
+ return {
83
+ content: [{ type: "text", text: JSON.stringify(result) }],
84
+ };
85
+ });
86
+ const transport = new StdioServerTransport();
87
+ await server.connect(transport);
88
+ }
89
+ async function dispatch(name, args, c) {
90
+ switch (name) {
91
+ case "lookup_property": return t.lookup_property(c, String(args.uprn));
92
+ case "lookup_epc": return t.lookup_epc(c, String(args.uprn));
93
+ case "lookup_flood_risk": return t.lookup_flood_risk(c, String(args.uprn));
94
+ case "get_property_sales": return t.get_property_sales(c, String(args.uprn));
95
+ case "search_property_listings": return t.search_property_listings(c, String(args.uprn));
96
+ case "get_comparables": return t.get_comparables(c, String(args.uprn), Number(args.count ?? 20));
97
+ case "get_planning_applications": return t.get_planning_applications(c, String(args.uprn));
98
+ case "get_schools": return t.get_schools(c, String(args.uprn), Number(args.radius_m ?? 1000));
99
+ case "get_transport": return t.get_transport(c, String(args.uprn), Number(args.radius_m ?? 800));
100
+ case "get_crime": return t.get_crime(c, String(args.postcode), args.date ? String(args.date) : undefined);
101
+ case "get_demographics": return t.get_demographics(c, String(args.postcode));
102
+ case "get_broadband": return t.get_broadband(c, String(args.postcode));
103
+ case "get_postcode_profile": return t.get_postcode_profile(c, String(args.postcode));
104
+ case "search_address": return t.search_address(c, String(args.query), args.postcode ? String(args.postcode) : undefined);
105
+ case "batch_property_lookup": return t.batch_property_lookup(c, args.uprns ?? []);
106
+ case "lookup_council_tax": return t.lookup_council_tax(c, String(args.uprn));
107
+ default: return { error: "unknown_tool", detail: name };
108
+ }
109
+ }
110
+ // Minimal Zod → JSON Schema converter — sufficient for our flat objects.
111
+ // We could pull in zod-to-json-schema if our shapes get more complex.
112
+ function zodToJsonSchema(s) {
113
+ if (s instanceof z.ZodObject) {
114
+ const properties = {};
115
+ const required = [];
116
+ for (const [key, value] of Object.entries(s.shape)) {
117
+ properties[key] = zodLeaf(value);
118
+ if (!(value instanceof z.ZodOptional) && !(value instanceof z.ZodDefault)) {
119
+ required.push(key);
120
+ }
121
+ }
122
+ return { type: "object", properties, ...(required.length ? { required } : {}) };
123
+ }
124
+ return zodLeaf(s);
125
+ }
126
+ function zodLeaf(s) {
127
+ const desc = s.description;
128
+ const meta = desc ? { description: desc } : {};
129
+ if (s instanceof z.ZodOptional || s instanceof z.ZodDefault)
130
+ return zodLeaf(s._def.innerType);
131
+ if (s instanceof z.ZodString)
132
+ return { type: "string", ...meta };
133
+ if (s instanceof z.ZodNumber)
134
+ return { type: "number", ...meta };
135
+ if (s instanceof z.ZodArray)
136
+ return { type: "array", items: zodLeaf(s.element), ...meta };
137
+ return meta;
138
+ }
139
+ main().catch((err) => {
140
+ console.error("[homedata-mcp] fatal:", err);
141
+ process.exit(1);
142
+ });
143
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Tool implementations shared by the MCP server and the CLI.
3
+ * Each function takes a HomedataClient and the relevant inputs, returns a
4
+ * structured response. No MCP-specific dependencies — both surfaces import these.
5
+ */
6
+ import type { HomedataClient, HomedataResponse } from "./client.js";
7
+ export declare const lookup_property: (c: HomedataClient, uprn: string) => Promise<HomedataResponse>;
8
+ export declare const lookup_epc: (c: HomedataClient, uprn: string) => Promise<HomedataResponse>;
9
+ export declare const lookup_flood_risk: (c: HomedataClient, uprn: string) => Promise<HomedataResponse>;
10
+ export declare const get_property_sales: (c: HomedataClient, uprn: string) => Promise<HomedataResponse>;
11
+ export declare const search_property_listings: (c: HomedataClient, uprn: string) => Promise<HomedataResponse>;
12
+ export declare const get_comparables: (c: HomedataClient, uprn: string, count?: number) => Promise<HomedataResponse>;
13
+ export declare const get_planning_applications: (c: HomedataClient, uprn: string) => Promise<HomedataResponse>;
14
+ export declare const get_schools: (c: HomedataClient, uprn: string, radius_m?: number) => Promise<HomedataResponse>;
15
+ export declare const get_transport: (c: HomedataClient, uprn: string, radius_m?: number) => Promise<HomedataResponse>;
16
+ export declare const get_crime: (c: HomedataClient, postcode: string, date?: string) => Promise<HomedataResponse>;
17
+ export declare const get_demographics: (c: HomedataClient, postcode: string) => Promise<HomedataResponse>;
18
+ export declare const get_broadband: (c: HomedataClient, postcode: string) => Promise<HomedataResponse>;
19
+ export declare const get_postcode_profile: (c: HomedataClient, postcode: string) => Promise<HomedataResponse>;
20
+ export declare const search_address: (c: HomedataClient, query: string, postcode?: string) => Promise<HomedataResponse>;
21
+ export declare const batch_property_lookup: (c: HomedataClient, uprns: string[]) => Promise<HomedataResponse>;
22
+ export declare const lookup_council_tax: (_c: HomedataClient, _uprn: string) => Promise<HomedataResponse>;
23
+ //# sourceMappingURL=tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEpE,eAAO,MAAM,eAAe,GAAI,GAAG,cAAc,EAAE,MAAM,MAAM,8BACR,CAAC;AAExD,eAAO,MAAM,UAAU,GAAI,GAAG,cAAc,EAAE,MAAM,MAAM,8BACF,CAAC;AAEzD,eAAO,MAAM,iBAAiB,GAAI,GAAG,cAAc,EAAE,MAAM,MAAM,8BAC5B,CAAC;AAEtC,eAAO,MAAM,kBAAkB,GAAI,GAAG,cAAc,EAAE,MAAM,MAAM,8BACzB,CAAC;AAE1C,eAAO,MAAM,wBAAwB,GAAI,GAAG,cAAc,EAAE,MAAM,MAAM,8BAC5B,CAAC;AAE7C,eAAO,MAAM,eAAe,GAAI,GAAG,cAAc,EAAE,MAAM,MAAM,EAAE,cAAU,8BACR,CAAC;AAEpE,eAAO,MAAM,yBAAyB,GAAI,GAAG,cAAc,EAAE,MAAM,MAAM,8BAC/B,CAAC;AAE3C,eAAO,MAAM,WAAW,GAAI,GAAG,cAAc,EAAE,MAAM,MAAM,EAAE,iBAAe,8BAChC,CAAC;AAE7C,eAAO,MAAM,aAAa,GAAI,GAAG,cAAc,EAAE,MAAM,MAAM,EAAE,iBAAc,8BAC/B,CAAC;AAE/C,eAAO,MAAM,SAAS,GAAI,GAAG,cAAc,EAAE,UAAU,MAAM,EAAE,OAAO,MAAM,8BAClC,CAAC;AAE3C,eAAO,MAAM,gBAAgB,GAAI,GAAG,cAAc,EAAE,UAAU,MAAM,8BACzB,CAAC;AAE5C,eAAO,MAAM,aAAa,GAAI,GAAG,cAAc,EAAE,UAAU,MAAM,8BACzB,CAAC;AAEzC,eAAO,MAAM,oBAAoB,GAAI,GAAG,cAAc,EAAE,UAAU,MAAM,8BACzB,CAAC;AAEhD,eAAO,MAAM,cAAc,GAAI,GAAG,cAAc,EAAE,OAAO,MAAM,EAAE,WAAW,MAAM,8BAC7B,CAAC;AAEtD,eAAO,MAAM,qBAAqB,GAAI,GAAG,cAAc,EAAE,OAAO,MAAM,EAAE,8BAC7B,CAAC;AAE5C,eAAO,MAAM,kBAAkB,GAAI,IAAI,cAAc,EAAE,OAAO,MAAM,KAAG,OAAO,CAAC,gBAAgB,CAO3F,CAAC"}
package/dist/tools.js ADDED
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Tool implementations shared by the MCP server and the CLI.
3
+ * Each function takes a HomedataClient and the relevant inputs, returns a
4
+ * structured response. No MCP-specific dependencies — both surfaces import these.
5
+ */
6
+ export const lookup_property = (c, uprn) => c.get(`/api/properties/${encodeURIComponent(uprn)}/`);
7
+ export const lookup_epc = (c, uprn) => c.get(`/api/epc-checker/${encodeURIComponent(uprn)}/`);
8
+ export const lookup_flood_risk = (c, uprn) => c.get(`/api/flood-risk/`, { uprn });
9
+ export const get_property_sales = (c, uprn) => c.get(`/api/property_sales/`, { uprn });
10
+ export const search_property_listings = (c, uprn) => c.get(`/api/property_listings/`, { uprn });
11
+ export const get_comparables = (c, uprn, count = 20) => c.get(`/api/comparables/${encodeURIComponent(uprn)}/`, { count });
12
+ export const get_planning_applications = (c, uprn) => c.get(`/api/planning/search/`, { uprn });
13
+ export const get_schools = (c, uprn, radius_m = 1000) => c.get(`/api/schools/`, { uprn, radius_m });
14
+ export const get_transport = (c, uprn, radius_m = 800) => c.get(`/api/transport/`, { uprn, radius_m });
15
+ export const get_crime = (c, postcode, date) => c.get(`/api/crime/`, { postcode, date });
16
+ export const get_demographics = (c, postcode) => c.get(`/api/demographics/`, { postcode });
17
+ export const get_broadband = (c, postcode) => c.get(`/api/broadband/`, { postcode });
18
+ export const get_postcode_profile = (c, postcode) => c.get(`/api/postcode-profile/`, { postcode });
19
+ export const search_address = (c, query, postcode) => c.get(`/api/address/find/`, { q: query, postcode });
20
+ export const batch_property_lookup = (c, uprns) => c.post(`/api/property/batch/`, { uprns });
21
+ export const lookup_council_tax = (_c, _uprn) =>
22
+ // Short-circuit — endpoint is documented "coming soon" and 404s today.
23
+ // Matches the Python 0.1.1 fix; keeps behaviour aligned across SDKs.
24
+ Promise.resolve({
25
+ error: "in_development",
26
+ status_code: 503,
27
+ detail: "Council tax band is in development. See https://homedata.co.uk/changelog",
28
+ });
29
+ //# sourceMappingURL=tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tools.js","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,59 @@
1
+ {
2
+ "name": "homedata-mcp",
3
+ "version": "0.1.0",
4
+ "description": "MCP server + CLI for the Homedata UK property data API — 29M UK properties (EPC, flood risk, planning, comparables, demographics, schools, broadband) for Claude, Cursor, Codex and other AI coding assistants.",
5
+ "type": "module",
6
+ "bin": {
7
+ "homedata-mcp": "dist/server.js",
8
+ "homedata": "dist/cli.js"
9
+ },
10
+ "main": "dist/index.js",
11
+ "types": "dist/index.d.ts",
12
+ "files": [
13
+ "dist",
14
+ "README.md",
15
+ "LICENSE",
16
+ "CHANGELOG.md"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsc",
20
+ "prepare": "npm run build",
21
+ "test": "node --test dist/test/*.js"
22
+ },
23
+ "keywords": [
24
+ "mcp",
25
+ "model-context-protocol",
26
+ "homedata",
27
+ "uk-property",
28
+ "property-data",
29
+ "claude",
30
+ "cursor",
31
+ "codex",
32
+ "windsurf",
33
+ "epc",
34
+ "flood-risk",
35
+ "planning",
36
+ "uprn"
37
+ ],
38
+ "homepage": "https://homedata.co.uk/mcp",
39
+ "bugs": {
40
+ "url": "https://github.com/wehomemove/homedata-mcp-node/issues"
41
+ },
42
+ "repository": {
43
+ "type": "git",
44
+ "url": "git+https://github.com/wehomemove/homedata-mcp-node.git"
45
+ },
46
+ "license": "MIT",
47
+ "author": "Homedata <hello@homedata.co.uk> (https://homedata.co.uk)",
48
+ "engines": {
49
+ "node": ">=18"
50
+ },
51
+ "dependencies": {
52
+ "@modelcontextprotocol/sdk": "^1.0.0",
53
+ "zod": "^3.23.0"
54
+ },
55
+ "devDependencies": {
56
+ "@types/node": "^22.0.0",
57
+ "typescript": "^5.5.0"
58
+ }
59
+ }