mcp-stream-estate 1.0.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/README.md +92 -0
- package/build/client.js +99 -0
- package/build/client.js.map +1 -0
- package/build/index.js +26 -0
- package/build/index.js.map +1 -0
- package/build/schemas/common.js +13 -0
- package/build/schemas/common.js.map +1 -0
- package/build/schemas/property-filters.js +104 -0
- package/build/schemas/property-filters.js.map +1 -0
- package/build/schemas/search-params.js +52 -0
- package/build/schemas/search-params.js.map +1 -0
- package/build/tools/indicators.js +94 -0
- package/build/tools/indicators.js.map +1 -0
- package/build/tools/properties.js +64 -0
- package/build/tools/properties.js.map +1 -0
- package/build/tools/searches.js +76 -0
- package/build/tools/searches.js.map +1 -0
- package/build/tools/webhooks.js +27 -0
- package/build/tools/webhooks.js.map +1 -0
- package/package.json +41 -0
package/README.md
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Stream.estate MCP Server
|
|
2
|
+
|
|
3
|
+
MCP server for the [Stream.estate](https://stream.estate) French real estate API. Search properties, get market statistics, manage saved searches with webhook notifications, and more.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- Node.js >= 20
|
|
8
|
+
- [Stream.estate API key](https://stream.estate/signup)
|
|
9
|
+
|
|
10
|
+
## Quick Start
|
|
11
|
+
|
|
12
|
+
### Claude Code (one command)
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
claude mcp add stream-estate -- npx mcp-stream-estate -e STREAM_ESTATE_API_KEY=your-api-key
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Claude Desktop
|
|
19
|
+
|
|
20
|
+
Add to your `claude_desktop_config.json`:
|
|
21
|
+
|
|
22
|
+
```json
|
|
23
|
+
{
|
|
24
|
+
"mcpServers": {
|
|
25
|
+
"stream-estate": {
|
|
26
|
+
"command": "npx",
|
|
27
|
+
"args": ["mcp-stream-estate"],
|
|
28
|
+
"env": {
|
|
29
|
+
"STREAM_ESTATE_API_KEY": "your-api-key"
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Configuration
|
|
37
|
+
|
|
38
|
+
| Environment Variable | Required | Default | Description |
|
|
39
|
+
|---------------------|----------|---------|-------------|
|
|
40
|
+
| `STREAM_ESTATE_API_KEY` | Yes | — | Your Stream.estate API key ([sign up](https://stream.estate/signup)) |
|
|
41
|
+
| `STREAM_ESTATE_BASE_URL` | No | `https://api.stream.estate` | API base URL |
|
|
42
|
+
|
|
43
|
+
## Available Tools
|
|
44
|
+
|
|
45
|
+
### Properties
|
|
46
|
+
| Tool | Description |
|
|
47
|
+
|------|-------------|
|
|
48
|
+
| `search-properties` | Search properties with 50+ filters (location, price, size, energy, etc.) |
|
|
49
|
+
| `get-property` | Get full property details by UUID |
|
|
50
|
+
| `find-similar-properties` | Find properties similar to a given one |
|
|
51
|
+
|
|
52
|
+
### Indicators
|
|
53
|
+
| Tool | Description |
|
|
54
|
+
|------|-------------|
|
|
55
|
+
| `get-cities` | Search cities by name, zipcode, or INSEE code |
|
|
56
|
+
| `location-autocomplete` | Autocomplete city/department names (returns IDs for filters) |
|
|
57
|
+
| `get-points-of-interest` | Find nearby schools, hospitals, restaurants, etc. |
|
|
58
|
+
| `get-price-per-meter` | Price/m² statistics with average, median, and time series |
|
|
59
|
+
|
|
60
|
+
### Saved Searches
|
|
61
|
+
| Tool | Description |
|
|
62
|
+
|------|-------------|
|
|
63
|
+
| `create-search` | Create a saved search with webhook notifications |
|
|
64
|
+
| `list-searches` | List all saved searches |
|
|
65
|
+
| `get-search` | Get a specific saved search |
|
|
66
|
+
| `update-search` | Update saved search criteria |
|
|
67
|
+
| `delete-search` | Delete a saved search |
|
|
68
|
+
|
|
69
|
+
### Webhooks
|
|
70
|
+
| Tool | Description |
|
|
71
|
+
|------|-------------|
|
|
72
|
+
| `test-webhook` | Send a test payload to a webhook endpoint |
|
|
73
|
+
|
|
74
|
+
## Key Concepts
|
|
75
|
+
|
|
76
|
+
- **Property types**: 0=Flat, 1=House, 2=Building, 3=Parking, 4=Office, 5=Land, 6=Shop
|
|
77
|
+
- **Transaction types**: 0=Sell, 1=Rent
|
|
78
|
+
- **Publisher types**: 0=Individual, 1=Professional
|
|
79
|
+
- **Energy categories**: A (most efficient) through G (least efficient)
|
|
80
|
+
- Use `location-autocomplete` first to find city/department IDs for search filters
|
|
81
|
+
|
|
82
|
+
## Development
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
pnpm run dev # Watch mode
|
|
86
|
+
pnpm run build # Production build
|
|
87
|
+
pnpm start # Run server
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## License
|
|
91
|
+
|
|
92
|
+
MIT
|
package/build/client.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
const DEFAULT_BASE_URL = "https://api.stream.estate";
|
|
2
|
+
export class StreamEstateClient {
|
|
3
|
+
apiKey;
|
|
4
|
+
baseUrl;
|
|
5
|
+
constructor(apiKey, baseUrl) {
|
|
6
|
+
this.apiKey = apiKey;
|
|
7
|
+
this.baseUrl = baseUrl ?? DEFAULT_BASE_URL;
|
|
8
|
+
}
|
|
9
|
+
async get(path, params) {
|
|
10
|
+
const qs = params ? this.buildQueryString(params) : "";
|
|
11
|
+
const url = `${this.baseUrl}${path}${qs ? `?${qs}` : ""}`;
|
|
12
|
+
return this.request(url, { method: "GET" });
|
|
13
|
+
}
|
|
14
|
+
async post(path, body) {
|
|
15
|
+
const url = `${this.baseUrl}${path}`;
|
|
16
|
+
return this.request(url, {
|
|
17
|
+
method: "POST",
|
|
18
|
+
body: JSON.stringify(body),
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
async put(path, body) {
|
|
22
|
+
const url = `${this.baseUrl}${path}`;
|
|
23
|
+
return this.request(url, {
|
|
24
|
+
method: "PUT",
|
|
25
|
+
body: JSON.stringify(body),
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
async del(path) {
|
|
29
|
+
const url = `${this.baseUrl}${path}`;
|
|
30
|
+
return this.request(url, { method: "DELETE" });
|
|
31
|
+
}
|
|
32
|
+
async request(url, init) {
|
|
33
|
+
const res = await fetch(url, {
|
|
34
|
+
...init,
|
|
35
|
+
headers: {
|
|
36
|
+
"Content-Type": "application/json",
|
|
37
|
+
"X-API-KEY": this.apiKey,
|
|
38
|
+
...(init.headers ?? {}),
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
if (!res.ok) {
|
|
42
|
+
const text = await res.text().catch(() => "");
|
|
43
|
+
throw new Error(`API ${res.status}: ${res.statusText}${text ? ` — ${text}` : ""}`);
|
|
44
|
+
}
|
|
45
|
+
if (res.status === 204)
|
|
46
|
+
return { success: true };
|
|
47
|
+
return res.json();
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Build query string with PHP-style array notation: param[]=v1¶m[]=v2
|
|
51
|
+
* Also maps order params: orderCreatedAt -> order[createdAt]
|
|
52
|
+
*/
|
|
53
|
+
buildQueryString(params) {
|
|
54
|
+
const parts = [];
|
|
55
|
+
for (const [key, value] of Object.entries(params)) {
|
|
56
|
+
if (value === undefined || value === null)
|
|
57
|
+
continue;
|
|
58
|
+
// Map flat order params to API bracket notation
|
|
59
|
+
const orderMatch = key.match(/^order(By)?(.+)$/);
|
|
60
|
+
if (orderMatch && typeof value === "string") {
|
|
61
|
+
const field = orderMatch[2];
|
|
62
|
+
const apiField = field.charAt(0).toLowerCase() + field.slice(1);
|
|
63
|
+
parts.push(`order[${apiField}]=${encodeURIComponent(value)}`);
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
if (Array.isArray(value)) {
|
|
67
|
+
for (const item of value) {
|
|
68
|
+
parts.push(`${encodeURIComponent(key)}[]=${encodeURIComponent(String(item))}`);
|
|
69
|
+
}
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
if (typeof value === "object") {
|
|
73
|
+
// Handle nested objects like expressions
|
|
74
|
+
for (const [subKey, subVal] of Object.entries(value)) {
|
|
75
|
+
parts.push(`${encodeURIComponent(key)}[${encodeURIComponent(subKey)}]=${encodeURIComponent(String(subVal))}`);
|
|
76
|
+
}
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
parts.push(`${encodeURIComponent(key)}=${encodeURIComponent(String(value))}`);
|
|
80
|
+
}
|
|
81
|
+
return parts.join("&");
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Transform expressions from simplified format to API's nested array format.
|
|
85
|
+
* Input: [{ word: "balcon", includes: true, strict: false }]
|
|
86
|
+
* Output: expressions[0][0][value]=balcon&expressions[0][0][options][includes]=true&expressions[0][0][options][strict]=false
|
|
87
|
+
*/
|
|
88
|
+
buildExpressionsParams(expressions) {
|
|
89
|
+
const result = {};
|
|
90
|
+
expressions.forEach((expr, groupIdx) => {
|
|
91
|
+
const prefix = `expressions[${groupIdx}][0]`;
|
|
92
|
+
result[`${prefix}[value]`] = expr.word;
|
|
93
|
+
result[`${prefix}[options][includes]`] = String(expr.includes ?? true);
|
|
94
|
+
result[`${prefix}[options][strict]`] = String(expr.strict ?? false);
|
|
95
|
+
});
|
|
96
|
+
return result;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/build/index.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { StreamEstateClient } from "./client.js";
|
|
5
|
+
import { registerIndicatorTools } from "./tools/indicators.js";
|
|
6
|
+
import { registerPropertyTools } from "./tools/properties.js";
|
|
7
|
+
import { registerSearchTools } from "./tools/searches.js";
|
|
8
|
+
import { registerWebhookTools } from "./tools/webhooks.js";
|
|
9
|
+
const apiKey = process.env.STREAM_ESTATE_API_KEY;
|
|
10
|
+
if (!apiKey) {
|
|
11
|
+
console.error("STREAM_ESTATE_API_KEY environment variable is required");
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
const baseUrl = process.env.STREAM_ESTATE_BASE_URL || "https://api.stream.estate";
|
|
15
|
+
const client = new StreamEstateClient(apiKey, baseUrl);
|
|
16
|
+
const server = new McpServer({
|
|
17
|
+
name: "stream-estate",
|
|
18
|
+
version: "1.0.0",
|
|
19
|
+
});
|
|
20
|
+
registerIndicatorTools(server, client);
|
|
21
|
+
registerPropertyTools(server, client);
|
|
22
|
+
registerSearchTools(server, client);
|
|
23
|
+
registerWebhookTools(server, client);
|
|
24
|
+
const transport = new StdioServerTransport();
|
|
25
|
+
await server.connect(transport);
|
|
26
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAE3D,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;AACjD,IAAI,CAAC,MAAM,EAAE,CAAC;IACZ,OAAO,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAC;IACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,2BAA2B,CAAC;AAClF,MAAM,MAAM,GAAG,IAAI,kBAAkB,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEvD,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;IAC3B,IAAI,EAAE,eAAe;IACrB,OAAO,EAAE,OAAO;CACjB,CAAC,CAAC;AAEH,sBAAsB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACvC,qBAAqB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACtC,mBAAmB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACpC,oBAAoB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAErC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;AAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const paginationParams = {
|
|
3
|
+
page: z.number().optional().describe("Page number (default: 1)"),
|
|
4
|
+
itemsPerPage: z.number().optional().describe("Items per page (max: 30)"),
|
|
5
|
+
};
|
|
6
|
+
export const propertyOrderParams = {
|
|
7
|
+
orderByCreatedAt: z.enum(["asc", "desc"]).optional().describe("Sort by creation date"),
|
|
8
|
+
orderByUpdatedAt: z.enum(["asc", "desc"]).optional().describe("Sort by last update date"),
|
|
9
|
+
orderByPrice: z.enum(["asc", "desc"]).optional().describe("Sort by price"),
|
|
10
|
+
orderBySurface: z.enum(["asc", "desc"]).optional().describe("Sort by surface area"),
|
|
11
|
+
orderByPricePerMeter: z.enum(["asc", "desc"]).optional().describe("Sort by price per m²"),
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=common.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../src/schemas/common.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0BAA0B,CAAC;IAChE,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0BAA0B,CAAC;CACzE,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,gBAAgB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;IACtF,gBAAgB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,0BAA0B,CAAC;IACzF,YAAY,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC;IAC1E,cAAc,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;IACnF,oBAAoB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;CAC1F,CAAC"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
// --- Location filters ---
|
|
3
|
+
export const locationFilters = {
|
|
4
|
+
includedCities: z.array(z.string()).optional().describe('City IRIs, e.g. ["/cities/30953"]. Use location-autocomplete to find IDs.'),
|
|
5
|
+
includedDepartments: z.array(z.string()).optional().describe('Department IRIs, e.g. ["/departments/77"]'),
|
|
6
|
+
includedZipcodes: z.array(z.string()).optional().describe('Zipcodes, e.g. ["75017", "75018"]'),
|
|
7
|
+
includedInseeCodes: z.array(z.string()).optional().describe('INSEE codes, e.g. ["75117"]'),
|
|
8
|
+
excludedCities: z.array(z.string()).optional().describe("City IRIs to exclude"),
|
|
9
|
+
excludedInseeCodes: z.array(z.string()).optional().describe("INSEE codes to exclude"),
|
|
10
|
+
excludedZipcodes: z.array(z.string()).optional().describe("Zipcodes to exclude"),
|
|
11
|
+
excludedProperties: z.array(z.string()).optional().describe("Property IRIs to exclude"),
|
|
12
|
+
lat: z.number().optional().describe("Latitude for radius search"),
|
|
13
|
+
lon: z.number().optional().describe("Longitude for radius search"),
|
|
14
|
+
radius: z.number().optional().describe("Search radius in km (requires lat+lon)"),
|
|
15
|
+
geoShapes: z.array(z.string()).optional().describe("Geographic polygon coordinates for area search"),
|
|
16
|
+
geocodingAccuracy: z.array(z.number()).optional().describe("1=house-number, 2=neighborhood"),
|
|
17
|
+
withResolvedLocation: z.boolean().optional().describe("Only properties with resolved GPS coordinates"),
|
|
18
|
+
};
|
|
19
|
+
// --- Price filters ---
|
|
20
|
+
export const priceFilters = {
|
|
21
|
+
budgetMin: z.number().optional().describe("Minimum price/budget"),
|
|
22
|
+
budgetMax: z.number().optional().describe("Maximum price/budget"),
|
|
23
|
+
pricePerMeterMin: z.number().optional().describe("Minimum price per m²"),
|
|
24
|
+
pricePerMeterMax: z.number().optional().describe("Maximum price per m²"),
|
|
25
|
+
priceExcludingFeesMin: z.number().optional().describe("Minimum price excluding fees"),
|
|
26
|
+
priceExcludingFeesMax: z.number().optional().describe("Maximum price excluding fees"),
|
|
27
|
+
priceMin: z.number().optional().describe("Minimum advert price"),
|
|
28
|
+
priceMax: z.number().optional().describe("Maximum advert price"),
|
|
29
|
+
withCoherentPrice: z.boolean().optional().describe("Filter for coherent/realistic prices"),
|
|
30
|
+
};
|
|
31
|
+
// --- Property characteristic filters ---
|
|
32
|
+
export const propertyCharacteristicFilters = {
|
|
33
|
+
propertyTypes: z.array(z.number()).optional().describe("0=Flat, 1=House, 2=Building, 3=Parking, 4=Office, 5=Land, 6=Shop"),
|
|
34
|
+
transactionType: z.number().optional().describe("0=Sell, 1=Rent"),
|
|
35
|
+
publisherTypes: z.array(z.number()).optional().describe("0=Individual, 1=Professional"),
|
|
36
|
+
roomMin: z.number().optional().describe("Minimum number of rooms"),
|
|
37
|
+
roomMax: z.number().optional().describe("Maximum number of rooms"),
|
|
38
|
+
bedroomMin: z.number().optional().describe("Minimum number of bedrooms"),
|
|
39
|
+
bedroomMax: z.number().optional().describe("Maximum number of bedrooms"),
|
|
40
|
+
surfaceMin: z.number().optional().describe("Minimum surface area in m²"),
|
|
41
|
+
surfaceMax: z.number().optional().describe("Maximum surface area in m²"),
|
|
42
|
+
furnished: z.boolean().optional().describe("Filter for furnished properties"),
|
|
43
|
+
withVirtualTour: z.boolean().optional().describe("Only properties with virtual tour"),
|
|
44
|
+
isExpired: z.boolean().optional().describe("Filter expired/active properties"),
|
|
45
|
+
sortMode: z.string().optional().describe('"property" or "advert" sorting mode'),
|
|
46
|
+
};
|
|
47
|
+
// --- Energy filters ---
|
|
48
|
+
export const energyFilters = {
|
|
49
|
+
energyCategories: z.array(z.string()).optional().describe("Energy efficiency categories: A through G"),
|
|
50
|
+
energyValueMin: z.number().optional().describe("Minimum energy value"),
|
|
51
|
+
energyValueMax: z.number().optional().describe("Maximum energy value"),
|
|
52
|
+
ghgLetters: z.array(z.string()).optional().describe("Greenhouse gas categories: A through G"),
|
|
53
|
+
ghgValueMin: z.number().optional().describe("Minimum GHG value"),
|
|
54
|
+
ghgValueMax: z.number().optional().describe("Maximum GHG value"),
|
|
55
|
+
};
|
|
56
|
+
// --- Date filters ---
|
|
57
|
+
export const dateFilters = {
|
|
58
|
+
fromDate: z.string().optional().describe("Property creation start date (ISO 8601)"),
|
|
59
|
+
toDate: z.string().optional().describe("Property creation end date (ISO 8601)"),
|
|
60
|
+
fromUpdatedAt: z.string().optional().describe("Property update start date (ISO 8601)"),
|
|
61
|
+
toUpdatedAt: z.string().optional().describe("Property update end date (ISO 8601)"),
|
|
62
|
+
};
|
|
63
|
+
// --- Event variation filters ---
|
|
64
|
+
export const eventFilters = {
|
|
65
|
+
priceEventFromDate: z.string().optional().describe("Price event start date (ISO 8601)"),
|
|
66
|
+
priceEventToDate: z.string().optional().describe("Price event end date (ISO 8601)"),
|
|
67
|
+
priceEventVariationMin: z.number().optional().describe("Minimum price variation %"),
|
|
68
|
+
priceEventVariationMax: z.number().optional().describe("Maximum price variation %"),
|
|
69
|
+
surfaceEventFromDate: z.string().optional().describe("Surface event start date (ISO 8601)"),
|
|
70
|
+
surfaceEventToDate: z.string().optional().describe("Surface event end date (ISO 8601)"),
|
|
71
|
+
surfaceEventVariationMin: z.number().optional().describe("Minimum surface variation %"),
|
|
72
|
+
surfaceEventVariationMax: z.number().optional().describe("Maximum surface variation %"),
|
|
73
|
+
};
|
|
74
|
+
// --- Misc filters ---
|
|
75
|
+
export const miscFilters = {
|
|
76
|
+
constructionYearMin: z.number().optional().describe("Minimum construction year"),
|
|
77
|
+
constructionYearMax: z.number().optional().describe("Maximum construction year"),
|
|
78
|
+
condominiumFeesMin: z.number().optional().describe("Minimum condominium fees"),
|
|
79
|
+
condominiumFeesMax: z.number().optional().describe("Maximum condominium fees"),
|
|
80
|
+
feesPercentageMin: z.number().optional().describe("Minimum fees percentage"),
|
|
81
|
+
feesPercentageMax: z.number().optional().describe("Maximum fees percentage"),
|
|
82
|
+
feesResponsibility: z.number().optional().describe("0=seller, 1=buyer"),
|
|
83
|
+
floorsMin: z.number().optional().describe("Minimum number of floors"),
|
|
84
|
+
floorsMax: z.number().optional().describe("Maximum number of floors"),
|
|
85
|
+
lotCountMin: z.number().optional().describe("Minimum lot count in condominium"),
|
|
86
|
+
lotCountMax: z.number().optional().describe("Maximum lot count in condominium"),
|
|
87
|
+
inventoryPriceMin: z.number().optional().describe("Minimum inventory price"),
|
|
88
|
+
inventoryPriceMax: z.number().optional().describe("Maximum inventory price"),
|
|
89
|
+
rentalChargesMin: z.number().optional().describe("Minimum rental charges"),
|
|
90
|
+
rentalChargesMax: z.number().optional().describe("Maximum rental charges"),
|
|
91
|
+
rentalPledgeMin: z.number().optional().describe("Minimum rental pledge/deposit"),
|
|
92
|
+
rentalPledgeMax: z.number().optional().describe("Maximum rental pledge/deposit"),
|
|
93
|
+
renterFeesMin: z.number().optional().describe("Minimum renter fees"),
|
|
94
|
+
renterFeesMax: z.number().optional().describe("Maximum renter fees"),
|
|
95
|
+
};
|
|
96
|
+
// --- Full-text search ---
|
|
97
|
+
export const expressionFilters = {
|
|
98
|
+
expressions: z.array(z.object({
|
|
99
|
+
word: z.string().describe("Search term"),
|
|
100
|
+
includes: z.boolean().optional().describe("true to include, false to exclude (default: true)"),
|
|
101
|
+
strict: z.boolean().optional().describe("true for exact phrase match (default: false)"),
|
|
102
|
+
})).optional().describe("Full-text search expressions for property title/description"),
|
|
103
|
+
};
|
|
104
|
+
//# sourceMappingURL=property-filters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"property-filters.js","sourceRoot":"","sources":["../../src/schemas/property-filters.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export const searchBodyParams = {
|
|
3
|
+
title: z.string().optional().describe("Search title/name"),
|
|
4
|
+
transactionType: z.number().optional().describe("0=Sell, 1=Rent"),
|
|
5
|
+
propertyTypes: z.array(z.number()).optional().describe("0=Flat, 1=House, 2=Building, 3=Parking, 4=Office, 5=Land, 6=Shop"),
|
|
6
|
+
publisherTypes: z.array(z.number()).optional().describe("0=Individual, 1=Professional"),
|
|
7
|
+
budgetMin: z.number().optional().describe("Minimum budget"),
|
|
8
|
+
budgetMax: z.number().optional().describe("Maximum budget"),
|
|
9
|
+
surfaceMin: z.number().optional().describe("Minimum surface in m²"),
|
|
10
|
+
surfaceMax: z.number().optional().describe("Maximum surface in m²"),
|
|
11
|
+
roomMin: z.number().optional().describe("Minimum rooms"),
|
|
12
|
+
roomMax: z.number().optional().describe("Maximum rooms"),
|
|
13
|
+
bedroomMin: z.number().optional().describe("Minimum bedrooms"),
|
|
14
|
+
bedroomMax: z.number().optional().describe("Maximum bedrooms"),
|
|
15
|
+
landSurfaceMin: z.number().optional().describe("Minimum land surface in m²"),
|
|
16
|
+
landSurfaceMax: z.number().optional().describe("Maximum land surface in m²"),
|
|
17
|
+
pricePerMeterMin: z.number().optional().describe("Minimum price per m²"),
|
|
18
|
+
pricePerMeterMax: z.number().optional().describe("Maximum price per m²"),
|
|
19
|
+
furnished: z.boolean().optional().describe("Filter furnished properties"),
|
|
20
|
+
withCoherentPrice: z.boolean().optional().describe("Filter for coherent prices"),
|
|
21
|
+
withVirtualTour: z.boolean().optional().describe("Only with virtual tour"),
|
|
22
|
+
// Location
|
|
23
|
+
includedCities: z.array(z.string()).optional().describe('City IRIs, e.g. ["/cities/30953"]'),
|
|
24
|
+
includedDepartments: z.array(z.string()).optional().describe('Department IRIs, e.g. ["/departments/77"]'),
|
|
25
|
+
includedZipcodes: z.array(z.string()).optional().describe("Zipcodes to include"),
|
|
26
|
+
includedInseeCodes: z.array(z.string()).optional().describe("INSEE codes to include"),
|
|
27
|
+
excludedCities: z.array(z.string()).optional().describe("City IRIs to exclude"),
|
|
28
|
+
lat: z.number().optional().describe("Latitude for radius search"),
|
|
29
|
+
lon: z.number().optional().describe("Longitude for radius search"),
|
|
30
|
+
radius: z.number().optional().describe("Search radius in km"),
|
|
31
|
+
geoShapes: z.array(z.string()).optional().describe("Geographic polygon coordinates"),
|
|
32
|
+
geoAccuracy: z.number().optional().describe("1=house-number, 2=neighborhood"),
|
|
33
|
+
// Full-text search
|
|
34
|
+
expressions: z.array(z.object({
|
|
35
|
+
word: z.string().describe("Search term"),
|
|
36
|
+
includes: z.boolean().optional().describe("Include or exclude (default: true)"),
|
|
37
|
+
strict: z.boolean().optional().describe("Exact phrase match (default: false)"),
|
|
38
|
+
})).optional().describe("Full-text search expressions"),
|
|
39
|
+
// Notifications
|
|
40
|
+
notificationEnabled: z.boolean().optional().describe("Enable webhook/email notifications"),
|
|
41
|
+
notificationRecipient: z.string().optional().describe("Email address for alerts"),
|
|
42
|
+
endpointRecipient: z.string().optional().describe("HTTPS webhook URL for match payloads"),
|
|
43
|
+
eventEndpoint: z.string().optional().describe("HTTPS webhook URL for event payloads"),
|
|
44
|
+
subscribedEvents: z.array(z.string()).optional().describe("Event types: property.ad.create, ad.update.price, ad.update.surface, ad.update.pictures, ad.update.expired, property.ad.update"),
|
|
45
|
+
hidePropertyContact: z.boolean().optional().describe("Hide contact info in payloads"),
|
|
46
|
+
// Source filters
|
|
47
|
+
includedSources: z.array(z.string()).optional().describe("Source sites to include"),
|
|
48
|
+
excludedSources: z.array(z.string()).optional().describe("Source sites to exclude"),
|
|
49
|
+
includedSiteCategories: z.array(z.string()).optional().describe("Site categories to include"),
|
|
50
|
+
excludedSiteCategories: z.array(z.string()).optional().describe("Site categories to exclude"),
|
|
51
|
+
};
|
|
52
|
+
//# sourceMappingURL=search-params.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-params.js","sourceRoot":"","sources":["../../src/schemas/search-params.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { paginationParams } from "../schemas/common.js";
|
|
3
|
+
import { locationFilters, priceFilters, propertyCharacteristicFilters, energyFilters, dateFilters, eventFilters, miscFilters, expressionFilters, } from "../schemas/property-filters.js";
|
|
4
|
+
export function registerIndicatorTools(server, client) {
|
|
5
|
+
// ── get-cities ──────────────────────────────────────────────────────
|
|
6
|
+
server.tool("get-cities", "Search French cities by name, zipcode, INSEE code, or geographic polygon. Returns city IDs needed for property search filters.", {
|
|
7
|
+
excludeGroupedCities: z.boolean().optional(),
|
|
8
|
+
inseeCode: z.string().optional().describe("Filter by single INSEE code"),
|
|
9
|
+
inseeCodes: z.array(z.string()).optional().describe("Filter by multiple INSEE codes"),
|
|
10
|
+
polygon: z.string().optional().describe("GPS coordinate polygon"),
|
|
11
|
+
label: z.string().optional().describe("Filter by display name"),
|
|
12
|
+
name: z.string().optional().describe("Filter by city name"),
|
|
13
|
+
sortByName: z.enum(["asc", "desc"]).optional(),
|
|
14
|
+
page: z.number().optional(),
|
|
15
|
+
slug: z.string().optional(),
|
|
16
|
+
zipcode: z.string().optional(),
|
|
17
|
+
zipcodes: z.array(z.string()).optional(),
|
|
18
|
+
}, async (params) => {
|
|
19
|
+
try {
|
|
20
|
+
const data = await client.get("/cities", params);
|
|
21
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
25
|
+
return { content: [{ type: "text", text: `Error: ${message}` }], isError: true };
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
// ── location-autocomplete ───────────────────────────────────────────
|
|
29
|
+
server.tool("location-autocomplete", "Autocomplete cities and departments by search query. Returns IDs needed for location filters in search-properties and create-search.", {
|
|
30
|
+
query: z.string().describe("Search term (e.g. 'Paris', 'Lyon', 'Marseille')"),
|
|
31
|
+
excludeCities: z.array(z.string()).optional().describe("City IRIs to exclude"),
|
|
32
|
+
excludeDepartments: z.array(z.string()).optional().describe("Department IRIs to exclude"),
|
|
33
|
+
}, async (params) => {
|
|
34
|
+
try {
|
|
35
|
+
const data = await client.get("/public/location-autocomplete", params);
|
|
36
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
40
|
+
return { content: [{ type: "text", text: `Error: ${message}` }], isError: true };
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
// ── get-points-of-interest ──────────────────────────────────────────
|
|
44
|
+
server.tool("get-points-of-interest", "Find points of interest (schools, hospitals, restaurants, parking) near a location. Returns facilities within a radius of given coordinates.", {
|
|
45
|
+
lat: z.number().describe("Latitude"),
|
|
46
|
+
lon: z.number().describe("Longitude"),
|
|
47
|
+
radius: z.number().optional().describe("Search radius in km"),
|
|
48
|
+
facilities: z
|
|
49
|
+
.array(z.string())
|
|
50
|
+
.optional()
|
|
51
|
+
.describe('Categories: "kindergarten", "school", "restaurant", "hospital", "parking"'),
|
|
52
|
+
}, async (params) => {
|
|
53
|
+
try {
|
|
54
|
+
const data = await client.get("/indicators/points_of_interest", params);
|
|
55
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
59
|
+
return { content: [{ type: "text", text: `Error: ${message}` }], isError: true };
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
// ── get-price-per-meter ─────────────────────────────────────────────
|
|
63
|
+
server.tool("get-price-per-meter", "Get price per m² statistics (average, median, time series) for properties matching filters. Useful for market analysis and property valuation.", {
|
|
64
|
+
...locationFilters,
|
|
65
|
+
...priceFilters,
|
|
66
|
+
...propertyCharacteristicFilters,
|
|
67
|
+
...energyFilters,
|
|
68
|
+
...dateFilters,
|
|
69
|
+
...eventFilters,
|
|
70
|
+
...miscFilters,
|
|
71
|
+
...expressionFilters,
|
|
72
|
+
...paginationParams,
|
|
73
|
+
dateHistogramGranularity: z
|
|
74
|
+
.enum(["month", "year"])
|
|
75
|
+
.optional()
|
|
76
|
+
.describe("Granularity for date histogram"),
|
|
77
|
+
}, async (params) => {
|
|
78
|
+
try {
|
|
79
|
+
const { expressions, ...rest } = params;
|
|
80
|
+
const queryParams = { ...rest };
|
|
81
|
+
if (expressions?.length) {
|
|
82
|
+
const exprParams = client.buildExpressionsParams(expressions);
|
|
83
|
+
Object.assign(queryParams, exprParams);
|
|
84
|
+
}
|
|
85
|
+
const data = await client.get("/indicators/price_per_meter", queryParams);
|
|
86
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
90
|
+
return { content: [{ type: "text", text: `Error: ${message}` }], isError: true };
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=indicators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"indicators.js","sourceRoot":"","sources":["../../src/tools/indicators.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { paginationParams, propertyOrderParams } from "../schemas/common.js";
|
|
3
|
+
import { locationFilters, priceFilters, propertyCharacteristicFilters, energyFilters, dateFilters, eventFilters, miscFilters, expressionFilters, } from "../schemas/property-filters.js";
|
|
4
|
+
export function registerPropertyTools(server, client) {
|
|
5
|
+
// Tool 1: search-properties
|
|
6
|
+
server.tool("search-properties", "Search French real estate properties with extensive filters for location, price, size, rooms, energy rating, and more. Returns paginated results with property details, adverts, photos, and nearby stations. Use location-autocomplete first to resolve city/department IDs.", {
|
|
7
|
+
...locationFilters,
|
|
8
|
+
...priceFilters,
|
|
9
|
+
...propertyCharacteristicFilters,
|
|
10
|
+
...energyFilters,
|
|
11
|
+
...dateFilters,
|
|
12
|
+
...eventFilters,
|
|
13
|
+
...miscFilters,
|
|
14
|
+
...expressionFilters,
|
|
15
|
+
...paginationParams,
|
|
16
|
+
...propertyOrderParams,
|
|
17
|
+
}, async (params) => {
|
|
18
|
+
try {
|
|
19
|
+
const { expressions, ...rest } = params;
|
|
20
|
+
const queryParams = { ...rest };
|
|
21
|
+
if (expressions?.length) {
|
|
22
|
+
const exprParams = client.buildExpressionsParams(expressions);
|
|
23
|
+
Object.assign(queryParams, exprParams);
|
|
24
|
+
}
|
|
25
|
+
const data = await client.get("/documents/properties", queryParams);
|
|
26
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
27
|
+
}
|
|
28
|
+
catch (error) {
|
|
29
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
30
|
+
return { content: [{ type: "text", text: `Error: ${message}` }], isError: true };
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
// Tool 2: get-property
|
|
34
|
+
server.tool("get-property", "Get full details for a single property by UUID, including all adverts, price history events, photos, contact info, and nearby transit stations.", {
|
|
35
|
+
id: z.string().describe("Property UUID"),
|
|
36
|
+
}, async (params) => {
|
|
37
|
+
try {
|
|
38
|
+
const data = await client.get(`/documents/properties/${params.id}`);
|
|
39
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
43
|
+
return { content: [{ type: "text", text: `Error: ${message}` }], isError: true };
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
// Tool 3: find-similar-properties
|
|
47
|
+
server.tool("find-similar-properties", "Find properties similar to a given property. Useful for market comparisons and finding alternatives.", {
|
|
48
|
+
id: z.string().describe("Reference property UUID"),
|
|
49
|
+
fromDate: z.string().optional().describe("Creation start date (ISO 8601)"),
|
|
50
|
+
...paginationParams,
|
|
51
|
+
...propertyOrderParams,
|
|
52
|
+
}, async (params) => {
|
|
53
|
+
try {
|
|
54
|
+
const { id, ...queryParams } = params;
|
|
55
|
+
const data = await client.get(`/documents/properties/${id}/similar-properties`, queryParams);
|
|
56
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
60
|
+
return { content: [{ type: "text", text: `Error: ${message}` }], isError: true };
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=properties.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"properties.js","sourceRoot":"","sources":["../../src/tools/properties.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { searchBodyParams } from "../schemas/search-params.js";
|
|
3
|
+
export function registerSearchTools(server, client) {
|
|
4
|
+
// ── create-search ───────────────────────────────────────────────────
|
|
5
|
+
server.tool("create-search", "Create a saved search with optional webhook notifications for real-time property alerts. Configure location, price, size filters and webhook endpoints.", {
|
|
6
|
+
...searchBodyParams,
|
|
7
|
+
}, async (params) => {
|
|
8
|
+
try {
|
|
9
|
+
const body = { ...params };
|
|
10
|
+
const data = await client.post("/searches", body);
|
|
11
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
12
|
+
}
|
|
13
|
+
catch (error) {
|
|
14
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
15
|
+
return { content: [{ type: "text", text: `Error: ${message}` }], isError: true };
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
// ── list-searches ───────────────────────────────────────────────────
|
|
19
|
+
server.tool("list-searches", "List all saved searches for the authenticated user. Can filter by notification status and title.", {
|
|
20
|
+
notificationEnabled: z.boolean().optional().describe("Filter by notification status"),
|
|
21
|
+
orderByTitle: z.enum(["asc", "desc"]).optional().describe("Sort by title"),
|
|
22
|
+
page: z.number().optional().describe("Page number"),
|
|
23
|
+
title: z.string().optional().describe("Filter by title"),
|
|
24
|
+
}, async (params) => {
|
|
25
|
+
try {
|
|
26
|
+
const data = await client.get("/searches", params);
|
|
27
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
31
|
+
return { content: [{ type: "text", text: `Error: ${message}` }], isError: true };
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
// ── get-search ──────────────────────────────────────────────────────
|
|
35
|
+
server.tool("get-search", "Get details of a specific saved search by its ID.", {
|
|
36
|
+
id: z.string().describe("Search ID"),
|
|
37
|
+
}, async (params) => {
|
|
38
|
+
try {
|
|
39
|
+
const data = await client.get(`/searches/${params.id}`);
|
|
40
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
44
|
+
return { content: [{ type: "text", text: `Error: ${message}` }], isError: true };
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
// ── update-search ───────────────────────────────────────────────────
|
|
48
|
+
server.tool("update-search", "Update an existing saved search with new criteria, filters, or webhook configuration.", {
|
|
49
|
+
id: z.string().describe("Search ID"),
|
|
50
|
+
...searchBodyParams,
|
|
51
|
+
}, async (params) => {
|
|
52
|
+
try {
|
|
53
|
+
const { id, ...body } = params;
|
|
54
|
+
const data = await client.put(`/searches/${id}`, body);
|
|
55
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
59
|
+
return { content: [{ type: "text", text: `Error: ${message}` }], isError: true };
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
// ── delete-search ───────────────────────────────────────────────────
|
|
63
|
+
server.tool("delete-search", "Delete a saved search by its ID.", {
|
|
64
|
+
id: z.string().describe("Search ID"),
|
|
65
|
+
}, async (params) => {
|
|
66
|
+
try {
|
|
67
|
+
const data = await client.del(`/searches/${params.id}`);
|
|
68
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
72
|
+
return { content: [{ type: "text", text: `Error: ${message}` }], isError: true };
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=searches.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"searches.js","sourceRoot":"","sources":["../../src/tools/searches.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export function registerWebhookTools(server, client) {
|
|
3
|
+
// ── test-webhook ────────────────────────────────────────────────────
|
|
4
|
+
server.tool("test-webhook", "Test webhook delivery by sending a simulated match or event payload to an endpoint. Useful for verifying webhook integration.", {
|
|
5
|
+
endpoint: z.string().describe("HTTPS webhook URL to test"),
|
|
6
|
+
type: z
|
|
7
|
+
.enum([
|
|
8
|
+
"ad.update.price",
|
|
9
|
+
"ad.update.surface",
|
|
10
|
+
"ad.update.pictures",
|
|
11
|
+
"ad.update.expired",
|
|
12
|
+
"property.ad.create",
|
|
13
|
+
"property.ad.update",
|
|
14
|
+
])
|
|
15
|
+
.describe("Event type to simulate"),
|
|
16
|
+
}, async (params) => {
|
|
17
|
+
try {
|
|
18
|
+
const data = await client.get("/webhook-tester", params);
|
|
19
|
+
return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
23
|
+
return { content: [{ type: "text", text: `Error: ${message}` }], isError: true };
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=webhooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhooks.js","sourceRoot":"","sources":["../../src/tools/webhooks.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,MAAM,UAAU,oBAAoB,CAAC,MAAiB,EAAE,MAA0B;IAChF,uEAAuE;IACvE,MAAM,CAAC,IAAI,CACT,cAAc,EACd,+HAA+H,EAC/H;QACE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,2BAA2B,CAAC;QAC1D,IAAI,EAAE,CAAC;aACJ,IAAI,CAAC;YACJ,iBAAiB;YACjB,mBAAmB;YACnB,oBAAoB;YACpB,mBAAmB;YACnB,oBAAoB;YACpB,oBAAoB;SACrB,CAAC;aACD,QAAQ,CAAC,wBAAwB,CAAC;KACtC,EACD,KAAK,EAAE,MAAM,EAAE,EAAE;QACf,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,iBAAiB,EAAE,MAAM,CAAC,CAAC;YACzD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;QACvF,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,OAAO,EAAE,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC5F,CAAC;IACH,CAAC,CACF,CAAC;AACJ,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "mcp-stream-estate",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "MCP server for the Stream.estate French real estate API",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"mcp-stream-estate": "./build/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc && chmod 755 build/index.js",
|
|
11
|
+
"start": "node build/index.js",
|
|
12
|
+
"dev": "tsc --watch"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"build"
|
|
16
|
+
],
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": ">=20.0.0"
|
|
19
|
+
},
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "https://github.com/StreamEstate/mcp-server.git"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"mcp",
|
|
27
|
+
"model-context-protocol",
|
|
28
|
+
"stream-estate",
|
|
29
|
+
"real-estate",
|
|
30
|
+
"france",
|
|
31
|
+
"api"
|
|
32
|
+
],
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
35
|
+
"zod": "^4.3.6"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@types/node": "^25.5.0",
|
|
39
|
+
"typescript": "^5.9.3"
|
|
40
|
+
}
|
|
41
|
+
}
|