@aborruso/ckan-mcp-server 0.4.62 → 0.4.64

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/LOG.md CHANGED
@@ -1,9 +1,14 @@
1
1
  # LOG
2
2
 
3
+ ## 2026-03-04 (v0.4.64)
4
+
5
+ - fix(europa): `q=*` now correctly returns all 1.7M+ datasets — Europa API ignores `q` when omitted; sending `q=*` was causing Elasticsearch to return only ~6k results; match-all queries (`*`, `*:*`) now omit the `q` parameter
6
+
3
7
  ## 2026-03-04
4
8
 
5
9
  - feat: expose Europa API facets in `europa_dataset_search` — country, format, categories, and 15 more facet types now rendered as tables (markdown) and compact objects (JSON, top 15 items per facet)
6
10
  - feat: add `is_hvd` boolean filter to `europa_dataset_search` — search only among High Value Datasets
11
+ - refactor: filter Europa facets to 8 useful ones (country, categories, format, is_hvd, scoring, language, subject, hvdCategory), resolve multilingual titles to requested lang, JSON output 52KB→12KB
7
12
  - feat: compact JSON output for heavy tools — `package_search`, `package_show`, `organization_list/show`, `group_list/show`, `datastore_search/search_sql` now return only essential fields in JSON mode (~70% token reduction)
8
13
  - feat: `truncateJson()` — JSON-safe truncation that shrinks arrays instead of cutting mid-string, always produces valid JSON
9
14
  - fix: filter `_id` field from datastore JSON output (already done in markdown)
package/dist/index.js CHANGED
@@ -3991,7 +3991,10 @@ var EUROPA_SEARCH_URL = "https://data.europa.eu/api/hub/search/search";
3991
3991
  async function makeEuropaSearchRequest(params) {
3992
3992
  const isNode = typeof process !== "undefined" && !!process.versions?.node;
3993
3993
  const searchParams = new URLSearchParams();
3994
- searchParams.set("q", params.q);
3994
+ const isMatchAll = !params.q || params.q === "*" || params.q === "*:*";
3995
+ if (!isMatchAll) {
3996
+ searchParams.set("q", params.q);
3997
+ }
3995
3998
  searchParams.set("page", String(params.page ?? 0));
3996
3999
  searchParams.set("limit", String(params.limit ?? 10));
3997
4000
  searchParams.set("filters", "dataset");
@@ -4036,7 +4039,7 @@ async function makeEuropaSearchRequest(params) {
4036
4039
  return {
4037
4040
  count: envelope?.result?.count ?? 0,
4038
4041
  results: envelope?.result?.results ?? [],
4039
- facets: envelope?.result?.facets ?? []
4042
+ rawFacets: envelope?.result?.facets ?? []
4040
4043
  };
4041
4044
  }
4042
4045
 
@@ -4177,6 +4180,34 @@ function renderEuropaSearchMarkdown(results, count, params) {
4177
4180
  return md;
4178
4181
  }
4179
4182
  var MAX_FACET_ITEMS = 15;
4183
+ var ALLOWED_FACETS = /* @__PURE__ */ new Set([
4184
+ "country",
4185
+ "categories",
4186
+ "format",
4187
+ "is_hvd",
4188
+ "scoring",
4189
+ "language",
4190
+ "subject",
4191
+ "hvdCategory"
4192
+ ]);
4193
+ function resolveFacetTitle(title, lang) {
4194
+ if (typeof title === "string") return title;
4195
+ return title[lang] || title["en"] || Object.values(title)[0] || "";
4196
+ }
4197
+ function resolveRawFacets(rawFacets, lang) {
4198
+ const result = [];
4199
+ for (const raw of rawFacets) {
4200
+ if (!ALLOWED_FACETS.has(raw.id)) continue;
4201
+ if (!raw.items || raw.items.length === 0) continue;
4202
+ const items = raw.items.sort((a, b) => b.count - a.count).slice(0, MAX_FACET_ITEMS).map((item) => ({
4203
+ id: item.id,
4204
+ title: resolveFacetTitle(item.title, lang),
4205
+ count: item.count
4206
+ }));
4207
+ result.push({ id: raw.id, title: raw.title, items });
4208
+ }
4209
+ return result;
4210
+ }
4180
4211
  function renderFacetsMarkdown(facets) {
4181
4212
  if (!facets || facets.length === 0) return "";
4182
4213
  let md = `## Facets
@@ -4184,20 +4215,14 @@ function renderFacetsMarkdown(facets) {
4184
4215
  `;
4185
4216
  for (const facet of facets) {
4186
4217
  if (!facet.items || facet.items.length === 0) continue;
4187
- const sorted = [...facet.items].sort((a, b) => b.count - a.count);
4188
- const items = sorted.slice(0, MAX_FACET_ITEMS);
4189
4218
  md += `### ${facet.title || facet.id}
4190
4219
 
4191
4220
  `;
4192
4221
  md += `| Value | Count |
4193
4222
  |---|---:|
4194
4223
  `;
4195
- for (const item of items) {
4224
+ for (const item of facet.items) {
4196
4225
  md += `| ${item.title || item.id} | ${item.count} |
4197
- `;
4198
- }
4199
- if (sorted.length > MAX_FACET_ITEMS) {
4200
- md += `| ... and ${sorted.length - MAX_FACET_ITEMS} more | |
4201
4226
  `;
4202
4227
  }
4203
4228
  md += `
@@ -4209,7 +4234,11 @@ function facetsToCompactJson(facets) {
4209
4234
  const result = {};
4210
4235
  for (const facet of facets) {
4211
4236
  if (!facet.items || facet.items.length === 0) continue;
4212
- result[facet.id] = facet.items.sort((a, b) => b.count - a.count).slice(0, MAX_FACET_ITEMS).map((item) => ({ id: item.id, title: item.title, count: item.count }));
4237
+ result[facet.id] = facet.items.map((item) => ({
4238
+ id: item.id,
4239
+ title: item.title,
4240
+ count: item.count
4241
+ }));
4213
4242
  }
4214
4243
  return result;
4215
4244
  }
@@ -4269,13 +4298,14 @@ Examples:
4269
4298
  if (params.sort && params.sort !== "relevance") {
4270
4299
  sortParam = `${params.sort}+${params.order}`;
4271
4300
  }
4272
- const { count, results, facets } = await makeEuropaSearchRequest({
4301
+ const { count, results, rawFacets } = await makeEuropaSearchRequest({
4273
4302
  q: params.q,
4274
4303
  page: params.page - 1,
4275
4304
  limit: params.page_size,
4276
4305
  facets: Object.keys(filterFacets).length > 0 ? filterFacets : void 0,
4277
4306
  sort: sortParam
4278
4307
  });
4308
+ const facets = resolveRawFacets(rawFacets, params.lang);
4279
4309
  if (params.response_format === "json" /* JSON */) {
4280
4310
  const filtered = results.map((d) => {
4281
4311
  const desc = pickLang(d.description, params.lang);
@@ -4865,7 +4895,7 @@ var registerAllPrompts = (server2) => {
4865
4895
  function createServer() {
4866
4896
  return new McpServer({
4867
4897
  name: "ckan-mcp-server",
4868
- version: "0.4.62"
4898
+ version: "0.4.63"
4869
4899
  });
4870
4900
  }
4871
4901
  function registerAll(server2) {