@aborruso/ckan-mcp-server 0.4.132 → 0.4.133

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/LOG.md +20 -1
  2. package/dist/index.js +28 -14
  3. package/package.json +1 -1
package/LOG.md CHANGED
@@ -1,10 +1,29 @@
1
1
  # LOG
2
2
 
3
+ ## 2026-10-28
4
+
5
+ ### v0.4.133
6
+
7
+ Ships #568. For callers: `ckan_find_portals` works again on the hosted Worker (it failed on every call since at least 2026-09-05); `ckan_status_show` on a site that is not a CKAN API now says so and points at `ckan_find_portals`, instead of telling the caller to call `ckan_status_show`; `open.toronto.ca` works as a server URL in every tool (routed to its CKAN host). Tests 616 passed. Smoke 16/17: same MQA outage as v0.4.132 (per-dataset `/api/mqa/cache/*/{id}` still not answering, `/global` 0.2 s), tagged with `SKIP_RELEASE_GATE=1` on the user's decision.
8
+
9
+ ### Telemetry errors: find_portals fixed on Workers, error messages logged, non-CKAN hints
10
+
11
+ From the error analysis of `worker_events_flat.jsonl` (app errors are logged only since 2026-09-05: 754 of 3,752 calls, 537 of them invalid input from scanners).
12
+
13
+ - `ckan_find_portals` failed on every Worker call (96/96 since 2026-09-05): it was the only tool calling axios directly, and axios's fetch adapter breaks on Workers ("The 'cache' field on 'RequestInitializerDict' is not implemented"). Now uses `safeFetch`, like MQA; SSRF checks on redirects come with it. Checked with `wrangler dev`: 945 portals, about 5 s (the datashades.info list is 22 MB).
14
+ - The worker log line of a failed call now has `error_message` (first 200 chars, one line) and `error_kind` (`validation`, `not_allowed`, `timeout`, `upstream_http`, `unreachable`, `other`, `src/utils/error-telemetry.ts`); the archiver carries both into the flat file. The find_portals failure stayed hidden for weeks because the log only said `error`.
15
+ - `ckan_status_show` on a site that is not the CKAN API (47% failure on real URLs: open.toronto.ca, open.ottawa.ca, data.europa.eu/data, ...) told the caller to call `ckan_status_show`. It now says the site may not run CKAN or keep the API on another host, and points at `ckan_find_portals`. `open.toronto.ca` is routed to its CKAN host `ckan0.cf.opendata.inter.prod-toronto.ca` via `portals.json`.
16
+ - Tests 615 passed (+14, each new test fails without its fix), Python tests 5.
17
+
3
18
  ## 2026-10-27
4
19
 
20
+ ### Archiver: empty result lists for zero-result searches
21
+
22
+ Manual archiver run on a scratchpad copy (7 live events): search fields reach `worker_events_flat.jsonl`, but a zero-result search came in with `result_ids`/`result_names` null, since the Observability API drops empty arrays from `source`. `flatten()` now restores `[]` whenever `result_count` is present, so "0 results" stays distinct from "not a search". Rechecked on a fresh copy: `zzqxkwvnonesiste` → `result_count` 0, lists `[]`. Tests in `tests/python/test_worker_telemetry_archiver.py` (stdlib `unittest`: zero count with omitted lists, non-empty lists, non-search event, field set); the zero-count case fails on the previous `flatten()`. They run in `update-telemetry.yml` before each archiver run (Greptile review).
23
+
5
24
  ### v0.4.132
6
25
 
7
- Ships #565: worker telemetry logs returned search results. Tests 601 passed. Smoke 16/17: the MQA case times out because data.europa.eu `/api/mqa/cache/datasets/{id}` (and its successor `/resources/{id}`) hang for every dataset id tried, while `/global`, `/countries`, `/catalogues/dati-gov-it` answer in 0.2 s; released anyway on the user's decision. The official spec (`openapi.yaml` 6.0.1-SNAPSHOT) marks `/datasets/{id}` deprecated, alias of `/resources/{id}`: switching is a separate change.
26
+ Ships #565: worker telemetry logs returned search results. Tests 601 passed. Smoke 16/17: the MQA case times out because data.europa.eu `/api/mqa/cache/datasets/{id}` (and its successor `/resources/{id}`) hang for every dataset id tried, while `/global`, `/countries`, `/catalogues/dati-gov-it` answer in 0.2 s; released anyway on the user's decision. Live on npm (provenance), the MCP Registry (`isLatest`), the Worker (`/health` 0.4.132) and the GitHub release (DXT + skill attached). Observability API checked read-only: `result_ids` arrives as a list and `flatten()` maps it. The official spec (`openapi.yaml` 6.0.1-SNAPSHOT) marks `/datasets/{id}` deprecated, alias of `/resources/{id}`: switching is a separate change.
8
27
 
