@opendata.cat/mcp-server 0.0.16 → 0.0.18
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 +3 -2
- package/dist/clients/socrata.js +50 -1
- package/dist/index.js +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -224,8 +224,9 @@ Les contribucions son benvingudes! Per afegir un nou portal de dades obertes:
|
|
|
224
224
|
|
|
225
225
|
## Changelog
|
|
226
226
|
|
|
227
|
-
### v0.0.
|
|
228
|
-
-
|
|
227
|
+
### v0.0.17 (2026-04-14)
|
|
228
|
+
- Simplificacio automatica de geometries GIS: centroide + bounding box en lloc de milers de coordenades
|
|
229
|
+
- Decodificador GTFS-RT integrat: trens FGC en temps real (retards, alertes, posicions GPS)
|
|
229
230
|
- Descodifica automaticament fitxers Protocol Buffers (.pb) de GTFS Realtime
|
|
230
231
|
- API REST documentada amb Swagger UI a /api/docs.html (OpenAPI 3.1)
|
|
231
232
|
- Instruccions per a models locals: LM Studio, Ollama (MCPHost) i Jan
|
package/dist/clients/socrata.js
CHANGED
|
@@ -15,5 +15,54 @@ export async function querySocrata(endpoint, filters, search, limit = 20, offset
|
|
|
15
15
|
const resp = await fetch(url.toString());
|
|
16
16
|
if (!resp.ok)
|
|
17
17
|
throw new Error(`Socrata error ${resp.status}: ${resp.statusText}`);
|
|
18
|
-
|
|
18
|
+
const rows = (await resp.json());
|
|
19
|
+
// Simplify geo fields: replace heavy polygon coords with centroid
|
|
20
|
+
return rows.map((row) => {
|
|
21
|
+
const simplified = {};
|
|
22
|
+
for (const [key, val] of Object.entries(row)) {
|
|
23
|
+
if (val && typeof val === "object" && "type" in val) {
|
|
24
|
+
const geo = val;
|
|
25
|
+
if (geo.type === "Point") {
|
|
26
|
+
simplified[key] = val;
|
|
27
|
+
}
|
|
28
|
+
else if (geo.type === "MultiPolygon" || geo.type === "Polygon" || geo.type === "MultiLineString" || geo.type === "LineString") {
|
|
29
|
+
// Extract centroid from coordinates
|
|
30
|
+
const coords = _flattenCoords(geo.coordinates);
|
|
31
|
+
if (coords.length > 0) {
|
|
32
|
+
const lats = coords.map((c) => c[1]);
|
|
33
|
+
const lngs = coords.map((c) => c[0]);
|
|
34
|
+
simplified[key] = {
|
|
35
|
+
type: geo.type,
|
|
36
|
+
centroid: { lat: _avg(lats), lng: _avg(lngs) },
|
|
37
|
+
bbox: { min_lat: Math.min(...lats), max_lat: Math.max(...lats), min_lng: Math.min(...lngs), max_lng: Math.max(...lngs) },
|
|
38
|
+
vertex_count: coords.length,
|
|
39
|
+
_note: "Geometria simplificada a centroide+bbox per no saturar el context. Usa l'endpoint .geojson de Socrata per obtenir les coordenades completes.",
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
simplified[key] = val;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
simplified[key] = val;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
simplified[key] = val;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return simplified;
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
function _flattenCoords(coords) {
|
|
58
|
+
if (!Array.isArray(coords))
|
|
59
|
+
return [];
|
|
60
|
+
if (coords.length === 0)
|
|
61
|
+
return [];
|
|
62
|
+
if (typeof coords[0] === "number")
|
|
63
|
+
return [coords];
|
|
64
|
+
return coords.flatMap((c) => _flattenCoords(c));
|
|
65
|
+
}
|
|
66
|
+
function _avg(nums) {
|
|
67
|
+
return Math.round((nums.reduce((a, b) => a + b, 0) / nums.length) * 10000) / 10000;
|
|
19
68
|
}
|
package/dist/index.js
CHANGED
|
@@ -13,10 +13,10 @@ import { queryOpendatasoft } from "./clients/opendatasoft.js";
|
|
|
13
13
|
import { decodeGtfsRt } from "./clients/gtfsrt.js";
|
|
14
14
|
const server = new McpServer({
|
|
15
15
|
name: "opendata-cat",
|
|
16
|
-
version: "
|
|
16
|
+
version: "",
|
|
17
17
|
});
|
|
18
18
|
// Tool 1: search_datasets
|
|
19
|
-
server.tool("search_datasets", "Cerca datasets de dades obertes catalanes per text lliure.
|
|
19
|
+
server.tool("search_datasets", "Cerca datasets de dades obertes catalanes per text lliure. IMPORTANT: fes múltiples cerques amb termes diferents per cobrir un tema ampli. Ex: si l'usuari pregunta per 'emergències', cerca 'bombers', '112 trucades', 'mossos policia', 'SEM ambulància' per separat. La cerca inclou sinònims en català i castellà.", {
|
|
20
20
|
query: z.string().describe("Text de cerca (ex: 'qualitat aire', 'pressupostos')"),
|
|
21
21
|
portal: z.string().optional().describe("Filtrar per portal: 'generalitat', 'barcelona', 'diba', 'aoc', 'reus', 'girona', 'fgc'"),
|
|
22
22
|
category: z.string().optional().describe("Filtrar per categoria"),
|
|
@@ -471,7 +471,7 @@ async function main() {
|
|
|
471
471
|
// Health check
|
|
472
472
|
if (req.url === "/health") {
|
|
473
473
|
res.writeHead(200, { "Content-Type": "application/json" });
|
|
474
|
-
res.end(JSON.stringify({ status: "ok", name: "opendata-cat", version: "
|
|
474
|
+
res.end(JSON.stringify({ status: "ok", name: "opendata-cat", version: "" }));
|
|
475
475
|
return;
|
|
476
476
|
}
|
|
477
477
|
// MCP endpoint
|