@aborruso/ckan-mcp-server 0.4.93 → 0.4.95
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 +12 -0
- package/dist/index.js +22 -3
- package/dist/worker.js +2 -2
- package/package.json +1 -1
package/LOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# LOG
|
|
2
2
|
|
|
3
|
+
## 2026-03-26
|
|
4
|
+
|
|
5
|
+
### v0.4.95
|
|
6
|
+
|
|
7
|
+
- Show `Portal Locale` (`locale_default`) in `ckan_status_show` markdown output
|
|
8
|
+
- Add query language hint to `ckan_package_search` description: check locale before searching
|
|
9
|
+
- Update skill query construction rule: dynamic locale check via `ckan_status_show` instead of hardcoded portal table
|
|
10
|
+
|
|
11
|
+
### v0.4.94
|
|
12
|
+
|
|
13
|
+
- Add `data.gov.ua` (Ukraine open data portal) to `portals.json` with explicit `force_text_field: false` to prevent auto-detection from incorrectly wrapping Solr queries in `text:(...)`, which caused 0 results
|
|
14
|
+
|
|
3
15
|
## 2026-03-24
|
|
4
16
|
|
|
5
17
|
### v0.4.93
|
package/dist/index.js
CHANGED
|
@@ -141,6 +141,17 @@ var portals_default = {
|
|
|
141
141
|
],
|
|
142
142
|
organization_view_url: "https://ckan-prod.zurich.datopian.com/organization/{name}"
|
|
143
143
|
},
|
|
144
|
+
{
|
|
145
|
+
id: "data-gov-ua",
|
|
146
|
+
name: "data.gov.ua",
|
|
147
|
+
api_url: "https://data.gov.ua",
|
|
148
|
+
api_url_aliases: [
|
|
149
|
+
"http://data.gov.ua"
|
|
150
|
+
],
|
|
151
|
+
search: {
|
|
152
|
+
force_text_field: false
|
|
153
|
+
}
|
|
154
|
+
},
|
|
144
155
|
{
|
|
145
156
|
id: "govdata-de",
|
|
146
157
|
name: "govdata.de",
|
|
@@ -1215,7 +1226,13 @@ Examples:
|
|
|
1215
1226
|
- Filter extras OR (correct): { fq: "extras_hvd_category:("http://data.europa.eu/bna/c_ac64a52d" OR "http://data.europa.eu/bna/c_dd313021")" }
|
|
1216
1227
|
- Get facets: { facet_field: ["organization"], rows: 0 }
|
|
1217
1228
|
|
|
1218
|
-
|
|
1229
|
+
Query language:
|
|
1230
|
+
Before searching a portal, check its locale via ckan_status_show (field: "Portal Locale" / locale_default).
|
|
1231
|
+
Translate query terms to the portal's language \u2014 searching in English on a non-English portal returns 0 results.
|
|
1232
|
+
Examples: locale "it" \u2192 Italian terms; "uk_UA" \u2192 Ukrainian (Cyrillic); "fr_FR" \u2192 French.
|
|
1233
|
+
Exception: multilingual portals (e.g. data.europa.eu, open.canada.ca) accept EN + native terms joined with OR.
|
|
1234
|
+
|
|
1235
|
+
Typical workflow: ckan_status_show (check locale) \u2192 ckan_package_search (query in portal's language) \u2192 ckan_package_show (get full metadata + resource IDs) \u2192 ckan_datastore_search (query tabular data)`,
|
|
1219
1236
|
inputSchema: z2.object({
|
|
1220
1237
|
server_url: z2.string().url("Must be a valid URL").describe("Base URL of the CKAN server"),
|
|
1221
1238
|
q: z2.string().optional().default("*:*").describe("Search query in Solr syntax"),
|
|
@@ -2597,6 +2614,8 @@ function formatStatusMarkdown(result, serverUrl, hvdCount) {
|
|
|
2597
2614
|
const sparqlLine = sparql ? `**SPARQL Endpoint**: ${sparql.endpoint_url}
|
|
2598
2615
|
` : "";
|
|
2599
2616
|
const hvdLine = hvdCount !== void 0 ? `**HVD Datasets**: ${hvdCount}
|
|
2617
|
+
` : "";
|
|
2618
|
+
const localeLine = result.locale_default ? `**Portal Locale**: ${result.locale_default}
|
|
2600
2619
|
` : "";
|
|
2601
2620
|
return `# CKAN Server Status
|
|
2602
2621
|
|
|
@@ -2605,7 +2624,7 @@ function formatStatusMarkdown(result, serverUrl, hvdCount) {
|
|
|
2605
2624
|
**CKAN Version**: ${result.ckan_version || "Unknown"}
|
|
2606
2625
|
**Site Title**: ${result.site_title || "N/A"}
|
|
2607
2626
|
**Site URL**: ${result.site_url || "N/A"}
|
|
2608
|
-
` + sparqlLine + hvdLine;
|
|
2627
|
+
` + localeLine + sparqlLine + hvdLine;
|
|
2609
2628
|
}
|
|
2610
2629
|
function registerStatusTools(server) {
|
|
2611
2630
|
server.registerTool(
|
|
@@ -5129,7 +5148,7 @@ var registerAllPrompts = (server) => {
|
|
|
5129
5148
|
function createServer() {
|
|
5130
5149
|
return new McpServer({
|
|
5131
5150
|
name: "ckan-mcp-server",
|
|
5132
|
-
version: "0.4.
|
|
5151
|
+
version: "0.4.95"
|
|
5133
5152
|
});
|
|
5134
5153
|
}
|
|
5135
5154
|
function registerAll(server) {
|
package/dist/worker.js
CHANGED
|
@@ -1086,7 +1086,7 @@ ckan_package_search({
|
|
|
1086
1086
|
})
|
|
1087
1087
|
\`\`\`
|
|
1088
1088
|
|
|
1089
|
-
If the portal supports HVD classification, look for datasets with fields like \`hvd_category\` or \`applicable_legislation\`.`,Sb=t=>{t.registerPrompt(sC,{title:"Search High-Value Datasets (HVD)",description:"Guided prompt to find High-Value Datasets (HVD) on a CKAN portal. Automatically uses the correct filter field from portal configuration.",argsSchema:{server_url:v.string().url().describe("Base URL of the CKAN server"),rows:v.coerce.number().int().positive().default(10).describe("Max results to return")}},async({server_url:e,rows:r})=>{let n=co(e);return ht(iC(e,r,n?.category_field??null))})};var $b=t=>{vb(t),bb(t),wb(t),xb(t),kb(t),Sb(t)};function zb(){return new ga({name:"ckan-mcp-server",version:"0.4.
|
|
1089
|
+
If the portal supports HVD classification, look for datasets with fields like \`hvd_category\` or \`applicable_legislation\`.`,Sb=t=>{t.registerPrompt(sC,{title:"Search High-Value Datasets (HVD)",description:"Guided prompt to find High-Value Datasets (HVD) on a CKAN portal. Automatically uses the correct filter field from portal configuration.",argsSchema:{server_url:v.string().url().describe("Base URL of the CKAN server"),rows:v.coerce.number().int().positive().default(10).describe("Max results to return")}},async({server_url:e,rows:r})=>{let n=co(e);return ht(iC(e,r,n?.category_field??null))})};var $b=t=>{vb(t),bb(t),wb(t),xb(t),kb(t),Sb(t)};function zb(){return new ga({name:"ckan-mcp-server",version:"0.4.93"})}function Tb(t){Kv(t),Jv(t),Gv(t),Qv(t),Yv(t),eb(t),ib(t),ab(t),cb(t),ub(t),lb(t),_b(t),$b(t)}var qa=class{constructor(e={}){this._started=!1,this._hasHandledRequest=!1,this._streamMapping=new Map,this._requestToStreamMapping=new Map,this._requestResponseMap=new Map,this._initialized=!1,this._enableJsonResponse=!1,this._standaloneSseStreamId="_GET_stream",this.sessionIdGenerator=e.sessionIdGenerator,this._enableJsonResponse=e.enableJsonResponse??!1,this._eventStore=e.eventStore,this._onsessioninitialized=e.onsessioninitialized,this._onsessionclosed=e.onsessionclosed,this._allowedHosts=e.allowedHosts,this._allowedOrigins=e.allowedOrigins,this._enableDnsRebindingProtection=e.enableDnsRebindingProtection??!1,this._retryInterval=e.retryInterval}async start(){if(this._started)throw new Error("Transport already started");this._started=!0}createJsonErrorResponse(e,r,n,o){let s={code:r,message:n};return o?.data!==void 0&&(s.data=o.data),new Response(JSON.stringify({jsonrpc:"2.0",error:s,id:null}),{status:e,headers:{"Content-Type":"application/json",...o?.headers}})}validateRequestHeaders(e){if(this._enableDnsRebindingProtection){if(this._allowedHosts&&this._allowedHosts.length>0){let r=e.headers.get("host");if(!r||!this._allowedHosts.includes(r)){let n=`Invalid Host header: ${r}`;return this.onerror?.(new Error(n)),this.createJsonErrorResponse(403,-32e3,n)}}if(this._allowedOrigins&&this._allowedOrigins.length>0){let r=e.headers.get("origin");if(r&&!this._allowedOrigins.includes(r)){let n=`Invalid Origin header: ${r}`;return this.onerror?.(new Error(n)),this.createJsonErrorResponse(403,-32e3,n)}}}}async handleRequest(e,r){if(!this.sessionIdGenerator&&this._hasHandledRequest)throw new Error("Stateless transport cannot be reused across requests. Create a new transport per request.");this._hasHandledRequest=!0;let n=this.validateRequestHeaders(e);if(n)return n;switch(e.method){case"POST":return this.handlePostRequest(e,r);case"GET":return this.handleGetRequest(e);case"DELETE":return this.handleDeleteRequest(e);default:return this.handleUnsupportedRequest()}}async writePrimingEvent(e,r,n,o){if(!this._eventStore||o<"2025-11-25")return;let s=await this._eventStore.storeEvent(n,{}),i=`id: ${s}
|
|
1090
1090
|
data:
|
|
1091
1091
|
|
|
1092
1092
|
`;this._retryInterval!==void 0&&(i=`id: ${s}
|
|
@@ -1280,4 +1280,4 @@ data:
|
|
|
1280
1280
|
</div>
|
|
1281
1281
|
</div>
|
|
1282
1282
|
</body>
|
|
1283
|
-
</html>`,{headers:{"Content-Type":"text/html; charset=utf-8","Access-Control-Allow-Origin":"*"}});if(t.method==="GET"&&e.pathname==="/health")return new Response(JSON.stringify({status:"ok",version:"0.4.
|
|
1283
|
+
</html>`,{headers:{"Content-Type":"text/html; charset=utf-8","Access-Control-Allow-Origin":"*"}});if(t.method==="GET"&&e.pathname==="/health")return new Response(JSON.stringify({status:"ok",version:"0.4.93",tools:20,resources:7,prompts:6,runtime:"cloudflare-workers"}),{headers:{"Content-Type":"application/json","Access-Control-Allow-Origin":"*"}});if(e.pathname==="/mcp"){if(t.method!=="POST"&&t.method!=="OPTIONS")return new Response("Method Not Allowed",{status:405,headers:{Allow:"POST, OPTIONS","Access-Control-Allow-Origin":"*"}});if(t.method==="OPTIONS")return new Response(null,{status:204,headers:{"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET, POST, DELETE, OPTIONS","Access-Control-Allow-Headers":"Content-Type, Accept, Authorization, Mcp-Session-Id","Access-Control-Max-Age":"86400"}});try{let r=zb();Tb(r);let n=new qa({sessionIdGenerator:void 0,enableJsonResponse:!0});await r.connect(n);let o=t.clone();try{let a=await o.json();if(a?.method==="tools/call"&&a?.params?.name){let c=a.params.name,u=a.params.arguments??{},l={tool:c,server:u.server_url??u.endpoint_url??""};u.q!==void 0&&(l.q=u.q),u.fq!==void 0&&(l.fq=u.fq),u.query!==void 0&&(l.query=u.query),u.id!==void 0&&(l.id=u.id),u.name!==void 0&&(l.name=u.name),u.pattern!==void 0&&(l.pattern=u.pattern),u.resource_id!==void 0&&(l.resource_id=u.resource_id),u.format_filter!==void 0&&(l.format_filter=u.format_filter),u.sort!==void 0&&(l.sort=u.sort),u.rows!==void 0&&(l.rows=u.rows),u.limit!==void 0&&(l.limit=u.limit),u.sql!==void 0&&(l.sql=String(u.sql).slice(0,200)),u.country!==void 0&&(l.country=u.country),u.language!==void 0&&(l.language=u.language),u.has_datastore!==void 0&&(l.has_datastore=u.has_datastore),u.min_datasets!==void 0&&(l.min_datasets=u.min_datasets),console.log(JSON.stringify(l))}}catch{}let s=await n.handleRequest(t),i=new Headers(s.headers);return i.set("Access-Control-Allow-Origin","*"),i.set("X-Service-Notice","Demo instance - 100k requests/day shared quota"),i.set("X-Recommendation","https://github.com/ondata/ckan-mcp-server#installation"),new Response(s.body,{status:s.status,statusText:s.statusText,headers:i})}catch(r){return console.error("Worker error:",r),new Response(JSON.stringify({jsonrpc:"2.0",error:{code:-32603,message:"Internal error",data:r instanceof Error?r.message:String(r)},id:null}),{status:500,headers:{"Content-Type":"application/json","Access-Control-Allow-Origin":"*"}})}}return new Response("Not Found",{status:404,headers:{"Access-Control-Allow-Origin":"*"}})}};export{nF as default};
|
package/package.json
CHANGED