@aborruso/ckan-mcp-server 0.4.7 → 0.4.8

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 CHANGED
@@ -74,6 +74,8 @@ Use the public Workers endpoint (no local install required):
74
74
  }
75
75
  ```
76
76
 
77
+ **NOTE**: This service uses the Cloudflare Workers free tier which has a limit of 100,000 requests per month.
78
+
77
79
  Want your own deployment? See [DEPLOYMENT.md](docs/DEPLOYMENT.md).
78
80
 
79
81
  ### Claude Desktop Configuration
@@ -150,6 +152,8 @@ Use the public Cloudflare Workers deployment (no local installation required):
150
152
  }
151
153
  ```
152
154
 
155
+ **NOTE**: This service uses the Cloudflare Workers free tier which has a limit of 100,000 requests per month.
156
+
153
157
  **Note**: This uses the public endpoint. You can also deploy your own Workers instance and use that URL instead.
154
158
 
155
159
  ## Available Tools
package/dist/index.js CHANGED
@@ -411,6 +411,15 @@ ${params.fq ? `**Filter**: ${params.fq}
411
411
  const sorted = Object.entries(facetValues).sort((a, b) => b[1] - a[1]).slice(0, 10);
412
412
  for (const [value, count] of sorted) {
413
413
  markdown += `- **${value}**: ${count}
414
+ `;
415
+ }
416
+ if (Object.keys(facetValues).length > sorted.length) {
417
+ markdown += `
418
+ Note: showing top ${sorted.length} only. Use \`response_format: json\` or increase \`facet_limit\`.
419
+ `;
420
+ } else {
421
+ markdown += `
422
+ Note: showing top ${sorted.length} only. Use \`response_format: json\` for full list.
414
423
  `;
415
424
  }
416
425
  markdown += "\n";
@@ -897,16 +906,84 @@ Returns:
897
906
  content: [{ type: "text", text: markdown2 }]
898
907
  };
899
908
  }
900
- const result = await makeCkanRequest(
901
- params.server_url,
902
- "organization_list",
903
- {
904
- all_fields: params.all_fields,
905
- sort: params.sort,
906
- limit: params.limit,
907
- offset: params.offset
909
+ let result;
910
+ try {
911
+ result = await makeCkanRequest(
912
+ params.server_url,
913
+ "organization_list",
914
+ {
915
+ all_fields: params.all_fields,
916
+ sort: params.sort,
917
+ limit: params.limit,
918
+ offset: params.offset
919
+ }
920
+ );
921
+ } catch (error) {
922
+ const message = error instanceof Error ? error.message : String(error);
923
+ if (message.includes("CKAN API error (500)")) {
924
+ const searchResult = await makeCkanRequest(
925
+ params.server_url,
926
+ "package_search",
927
+ {
928
+ rows: 0,
929
+ "facet.field": JSON.stringify(["organization"]),
930
+ "facet.limit": -1
931
+ }
932
+ );
933
+ const items = searchResult.search_facets?.organization?.items || [];
934
+ const sortValue = params.sort?.toLowerCase() ?? "name asc";
935
+ const sortedItems = [...items].sort((a, b) => {
936
+ if (sortValue.includes("package_count") || sortValue.includes("count")) {
937
+ return b.count - a.count;
938
+ }
939
+ if (sortValue.includes("name desc")) {
940
+ return String(b.name).localeCompare(String(a.name));
941
+ }
942
+ return String(a.name).localeCompare(String(b.name));
943
+ });
944
+ const pagedItems = sortedItems.slice(params.offset, params.offset + params.limit);
945
+ const organizations = pagedItems.map((item) => ({
946
+ id: item.name,
947
+ name: item.name,
948
+ title: item.display_name || item.name,
949
+ package_count: item.count
950
+ }));
951
+ if (params.response_format === "json" /* JSON */) {
952
+ const output = { count: items.length, organizations };
953
+ return {
954
+ content: [{ type: "text", text: truncateText(JSON.stringify(output, null, 2)) }],
955
+ structuredContent: output
956
+ };
957
+ }
958
+ let markdown2 = `# CKAN Organizations
959
+
960
+ `;
961
+ markdown2 += `**Server**: ${params.server_url}
962
+ `;
963
+ markdown2 += `**Total**: ${items.length}
964
+ `;
965
+ markdown2 += `
966
+ Note: organization_list returned 500; using package_search facets.
967
+
968
+ `;
969
+ for (const org of organizations) {
970
+ markdown2 += `## ${org.title || org.name}
971
+
972
+ `;
973
+ markdown2 += `- **Name**: \`${org.name}\`
974
+ `;
975
+ markdown2 += `- **Datasets**: ${org.package_count || 0}
976
+ `;
977
+ markdown2 += `- **Link**: ${getOrganizationViewUrl(params.server_url, org)}
978
+
979
+ `;
980
+ }
981
+ return {
982
+ content: [{ type: "text", text: truncateText(markdown2) }]
983
+ };
908
984
  }
909
- );
985
+ throw error;
986
+ }
910
987
  if (params.response_format === "json" /* JSON */) {
911
988
  const output = Array.isArray(result) ? { count: result.length, organizations: result } : result;
912
989
  return {
@@ -2149,7 +2226,7 @@ function registerAllResources(server2) {
2149
2226
  function createServer() {
2150
2227
  return new McpServer({
2151
2228
  name: "ckan-mcp-server",
2152
- version: "0.4.7"
2229
+ version: "0.4.8"
2153
2230
  });
2154
2231
  }
2155
2232
  function registerAll(server2) {