@opendata.cat/mcp-server 0.0.10 → 0.0.12

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.
Files changed (3) hide show
  1. package/README.md +55 -11
  2. package/dist/index.js +263 -2
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -12,7 +12,7 @@
12
12
 
13
13
  # Opendata.cat MCP Server
14
14
 
15
- Servidor [MCP](https://modelcontextprotocol.io/) (Model Context Protocol) que connecta els models de llenguatge (Claude, ChatGPT, Gemini...) amb les **dades obertes publiques de Catalunya**. Cerca datasets, explora metadades i consulta dades reals de la Generalitat, l'Ajuntament de Barcelona i la Diputacio de Barcelona directament des del teu assistent d'IA.
15
+ Servidor [MCP](https://modelcontextprotocol.io/) (Model Context Protocol) que connecta els models de llenguatge (Claude, ChatGPT, Gemini...) amb les **dades obertes publiques de Catalunya**. Cerca datasets, explora metadades i consulta dades reals de 7 portals catalans directament des del teu assistent d'IA.
16
16
 
17
17
  Un projecte d'**[opendata.cat](https://opendata.cat)** — associacio sense anim de lucre fundada el 2012 que promou la transparencia, la difusio i l'estandarditzacio de les dades obertes a Catalunya. Inspirat en el projecte [datagouv-mcp](https://github.com/datagouv/datagouv-mcp) del govern frances.
18
18
 
@@ -26,18 +26,20 @@ Un projecte d'**[opendata.cat](https://opendata.cat)** — associacio sense anim
26
26
  | [Consorci AOC](https://dadesobertes.seu-e.cat) | ~893 | CKAN datastore |
27
27
  | [Ajuntament de Reus](https://opendata.reus.cat) | 119 | CKAN datastore |
28
28
  | [Ajuntament de Girona](https://www.girona.cat/opendata/) | 53 | CKAN datastore |
29
+ | [FGC (Ferrocarrils)](https://dadesobertes.fgc.cat) | 50 | Opendatasoft |
29
30
 
30
31
  El Consorci AOC inclou datasets de les **diputacions de Tarragona, Girona i Lleida**, ajuntaments, consells comarcals i altres organismes publics catalans.
31
32
 
32
- **+2.700 datasets** de 6 portals. La majoria queryables amb filtres, cerca i paginacio.
33
+ **+2.800 datasets** de 7 portals. La majoria queryables amb filtres, cerca i paginacio.
33
34
 
34
35
  El cataleg s'actualitza automaticament cada setmana. Cada endpoint es valida per assegurar que funciona.
35
36
 
36
37
  **Tipus d'acces:**
37
38
  - **Socrata**: consulta SoQL amb filtres i cerca (Generalitat)
38
- - **CKAN**: datastore_search amb filtres i cerca (Barcelona, AOC)
39
+ - **CKAN**: datastore_search amb filtres i cerca (Barcelona, AOC, Reus, Girona)
39
40
  - **Diba REST**: API do.diba.cat amb paginacio i filtres (Diputacio BCN)
40
41
  - **CIDO JSON:API**: api.diba.cat per contractacions, normatives, subvencions, oposicions, convenis (Diputacio BCN)
42
+ - **Opendatasoft**: API records amb filtres i cerca (FGC — horaris GTFS, trens temps real, estacions esqui)
41
43
  - **File download**: descarrega directa de CSV, JSON, XLSX o fitxers GIS
42
44
  - **Restricted**: requereix token d'autenticacio (4 datasets BSM)
43
45
 
@@ -89,6 +91,7 @@ Afegeix al fitxer `.vscode/mcp.json` del teu projecte:
89
91
  | `query_dataset` | Consulta dades reals directament al portal origen |
90
92
  | `list_portals` | Llista els portals disponibles amb estadistiques |
91
93
  | `list_categories` | Llista categories i temes disponibles amb comptadors |
94
+ | `related_datasets` | Retorna datasets relacionats d'altres portals |
92
95
 
93
96
  ### search_datasets
94
97
 
@@ -96,7 +99,7 @@ Cerca datasets per text lliure.
96
99
 
97
100
  ```
98
101
  query: "qualitat aire"
99
- portal: "barcelona" # opcional: generalitat, barcelona, diba
102
+ portal: "barcelona" # opcional: generalitat, barcelona, diba, aoc, reus, girona, fgc
100
103
  category: "Medi Ambient" # opcional
101
104
  limit: 20 # opcional (defecte: 20)
102
105
  ```
@@ -137,17 +140,45 @@ Llista els portals disponibles amb el nombre de datasets de cadascun. No requere
137
140
 
138
141
  Llista totes les categories i temes de datasets disponibles amb comptadors per portal. Ideal per descobrir quins tipus de dades hi ha.
139
142
 
143
+ ## Prompts disponibles
144
+
145
+ Prompts predefinits que guien l'LLM pas a pas per fer analisis completes:
146
+
147
+ | Prompt | Descripcio | Arguments |
148
+ |--------|-----------|-----------|
149
+ | `estat_embassaments` | Estat actual dels embassaments amb grafiques d'evolucio | — |
150
+ | `trens_fgc_temps_real` | Retards, alertes i posicions dels trens FGC en temps real | — |
151
+ | `qualitat_aire` | Analisi de la qualitat de l'aire amb comparativa OMS/UE | `lloc` (opcional) |
152
+ | `accidents_transit` | Analisi d'accidents de transit amb punts negres i tendencies | `municipi` (opcional) |
153
+ | `pressupostos_municipals` | Pressupostos municipals amb desglossament per partides | `municipi` (opcional) |
154
+ | `compara_municipis` | Compara dos municipis en totes les dades disponibles | `municipi_a`, `municipi_b` |
155
+ | `descobreix_dades` | Mapa complet de dades obertes sobre un tema | `tema` |
156
+ | `analisi_bombers` | Actuacions dels Bombers: emergencies, distribucio, tendencies | `comarca` (opcional) |
157
+ | `novetats` | Datasets actualitzats mes recentment | `portal` (opcional) |
158
+ | `datasets_populars` | Datasets mes consultats pels usuaris | — |
159
+ | `explorar_portal` | Guia completa d'un portal: categories, exemples, destacats | `portal` |
160
+ | `dades_municipi` | Fitxa completa d'un municipi amb totes les dades disponibles | `municipi` |
161
+ | `datasets_temps_real` | Datasets amb dades en temps real o actualitzacio frequent | — |
162
+ | `resum_portals` | Visio panoramica de tots els portals de dades obertes | — |
163
+
140
164
  ## Exemples d'us
141
165
 
142
166
  Un cop configurat, pots fer preguntes al teu LLM com:
143
167
 
144
- - *"Quins datasets hi ha sobre mobilitat a Barcelona?"*
145
- - *"Mostra'm les dades de qualitat de l'aire d'ahir"*
146
- - *"Quants equipaments culturals te Girona?"*
147
- - *"Dona'm les ultimes dades de pressupostos municipals"*
148
- - *"Quin es l'estat dels embassaments de Catalunya?"*
149
- - *"Quines dades obertes hi ha sobre educacio a Catalunya?"*
150
- - *"Quins tipus de dades teniu disponibles?"*
168
+ - *"Quin es l'estat dels embassaments de Catalunya?"* → prompt `estat_embassaments`
169
+ - *"Hi ha algun tren de FGC amb retard ara mateix?"* → prompt `trens_fgc_temps_real`
170
+ - *"Analitza la qualitat de l'aire a Terrassa"* → prompt `qualitat_aire`
171
+ - *"Fes unes grafiques amb l'evolucio dels accidents de transit a Barcelona"* → prompt `accidents_transit`
172
+ - *"Compara Girona i Tarragona en dades obertes"* → prompt `compara_municipis`
173
+ - *"Quines dades obertes hi ha sobre educacio a Catalunya?"* → prompt `descobreix_dades`
174
+ - *"Dona'm les ultimes dades de pressupostos de Reus"* → prompt `pressupostos_municipals`
175
+ - *"Analitza les actuacions dels Bombers al Valles"* → prompt `analisi_bombers`
176
+ - *"Quines novetats hi ha en dades obertes?"* → prompt `novetats`
177
+ - *"Quins son els datasets mes consultats?"* → prompt `datasets_populars`
178
+ - *"Explora'm el portal de la Generalitat"* → prompt `explorar_portal`
179
+ - *"Quines dades obertes te Sabadell?"* → prompt `dades_municipi`
180
+ - *"Quines dades en temps real hi ha?"* → prompt `datasets_temps_real`
181
+ - *"Dona'm un resum de tots els portals"* → prompt `resum_portals`
151
182
 
152
183
  ## Com funciona
153
184
 
@@ -175,6 +206,19 @@ Les contribucions son benvingudes! Per afegir un nou portal de dades obertes:
175
206
 
176
207
  ## Changelog
177
208
 
209
+ ### v0.0.12 (2026-04-13)
210
+ - 14 prompts predefinits (8 analisi + 6 descobriment)
211
+ - Nous prompts: novetats, datasets_populars, explorar_portal, dades_municipi, datasets_temps_real, resum_portals
212
+ - Crawler incremental: UPSERT en lloc de TRUNCATE, no perd dades si un portal falla
213
+ - Backup automatic despres de cada carrega
214
+
215
+ ### v0.0.10 (2026-04-13)
216
+ - Afegeix portal FGC (Ferrocarrils de la Generalitat de Catalunya) — 50 datasets via Opendatasoft
217
+ - Nou client Opendatasoft per consultar dades de transport, esqui, meteorologia, GTFS
218
+ - list_portals ara llista els 7 portals (abans nomes 3)
219
+ - Fix seguretat: validacio de claus de filtre SoQL contra injeccio
220
+ - Cobertura total: ~2.800 datasets de 7 portals
221
+
178
222
  ### v0.0.7 (2026-04-13)
179
223
  - Afegeix portal Consorci AOC (~893 datasets de diputacions, ajuntaments, consells comarcals)
180
224
  - Cobertura total: ~2.600 datasets, ~2.400 queryables
package/dist/index.js CHANGED
@@ -12,7 +12,7 @@ import { queryCido } from "./clients/cido.js";
12
12
  import { queryOpendatasoft } from "./clients/opendatasoft.js";
13
13
  const server = new McpServer({
14
14
  name: "opendata-cat",
15
- version: "0.0.10",
15
+ version: "0.0.12",
16
16
  });
17
17
  // Tool 1: search_datasets
18
18
  server.tool("search_datasets", "Cerca datasets de dades obertes catalanes per text lliure. Retorna nom, descripció, portal i formats.", {
@@ -172,6 +172,267 @@ server.tool("related_datasets", "Retorna datasets relacionats d'ALTRES portals.
172
172
  }],
173
173
  };
174
174
  });
175
+ // ===== PROMPTS =====
176
+ server.prompt("estat_embassaments", "Analitza l'estat actual dels embassaments de Catalunya amb gràfiques d'evolució.", () => ({
177
+ messages: [{
178
+ role: "user",
179
+ content: {
180
+ type: "text",
181
+ text: "Consulta l'estat actual dels embassaments de les Conques Internes de Catalunya.\n\n"
182
+ + "1. Usa search_datasets amb 'embassament' per trobar el dataset rellevant\n"
183
+ + "2. Usa query_dataset per obtenir les últimes dades\n"
184
+ + "3. Presenta una taula amb cada embassament: nom, volum actual (hm³), percentatge ple, i variació\n"
185
+ + "4. Genera un gràfic ASCII o Markdown amb l'evolució dels nivells\n"
186
+ + "5. Destaca embassaments en situació crítica (< 40%) i els que estan millor\n"
187
+ + "6. Compara amb el dataset d'estat de sequera si n'hi ha\n\n"
188
+ + "Mostra les dades de forma visual i fàcil d'entendre.",
189
+ },
190
+ }],
191
+ }));
192
+ server.prompt("trens_fgc_temps_real", "Consulta l'estat dels trens de FGC en temps real: retards, alertes i posicions.", () => ({
193
+ messages: [{
194
+ role: "user",
195
+ content: {
196
+ type: "text",
197
+ text: "Consulta l'estat en temps real dels trens de Ferrocarrils de la Generalitat de Catalunya (FGC).\n\n"
198
+ + "1. Usa search_datasets amb portal 'fgc' per trobar els datasets GTFS Realtime\n"
199
+ + "2. Consulta 'trip-updates' per veure retards actuals\n"
200
+ + "3. Consulta 'vehicle-positions' per veure on són els trens\n"
201
+ + "4. Consulta 'alerts' per veure si hi ha alertes de servei\n\n"
202
+ + "Presenta un resum clar:\n"
203
+ + "- Trens amb retard (quants minuts, quina línia)\n"
204
+ + "- Alertes actives de servei\n"
205
+ + "- Estat general: normal / amb incidències / interromput",
206
+ },
207
+ }],
208
+ }));
209
+ server.prompt("qualitat_aire", "Analitza la qualitat de l'aire a una estació o municipi de Catalunya.", { lloc: z.string().optional().describe("Nom del municipi o estació (ex: 'Barcelona', 'Sabadell')") }, ({ lloc }) => {
210
+ const filtreText = lloc ? ` a ${lloc}` : " a les principals estacions";
211
+ return {
212
+ messages: [{
213
+ role: "user",
214
+ content: {
215
+ type: "text",
216
+ text: `Analitza la qualitat de l'aire${filtreText}.\n\n`
217
+ + "1. Usa search_datasets amb 'qualitat aire contaminació' per trobar els datasets rellevants\n"
218
+ + "2. Consulta les últimes mesures disponibles"
219
+ + (lloc ? ` filtrant per '${lloc}'` : "") + "\n"
220
+ + "3. Presenta els nivells de: NO₂, PM10, PM2.5, O₃, SO₂ (els que hi hagi)\n"
221
+ + "4. Compara amb els llindars de l'OMS i la normativa UE\n"
222
+ + "5. Dona una valoració global: bona / acceptable / dolenta / molt dolenta\n"
223
+ + "6. Si hi ha dades històriques, mostra la tendència recent\n\n"
224
+ + "Usa taules i indicadors visuals per fer-ho entenedor.",
225
+ },
226
+ }],
227
+ };
228
+ });
229
+ server.prompt("accidents_transit", "Analitza les dades d'accidents de trànsit a Catalunya o a un municipi concret.", { municipi: z.string().optional().describe("Nom del municipi (ex: 'Barcelona', 'Hospitalet')") }, ({ municipi }) => {
230
+ const filtreText = municipi ? ` a ${municipi}` : " a Catalunya";
231
+ return {
232
+ messages: [{
233
+ role: "user",
234
+ content: {
235
+ type: "text",
236
+ text: `Analitza les dades d'accidents de trànsit${filtreText}.\n\n`
237
+ + "1. Usa search_datasets amb 'accidents trànsit" + (municipi ? ` ${municipi}` : "") + "'\n"
238
+ + "2. Consulta les dades més recents\n"
239
+ + "3. Presenta: nombre total d'accidents, distribució per gravetat (mortals, ferits greus, lleus)\n"
240
+ + "4. Si hi ha dades geolocalitzades, identifica els punts negres\n"
241
+ + "5. Analitza tendències: augmenten o disminueixen?\n"
242
+ + "6. Busca datasets relacionats amb related_datasets per completar l'anàlisi\n\n"
243
+ + "Presenta conclusions clares amb dades concretes.",
244
+ },
245
+ }],
246
+ };
247
+ });
248
+ server.prompt("pressupostos_municipals", "Explora i compara els pressupostos municipals d'ajuntaments catalans.", { municipi: z.string().optional().describe("Nom del municipi") }, ({ municipi }) => {
249
+ const filtreText = municipi ? ` de ${municipi}` : "";
250
+ return {
251
+ messages: [{
252
+ role: "user",
253
+ content: {
254
+ type: "text",
255
+ text: `Explora els pressupostos municipals${filtreText}.\n\n`
256
+ + "1. Usa search_datasets amb 'pressupost" + (municipi ? ` ${municipi}` : " municipal") + "'\n"
257
+ + "2. Consulta les últimes dades de pressupost disponibles\n"
258
+ + "3. Desglossa: ingressos vs despeses, partides principals\n"
259
+ + "4. Si hi ha dades multi-any, mostra l'evolució\n"
260
+ + "5. Destaca les partides més grans i les variacions significatives\n\n"
261
+ + "Presenta les xifres en format comprensible (milions €) amb taules.",
262
+ },
263
+ }],
264
+ };
265
+ });
266
+ server.prompt("compara_municipis", "Compara dos municipis catalans en totes les dades obertes disponibles.", {
267
+ municipi_a: z.string().describe("Primer municipi"),
268
+ municipi_b: z.string().describe("Segon municipi"),
269
+ }, ({ municipi_a, municipi_b }) => ({
270
+ messages: [{
271
+ role: "user",
272
+ content: {
273
+ type: "text",
274
+ text: `Compara els municipis de ${municipi_a} i ${municipi_b} amb totes les dades obertes disponibles.\n\n`
275
+ + `1. Usa search_datasets per trobar datasets que incloguin '${municipi_a}'\n`
276
+ + `2. Usa search_datasets per trobar datasets que incloguin '${municipi_b}'\n`
277
+ + "3. Per cada tema comú (població, pressupost, equipaments, transport...), consulta les dades dels dos municipis\n"
278
+ + "4. Presenta una taula comparativa amb les dades clau\n"
279
+ + "5. Destaca les diferències més significatives\n\n"
280
+ + "Organitza la comparativa per temes i indica la font de cada dada.",
281
+ },
282
+ }],
283
+ }));
284
+ server.prompt("descobreix_dades", "Explora quines dades obertes hi ha disponibles sobre un tema a Catalunya.", { tema: z.string().describe("Tema a explorar (ex: 'educació', 'medi ambient', 'turisme')") }, ({ tema }) => ({
285
+ messages: [{
286
+ role: "user",
287
+ content: {
288
+ type: "text",
289
+ text: `Explora totes les dades obertes disponibles sobre '${tema}' a Catalunya.\n\n`
290
+ + `1. Usa search_datasets amb '${tema}' (limit: 50)\n`
291
+ + "2. Agrupa els resultats per portal i categoria\n"
292
+ + "3. Per als 3-5 datasets més rellevants, usa get_dataset_info per mostrar detalls (camps, tipus, actualització)\n"
293
+ + "4. Usa related_datasets per descobrir dades complementàries\n"
294
+ + "5. Suggereix 3 anàlisis interessants que es podrien fer creuant aquests datasets\n\n"
295
+ + "L'objectiu és donar un mapa complet de quines dades existeixen i què es pot fer amb elles.",
296
+ },
297
+ }],
298
+ }));
299
+ server.prompt("analisi_bombers", "Analitza les actuacions dels Bombers de la Generalitat: tipus d'emergències, distribució territorial i tendències.", { comarca: z.string().optional().describe("Filtrar per comarca (ex: 'Barcelonès', 'Vallès Occidental')") }, ({ comarca }) => {
300
+ const filtreText = comarca ? ` a la comarca de ${comarca}` : "";
301
+ return {
302
+ messages: [{
303
+ role: "user",
304
+ content: {
305
+ type: "text",
306
+ text: `Analitza les actuacions dels Bombers de la Generalitat${filtreText}.\n\n`
307
+ + "1. Usa search_datasets amb 'bombers actuacions emergències'\n"
308
+ + "2. Consulta els datasets d'actuacions, GRAF i EAIC\n"
309
+ + "3. Presenta: nombre total d'actuacions, distribució per tipus (incendis, rescats, inundacions...)\n"
310
+ + "4. Si hi ha dades temporals, mostra estacionalitat (estiu = incendis?)\n"
311
+ + "5. Identifica les zones amb més actuacions\n"
312
+ + (comarca ? `6. Filtra específicament per la comarca de ${comarca}\n` : "")
313
+ + "\nFes una anàlisi visual amb taules i percentatges.",
314
+ },
315
+ }],
316
+ };
317
+ });
318
+ // ===== PROMPTS DE DESCOBRIMENT =====
319
+ server.prompt("novetats", "Mostra els datasets actualitzats més recentment als portals de dades obertes de Catalunya.", { portal: z.string().optional().describe("Filtrar per portal: generalitat, barcelona, diba, aoc, reus, girona, fgc") }, ({ portal }) => {
320
+ const filtreText = portal ? ` al portal ${portal}` : "";
321
+ return {
322
+ messages: [{
323
+ role: "user",
324
+ content: {
325
+ type: "text",
326
+ text: `Mostra els datasets de dades obertes de Catalunya actualitzats més recentment${filtreText}.\n\n`
327
+ + "1. Usa list_portals per veure els portals disponibles\n"
328
+ + `2. Usa search_datasets amb termes generals${portal ? ` i portal '${portal}'` : ""} per obtenir datasets\n`
329
+ + "3. Per als primers 10 resultats, usa get_dataset_info per veure la data d'última actualització (last_updated)\n"
330
+ + "4. Ordena per data d'actualització (més recent primer)\n"
331
+ + "5. Presenta una taula amb: nom, portal, categoria, última actualització, formats\n"
332
+ + "6. Destaca els que s'han actualitzat en els últims 7 dies\n\n"
333
+ + "L'objectiu és descobrir quines dades es mantenen actives i actualitzades.",
334
+ },
335
+ }],
336
+ };
337
+ });
338
+ server.prompt("datasets_populars", "Mostra els datasets més consultats pels usuaris del MCP.", () => ({
339
+ messages: [{
340
+ role: "user",
341
+ content: {
342
+ type: "text",
343
+ text: "Mostra els datasets de dades obertes de Catalunya més consultats pels usuaris.\n\n"
344
+ + "1. Usa search_datasets amb termes populars: 'embassament', 'qualitat aire', 'transport', 'pressupost', 'població'\n"
345
+ + "2. Per cada cerca, agafa el primer resultat i usa get_dataset_info per obtenir detalls\n"
346
+ + "3. Presenta un rànquing dels datasets més rellevants amb:\n"
347
+ + " - Nom i portal\n"
348
+ + " - Descripció breu\n"
349
+ + " - Camps disponibles\n"
350
+ + " - Última actualització\n"
351
+ + "4. Per al top 3, fes una consulta amb query_dataset (limit: 3) per mostrar una mostra de dades reals\n"
352
+ + "5. Suggereix preguntes interessants que es podrien fer a cada dataset\n\n"
353
+ + "L'objectiu és inspirar l'usuari amb les possibilitats de les dades obertes.",
354
+ },
355
+ }],
356
+ }));
357
+ server.prompt("explorar_portal", "Explora un portal de dades obertes: quants datasets té, categories, exemples de cada tipus.", { portal: z.string().describe("Portal a explorar: generalitat, barcelona, diba, aoc, reus, girona, fgc") }, ({ portal }) => ({
358
+ messages: [{
359
+ role: "user",
360
+ content: {
361
+ type: "text",
362
+ text: `Fes una exploració completa del portal de dades obertes '${portal}'.\n\n`
363
+ + "1. Usa list_portals per obtenir el nombre total de datasets\n"
364
+ + "2. Usa list_categories per veure les categories disponibles al portal\n"
365
+ + `3. Usa search_datasets amb portal '${portal}' i limit 50 per veure tots els datasets\n`
366
+ + "4. Agrupa-los per categoria i presenta una taula resum\n"
367
+ + "5. Per a cada categoria, tria el dataset més interessant i usa get_dataset_info per mostrar-ne els camps\n"
368
+ + "6. Destaca:\n"
369
+ + " - Datasets amb dades en temps real o actualització freqüent\n"
370
+ + " - Datasets amb molts camps (rics en dades)\n"
371
+ + " - Datasets únics que no es troben a altres portals\n\n"
372
+ + "Presenta el portal com una guia completa per a un nou usuari.",
373
+ },
374
+ }],
375
+ }));
376
+ server.prompt("dades_municipi", "Descobreix totes les dades obertes disponibles sobre un municipi concret de Catalunya.", { municipi: z.string().describe("Nom del municipi (ex: 'Sabadell', 'Girona', 'Manresa')") }, ({ municipi }) => ({
377
+ messages: [{
378
+ role: "user",
379
+ content: {
380
+ type: "text",
381
+ text: `Descobreix totes les dades obertes disponibles sobre el municipi de ${municipi}.\n\n`
382
+ + `1. Usa search_datasets amb '${municipi}' (limit: 50) per trobar tots els datasets\n`
383
+ + "2. Agrupa per portal i categoria\n"
384
+ + "3. Per als datasets més rellevants, usa get_dataset_info per veure detalls\n"
385
+ + "4. Fes query_dataset (limit: 3) als 2-3 datasets més interessants per mostrar dades reals\n"
386
+ + "5. Usa related_datasets per trobar dades complementàries d'altres portals\n"
387
+ + "6. Presenta un resum en format fitxa municipal:\n"
388
+ + " - Població (si hi ha dades)\n"
389
+ + " - Pressupost (si hi ha dades)\n"
390
+ + " - Equipaments, transport, medi ambient...\n"
391
+ + ` - Què falta: quins temes no tenen dades obertes\n\n`
392
+ + `L'objectiu és donar un retrat complet de ${municipi} a través de les dades obertes.`,
393
+ },
394
+ }],
395
+ }));
396
+ server.prompt("datasets_temps_real", "Llista els datasets que ofereixen dades en temps real o actualització freqüent.", () => ({
397
+ messages: [{
398
+ role: "user",
399
+ content: {
400
+ type: "text",
401
+ text: "Descobreix quins datasets de dades obertes de Catalunya ofereixen dades en temps real o actualització molt freqüent.\n\n"
402
+ + "1. Usa search_datasets amb termes com 'temps real', 'GTFS', 'realtime' per trobar datasets en viu\n"
403
+ + "2. Usa search_datasets amb portal 'fgc' per trobar dades de transport en temps real\n"
404
+ + "3. Usa search_datasets amb 'qualitat aire estacions' per trobar mesures en directe\n"
405
+ + "4. Usa search_datasets amb 'embassament' i 'cabal' per trobar dades hídriques en viu\n"
406
+ + "5. Per cada dataset trobat, usa get_dataset_info per verificar la freqüència d'actualització\n"
407
+ + "6. Presenta una llista organitzada per tema:\n"
408
+ + " - Transport: trens FGC, trànsit, bicing...\n"
409
+ + " - Medi ambient: aire, aigua, meteorologia...\n"
410
+ + " - Altres en temps real\n"
411
+ + "7. Per als 3 més interessants, fes query_dataset per mostrar les últimes dades\n\n"
412
+ + "L'objectiu és que l'usuari sàpiga quines dades pot consultar 'ara mateix'.",
413
+ },
414
+ }],
415
+ }));
416
+ server.prompt("resum_portals", "Resum general de tots els portals: quants datasets, quins temes, quins formats.", () => ({
417
+ messages: [{
418
+ role: "user",
419
+ content: {
420
+ type: "text",
421
+ text: "Fes un resum complet de tots els portals de dades obertes de Catalunya.\n\n"
422
+ + "1. Usa list_portals per obtenir la llista amb comptadors\n"
423
+ + "2. Usa list_categories per veure les categories de cada portal\n"
424
+ + "3. Presenta una taula comparativa:\n"
425
+ + " - Nom del portal, URL, nombre de datasets\n"
426
+ + " - Tipus d'API (Socrata, CKAN, REST, Opendatasoft)\n"
427
+ + " - Categories principals\n"
428
+ + " - Tipus de dades destacades\n"
429
+ + "4. Per cada portal, destaca el dataset més singular o interessant\n"
430
+ + "5. Indica quins portals tenen dades en temps real\n"
431
+ + "6. Suggereix per a cada portal una pregunta interessant que es podria respondre amb les seves dades\n\n"
432
+ + "L'objectiu és donar una visió panoràmica de l'ecosistema de dades obertes català.",
433
+ },
434
+ }],
435
+ }));
175
436
  async function main() {
176
437
  const mode = process.argv.includes("--http") ? "http" : "stdio";
177
438
  const port = parseInt(process.env.MCP_PORT || "3100", 10);
@@ -190,7 +451,7 @@ async function main() {
190
451
  // Health check
191
452
  if (req.url === "/health") {
192
453
  res.writeHead(200, { "Content-Type": "application/json" });
193
- res.end(JSON.stringify({ status: "ok", name: "opendata-cat", version: "0.0.10" }));
454
+ res.end(JSON.stringify({ status: "ok", name: "opendata-cat", version: "0.0.12" }));
194
455
  return;
195
456
  }
196
457
  // MCP endpoint
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.0.10",
6
+ "version": "0.0.12",
7
7
  "description": "Servidor MCP per consultar les dades obertes públiques de Catalunya",
8
8
  "type": "module",
9
9
  "main": "dist/index.js",