9
28
  ### Worker telemetry: returned search results
10
29
 
package/dist/index.js CHANGED
@@ -96,6 +96,16 @@ var portals_default = {
96
96
  "http://open.canada.ca"
97
97
  ]
98
98
  },
99
+ {
100
+ id: "open-toronto",
101
+ name: "open.toronto.ca",
102
+ api_url: "https://ckan0.cf.opendata.inter.prod-toronto.ca",
103
+ api_url_aliases: [
104
+ "https://open.toronto.ca",
105
+ "http://open.toronto.ca"
106
+ ],
107
+ dataset_view_url: "https://open.toronto.ca/dataset/{name}/"
108
+ },
99
109
  {
100
110
  id: "data-gov-au",
101
111
  name: "data.gov.au",
@@ -3648,14 +3658,15 @@ Typical workflow: ckan_status_show (verify server is up) \u2192 ckan_package_sea
3648
3658
  structuredContent: cappedStructured(result)
3649
3659
  };
3650
3660
  } catch (error) {
3651
- const migrated = error instanceof CkanApiError && error.serverUrl && getPortalMigration(error.serverUrl);
3652
- const detail = formatCkanError(error, "ckan_status_show");
3661
+ const migrated = (error instanceof CkanApiError || error instanceof CkanTransportError) && error.serverUrl && getPortalMigration(error.serverUrl);
3662
+ if (migrated) {
3663
+ return { content: [{ type: "text", text: formatCkanError(error, "ckan_status_show") }], isError: true };
3664
+ }
3665
+ const detail = error instanceof CkanApiError || error instanceof CkanTransportError ? `${error.message}
3666
+ \u2192 No CKAN API answered at this address. The site may be up but not run CKAN, or keep its CKAN API on another host. Use \`ckan_find_portals\` to look up the portal's CKAN API URL; retry later only if this address usually works.` : formatCkanError(error, "ckan_status_show");
3653
3667
  return {
3654
- content: [{
3655
- type: "text",
3656
- text: migrated ? detail : `Server appears to be offline or not a valid CKAN instance:
3657
- ${detail}`
3658
- }],
3668
+ content: [{ type: "text", text: `Server appears to be offline or not a valid CKAN instance:
3669
+ ${detail}` }],
3659
3670
  isError: true
3660
3671
  };
3661
3672
  }
@@ -5407,14 +5418,17 @@ ${error instanceof Error ? error.message : String(error)}`;
5407
5418
 
5408
5419
  // src/tools/portal-discovery.ts
5409
5420
  import { z as z11 } from "zod";
5410
- import axios2 from "axios";
5411
5421
  var DATASHADES_URL = "https://datashades.info/api/portal/list";
5412
5422
  async function fetchPortals() {
5413
- const resp = await axios2.get(DATASHADES_URL, {
5414
- timeout: 15e3,
5415
- headers: { "User-Agent": "CKAN-MCP-Server/1.0" }
5416
- });
5417
- return resp.data.portals;
5423
+ const resp = await safeFetch(DATASHADES_URL, {
5424
+ headers: { "User-Agent": "CKAN-MCP-Server/1.0" },
5425
+ signal: AbortSignal.timeout(15e3)
5426
+ }, { httpsOnly: true });
5427
+ if (!resp.ok) {
5428
+ throw new Error(`datashades.info returned ${resp.status} ${resp.statusText}`);
5429
+ }
5430
+ const data = await resp.json();
5431
+ return data.portals;
5418
5432
  }
5419
5433
  function deduplicateByHostname(portals) {
5420
5434
  const seen = /* @__PURE__ */ new Map();
@@ -6142,7 +6156,7 @@ var registerAllPrompts = (server) => {
6142
6156
  function createServer() {
6143
6157
  return new McpServer({
6144
6158
  name: "ckan-mcp-server",
6145
- version: "0.4.132"
6159
+ version: "0.4.133"
6146
6160
  });
6147
6161
  }
6148
6162
  function registerAll(server) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aborruso/ckan-mcp-server",
3
- "version": "0.4.132",
3
+ "version": "0.4.133",
4
4
  "mcpName": "io.github.aborruso/ckan-mcp-server",
5
5
  "description": "MCP server for interacting with CKAN open data portals",
6
6
  "repository": {