@aborruso/ckan-mcp-server 0.4.97 → 0.4.99
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 +10 -0
- package/dist/index.js +14 -3
- package/dist/worker.js +8 -8
- package/package.json +1 -1
package/LOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# LOG
|
|
2
2
|
|
|
3
|
+
## 2026-04-09
|
|
4
|
+
|
|
5
|
+
### v0.4.99
|
|
6
|
+
|
|
7
|
+
- Fix `resolveSearchQuery`: `*:*` and fielded queries (e.g. `title:X`) are no longer wrapped in `text:(...)` when auto-detected parser override is "text" — `escapeSolrQuery` was turning `*:*` into `\*\:\*`, returning 0 results on portals like dati.comune.messina.it
|
|
8
|
+
|
|
9
|
+
## 2026-04-05
|
|
10
|
+
|
|
11
|
+
- Fix `ckan_package_search`: quoted phrases (e.g. `"aree protette"`) now work inside `text:(...)` wrapping — removed `"` from `escapeSolrQuery` special chars so phrase queries are preserved
|
|
12
|
+
|
|
3
13
|
## 2026-04-03
|
|
4
14
|
|
|
5
15
|
### v0.4.97
|
package/dist/index.js
CHANGED
|
@@ -163,6 +163,16 @@ var portals_default = {
|
|
|
163
163
|
force_text_field: false
|
|
164
164
|
}
|
|
165
165
|
},
|
|
166
|
+
{
|
|
167
|
+
id: "bdap-rgs-mef",
|
|
168
|
+
name: "bdap-opendata.rgs.mef.gov.it",
|
|
169
|
+
api_url: "https://bdap-opendata.rgs.mef.gov.it/SpodCkanApi",
|
|
170
|
+
api_url_aliases: [
|
|
171
|
+
"http://bdap-opendata.rgs.mef.gov.it/SpodCkanApi"
|
|
172
|
+
],
|
|
173
|
+
dataset_view_url: "https://bdap-opendata.rgs.mef.gov.it/SpodCkanApi/dataset/{name}",
|
|
174
|
+
organization_view_url: "https://bdap-opendata.rgs.mef.gov.it/SpodCkanApi/organization/{name}"
|
|
175
|
+
},
|
|
166
176
|
{
|
|
167
177
|
id: "govdata-de",
|
|
168
178
|
name: "govdata.de",
|
|
@@ -610,7 +620,7 @@ function getOrganizationViewUrl(serverUrl, org) {
|
|
|
610
620
|
// src/utils/search.ts
|
|
611
621
|
var DEFAULT_SEARCH_QUERY = "*:*";
|
|
612
622
|
var FIELD_QUERY_PATTERN = /\b[a-zA-Z_][\w-]*:/;
|
|
613
|
-
var SOLR_SPECIAL_CHARS = /[+\-!(){}[\]
|
|
623
|
+
var SOLR_SPECIAL_CHARS = /[+\-!(){}[\]^~*?:\\/|&]/g;
|
|
614
624
|
function isFieldedQuery(query) {
|
|
615
625
|
return FIELD_QUERY_PATTERN.test(query);
|
|
616
626
|
}
|
|
@@ -665,7 +675,8 @@ function resolveSearchQuery(serverUrl, query, parserOverride) {
|
|
|
665
675
|
const portalForce = portalSearchConfig.force_text_field ?? false;
|
|
666
676
|
let forceTextField = false;
|
|
667
677
|
if (parserOverride === "text") {
|
|
668
|
-
|
|
678
|
+
const trimmedQuery = query.trim();
|
|
679
|
+
forceTextField = trimmedQuery !== DEFAULT_SEARCH_QUERY && !isFieldedQuery(trimmedQuery);
|
|
669
680
|
} else if (parserOverride === "default") {
|
|
670
681
|
forceTextField = false;
|
|
671
682
|
} else if (portalForce) {
|
|
@@ -5159,7 +5170,7 @@ var registerAllPrompts = (server) => {
|
|
|
5159
5170
|
function createServer() {
|
|
5160
5171
|
return new McpServer({
|
|
5161
5172
|
name: "ckan-mcp-server",
|
|
5162
|
-
version: "0.4.
|
|
5173
|
+
version: "0.4.99"
|
|
5163
5174
|
});
|
|
5164
5175
|
}
|
|
5165
5176
|
function registerAll(server) {
|
package/dist/worker.js
CHANGED
|
@@ -46,7 +46,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
46
46
|
... [Response truncated at ${e} characters]`}function nt(t,e=Rr){let r=JSON.stringify(t,null,2);if(r.length<=e||(r=JSON.stringify(t),r.length<=e))return r;let n=structuredClone(t),o=["results","records","resources","packages","organizations","groups","tags"];for(let s of o)if(Array.isArray(n[s])&&n[s].length>0){let i=n[s].length;for(;n[s].length>1;)if(n[s].pop(),n._truncated=!0,n._original_count=i,r=JSON.stringify(n),r.length<=e)return r}return W(JSON.stringify(n),e)}function Xe(t){try{if(!t)return"Invalid Date";let e=new Date(t);return Number.isNaN(e.getTime())?"Invalid Date":e.toISOString().slice(0,10)}catch{return"Invalid Date"}}function Iv(t){if(!t||t===0)return"0 B";let e=1024,r=["B","KB","MB","GB"],n=Math.floor(Math.log(t)/Math.log(e));return parseFloat((t/Math.pow(e,n)).toFixed(2))+" "+r[n]}function JA(){try{return typeof WorkerGlobalScope<"u"}catch{return!1}}function se(t){return JA()?t+`
|
|
47
47
|
|
|
48
48
|
---
|
|
49
|
-
\u2139\uFE0F Demo instance (100k requests/day shared quota). For unlimited access: https://github.com/ondata/ckan-mcp-server#installation`:t}function $s(t,e){let r=Uf(t);return(rr(t)?.dataset_view_url||Pr.defaults.dataset_view_url).replace("{server_url}",r).replace("{id}",e.id).replace("{name}",e.name)}function gn(t,e){let r=Uf(t);return(rr(t)?.organization_view_url||Pr.defaults.organization_view_url).replace("{server_url}",r).replace("{id}",e.id).replace("{name}",e.name)}var WA="*:*",Mv=/\b[a-zA-Z_][\w-]*:/,GA=/[+\-!(){}[\]
|
|
49
|
+
\u2139\uFE0F Demo instance (100k requests/day shared quota). For unlimited access: https://github.com/ondata/ckan-mcp-server#installation`:t}function $s(t,e){let r=Uf(t);return(rr(t)?.dataset_view_url||Pr.defaults.dataset_view_url).replace("{server_url}",r).replace("{id}",e.id).replace("{name}",e.name)}function gn(t,e){let r=Uf(t);return(rr(t)?.organization_view_url||Pr.defaults.organization_view_url).replace("{server_url}",r).replace("{id}",e.id).replace("{name}",e.name)}var WA="*:*",Mv=/\b[a-zA-Z_][\w-]*:/,GA=/[+\-!(){}[\]^~*?:\\/|&]/g;function QA(t){return Mv.test(t)}function YA(t){return t.replace(GA,"\\$&")}function XA(t){let e=new Date,r=e.toISOString(),n=/\b(?!metadata_)(modified|issued):\[NOW-(\d+)(DAYS?|MONTHS?|YEARS?)\s+TO\s+NOW\]/gi;return t.replace(n,(o,s,i,a)=>{let c=parseInt(i,10),u=new Date(e);switch(a.toLowerCase().replace(/s$/,"")){case"day":u.setDate(u.getDate()-c);break;case"month":u.setMonth(u.getMonth()-c);break;case"year":u.setFullYear(u.getFullYear()-c);break;default:return o}let d=u.toISOString();return`${s}:[${d} TO ${r}]`})}var eO=/\b(AND|OR|NOT)\b|[+\-!]/;function jv(t){let e=t.trim();return e==="*:*"||e===""||Mv.test(e)||eO.test(e)?!1:e.split(/\s+/).filter(Boolean).length>1}function qv(t){return t.trim().split(/\s+/).filter(Boolean).join(" OR ")}function Ca(t){return t.normalize("NFD").replace(/[\u0300-\u036f]/g,"")}function Dv(t){return t!==Ca(t)}function Na(t,e,r){let o=Ev(t).force_text_field??!1,s=!1;if(r==="text")s=!0;else if(r==="default")s=!1;else if(o){let a=e.trim();s=a!==WA&&!QA(a)}let i=s?`text:(${YA(e)})`:e;return i=XA(i),{effectiveQuery:i,forcedTextField:s}}var Vf=new Map;async function tO(t){let e=t.replace(/\/$/,"").toLowerCase();if(Vf.has(e))return Vf.get(e);let r="data OR dati",[n,o]=await Promise.allSettled([F(t,"package_search",{q:r,rows:0}),F(t,"package_search",{q:`text:(${r})`,rows:0})]),s=n.status==="fulfilled"?n.value.count??0:0,i=o.status==="fulfilled"?o.value.count??0:0,a=i>0&&(s===0||i>s*2);return Vf.set(e,a),a}var Lv={title:4,notes:2,tags:3,organization:1},rO=new Set(["a","an","the","and","or","but","in","on","at","to","for","of","with","by","from","as","is","was","are","were","be","been","being","have","has","had","do","does","did","will","would","could","should","may","might","must","can","this","that","these","those"]),Uv=t=>{let r=(t.toLowerCase().match(/[\p{L}\p{N}]+/gu)??[]).filter(n=>n.length>1&&!rO.has(n));return Array.from(new Set(r))},nO=t=>t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),Fv=(t,e)=>{if(!t||e.length===0)return!1;let r=t.toLowerCase().replace(/_/g," ");return e.some(n=>new RegExp(`\\b${nO(n)}\\b`,"i").test(r))},Bf=(t,e,r)=>Fv(t,e)?r:0,oO=(t,e,r=Lv)=>{let n=Uv(t),o=e.title||e.name||"",s=e.notes||"",i=e.organization?.title||e.organization?.name||e.owner_org||"",a={title:Bf(o,n,r.title),notes:Bf(s,n,r.notes),tags:0,organization:Bf(i,n,r.organization),total:0};if(Array.isArray(e.tags)&&e.tags.length>0&&n.length>0){let c=e.tags.some(u=>{let l=typeof u=="string"?u:u?.name;return Fv(l,n)});a.tags=c?r.tags:0}return a.total=a.title+a.notes+a.tags+a.organization,{total:a.total,breakdown:a,terms:n}},Hv=t=>{if(!t||t.access_services==null)return[];let e=t.access_services;if(Array.isArray(e))return e;if(typeof e=="string"&&e.trim().length>0)try{let r=JSON.parse(e);return Array.isArray(r)?r:[]}catch{return[]}return[]},Vv=t=>{let e=[];for(let r of t){let n=r.endpoint_url;if(Array.isArray(n))for(let o of n)typeof o=="string"&&o.trim().length>0&&e.push(o.trim());else typeof n=="string"&&n.trim().length>0&&e.push(n.trim())}return Array.from(new Set(e))},Kf=t=>{if(!t)return null;let e=typeof t.download_url=="string"?t.download_url.trim():"",r=typeof t.access_url=="string"?t.access_url.trim():"",n=typeof t.url=="string"?t.url.trim():"";return e||r||n||null},sO=t=>({...t,metadata_harvested_at:t.metadata_modified??null,resources:Array.isArray(t.resources)?t.resources.map(e=>{let r=Hv(e),n=Vv(r),o=Kf(e);return n.length===0&&!o?e:{...e,...n.length>0?{access_service_endpoints:n}:{},...o?{effective_download_url:o}:{}}}):t.resources}),iO=(t,e)=>{let r=`# Dataset: ${t.title||t.name}
|
|
50
50
|
|
|
51
51
|
`;if(r+=`**Server**: ${e}
|
|
52
52
|
`,r+=`**Link**: ${$s(e,t)}
|
|
@@ -369,7 +369,7 @@ Examples:
|
|
|
369
369
|
- { server_url: "https://dati.gov.it/opendata", id: "dataset-name" }
|
|
370
370
|
- { server_url: "...", id: "abc-123-def", include_tracking: true }
|
|
371
371
|
|
|
372
|
-
Typical workflow: ckan_package_show \u2192 pick a resource with datastore_active=true \u2192 ckan_datastore_search (query its data)`,inputSchema:v.object({server_url:v.string().url().describe("Base URL of the CKAN server"),id:v.string().min(1).describe("Dataset ID or name"),include_tracking:v.boolean().optional().default(!1).describe("Include tracking statistics"),response_format:fe}).strict(),annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}},async e=>{try{let r=await F(e.server_url,"package_show",{id:e.id,include_tracking:e.include_tracking});if(e.response_format==="json"){let o=lO(sO(r),e.server_url);return{content:[{type:"text",text:nt(o)}],structuredContent:o}}let n=iO(r,e.server_url);return{content:[{type:"text",text:W(se(n))}]}}catch(r){return{content:[{type:"text",text:`Error fetching package: ${r instanceof Error?r.message:String(r)}`}],isError:!0}}}),t.registerTool("ckan_list_resources",{title:"List CKAN Dataset Resources",description:`List all resources in a dataset with a compact summary.
|
|
372
|
+
Typical workflow: ckan_package_show \u2192 pick a resource with datastore_active=true \u2192 ckan_datastore_search (query its data)`,inputSchema:v.object({server_url:v.string().url().describe("Base URL of the CKAN server (e.g., https://dati.gov.it/opendata)"),id:v.string().min(1).describe("Dataset ID (UUID) or machine-readable name slug (e.g., 'raccolta-differenziata-comuni')"),include_tracking:v.boolean().optional().default(!1).describe("Include tracking statistics"),response_format:fe}).strict(),annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}},async e=>{try{let r=await F(e.server_url,"package_show",{id:e.id,include_tracking:e.include_tracking});if(e.response_format==="json"){let o=lO(sO(r),e.server_url);return{content:[{type:"text",text:nt(o)}],structuredContent:o}}let n=iO(r,e.server_url);return{content:[{type:"text",text:W(se(n))}]}}catch(r){return{content:[{type:"text",text:`Error fetching package: ${r instanceof Error?r.message:String(r)}`}],isError:!0}}}),t.registerTool("ckan_list_resources",{title:"List CKAN Dataset Resources",description:`List all resources in a dataset with a compact summary.
|
|
373
373
|
|
|
374
374
|
Returns a focused table of resources showing format, size, DataStore availability, and download URL.
|
|
375
375
|
Use this to quickly assess what files a dataset contains before deciding how to access the data.
|
|
@@ -648,7 +648,7 @@ Args:
|
|
|
648
648
|
Returns:
|
|
649
649
|
List of tags with counts (from faceting)
|
|
650
650
|
|
|
651
|
-
Typical workflow: ckan_tag_list \u2192 ckan_package_search with fq="tags:tag_name" (find datasets by tag) \u2192 ckan_package_show`,inputSchema:v.object({server_url:v.string().url(),q:v.string().optional().default("*:*"),fq:v.string().optional(),tag_query:v.string().optional(),limit:v.number().int().min(1).max(1e3).optional().default(100),response_format:fe}).strict(),annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!0}},async e=>{try{let r={q:e.q,rows:0,"facet.field":JSON.stringify(["tags"]),"facet.limit":e.limit};e.fq&&(r.fq=e.fq);let n=await F(e.server_url,"package_search",r),o=yO(n);if(e.tag_query){let i=e.tag_query.toLowerCase();o=o.filter(a=>a.name.toLowerCase().includes(i))}if(o=o.sort((i,a)=>a.count-i.count||i.name.localeCompare(a.name)).slice(0,e.limit),e.response_format==="json"){let i={count:o.length,tags:o};return{content:[{type:"text",text:W(JSON.stringify(i,null,2))}],structuredContent:i}}let s=`# CKAN Tags
|
|
651
|
+
Typical workflow: ckan_tag_list \u2192 ckan_package_search with fq="tags:tag_name" (find datasets by tag) \u2192 ckan_package_show`,inputSchema:v.object({server_url:v.string().url().describe("Base URL of the CKAN server (e.g., https://dati.gov.it/opendata)"),q:v.string().optional().default("*:*").describe("Dataset search query in Solr syntax to scope the tag facet (default: '*:*' for all datasets)"),fq:v.string().optional().describe("Filter query in Solr syntax (e.g., 'organization:comune-palermo') to restrict which datasets contribute to tag counts"),tag_query:v.string().optional().describe("Substring filter applied to tag names after faceting (e.g., 'acqua' to keep only tags containing 'acqua')"),limit:v.number().int().min(1).max(1e3).optional().default(100).describe("Max tags to return (default 100, max 1000); tags are sorted by count descending"),response_format:fe}).strict(),annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!0}},async e=>{try{let r={q:e.q,rows:0,"facet.field":JSON.stringify(["tags"]),"facet.limit":e.limit};e.fq&&(r.fq=e.fq);let n=await F(e.server_url,"package_search",r),o=yO(n);if(e.tag_query){let i=e.tag_query.toLowerCase();o=o.filter(a=>a.name.toLowerCase().includes(i))}if(o=o.sort((i,a)=>a.count-i.count||i.name.localeCompare(a.name)).slice(0,e.limit),e.response_format==="json"){let i={count:o.length,tags:o};return{content:[{type:"text",text:W(JSON.stringify(i,null,2))}],structuredContent:i}}let s=`# CKAN Tags
|
|
652
652
|
|
|
653
653
|
`;if(s+=`**Server**: ${e.server_url}
|
|
654
654
|
`,s+=`**Query**: ${e.q}
|
|
@@ -696,7 +696,7 @@ Args:
|
|
|
696
696
|
Returns:
|
|
697
697
|
List of groups with metadata. When limit=0, returns only the count of groups with datasets.
|
|
698
698
|
|
|
699
|
-
Typical workflow: ckan_group_list \u2192 ckan_group_show (inspect one) \u2192 ckan_package_search with fq="groups:name" (browse its datasets)`,inputSchema:v.object({server_url:v.string().url(),all_fields:v.boolean().optional().default(!1),sort:v.string().optional().default("name asc"),limit:v.number().int().min(0).optional().default(100),offset:v.number().int().min(0).optional().default(0),response_format:fe}).strict(),annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}},async e=>{try{if(e.limit===0){let s=(await F(e.server_url,"package_search",{rows:0,"facet.field":JSON.stringify(["groups"]),"facet.limit":-1})).search_facets?.groups?.items?.length||0;return e.response_format==="json"?{content:[{type:"text",text:JSON.stringify({count:s},null,2)}],structuredContent:{count:s}}:{content:[{type:"text",text:`# CKAN Groups Count
|
|
699
|
+
Typical workflow: ckan_group_list \u2192 ckan_group_show (inspect one) \u2192 ckan_package_search with fq="groups:name" (browse its datasets)`,inputSchema:v.object({server_url:v.string().url().describe("Base URL of the CKAN server (e.g., https://dati.gov.it/opendata)"),all_fields:v.boolean().optional().default(!1).describe("Return full group objects (true) or just name slugs (false)"),sort:v.string().optional().default("name asc").describe("Sort field and direction (e.g., 'name asc', 'package_count desc')"),limit:v.number().int().min(0).optional().default(100).describe("Max groups to return. Use 0 to get only the count via faceting"),offset:v.number().int().min(0).optional().default(0).describe("Pagination offset"),response_format:fe}).strict(),annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}},async e=>{try{if(e.limit===0){let s=(await F(e.server_url,"package_search",{rows:0,"facet.field":JSON.stringify(["groups"]),"facet.limit":-1})).search_facets?.groups?.items?.length||0;return e.response_format==="json"?{content:[{type:"text",text:JSON.stringify({count:s},null,2)}],structuredContent:{count:s}}:{content:[{type:"text",text:`# CKAN Groups Count
|
|
700
700
|
|
|
701
701
|
**Server**: ${e.server_url}
|
|
702
702
|
**Total groups (with datasets)**: ${s}
|
|
@@ -726,7 +726,7 @@ Args:
|
|
|
726
726
|
Returns:
|
|
727
727
|
Group details with optional datasets
|
|
728
728
|
|
|
729
|
-
Typical workflow: ckan_group_show \u2192 ckan_package_show (inspect a dataset) \u2192 ckan_datastore_search (query its data)`,inputSchema:v.object({server_url:v.string().url(),id:v.string().min(1),include_datasets:v.boolean().optional().default(!0),response_format:fe}).strict(),annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}},async e=>{try{let r=await F(e.server_url,"group_show",{id:e.id,include_datasets:e.include_datasets});if(e.response_format==="json"){let o=wO(r);return{content:[{type:"text",text:nt(o)}],structuredContent:o}}let n=_O(r,e.server_url);return{content:[{type:"text",text:W(se(n))}]}}catch(r){return{content:[{type:"text",text:`Error fetching group: ${r instanceof Error?r.message:String(r)}`}],isError:!0}}}),t.registerTool("ckan_group_search",{title:"Search CKAN Groups by Name",description:`Search for groups by name pattern.
|
|
729
|
+
Typical workflow: ckan_group_show \u2192 ckan_package_show (inspect a dataset) \u2192 ckan_datastore_search (query its data)`,inputSchema:v.object({server_url:v.string().url().describe("Base URL of the CKAN server (e.g., https://dati.gov.it/opendata)"),id:v.string().min(1).describe("Group ID (UUID) or machine-readable name slug (e.g., 'transport', 'energia')"),include_datasets:v.boolean().optional().default(!0).describe("Include the list of datasets belonging to this group"),response_format:fe}).strict(),annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1}},async e=>{try{let r=await F(e.server_url,"group_show",{id:e.id,include_datasets:e.include_datasets});if(e.response_format==="json"){let o=wO(r);return{content:[{type:"text",text:nt(o)}],structuredContent:o}}let n=_O(r,e.server_url);return{content:[{type:"text",text:W(se(n))}]}}catch(r){return{content:[{type:"text",text:`Error fetching group: ${r instanceof Error?r.message:String(r)}`}],isError:!0}}}),t.registerTool("ckan_group_search",{title:"Search CKAN Groups by Name",description:`Search for groups by name pattern.
|
|
730
730
|
|
|
731
731
|
This tool provides a simpler interface than package_search for finding groups.
|
|
732
732
|
Wildcards are automatically added around the search pattern.
|
|
@@ -739,7 +739,7 @@ Args:
|
|
|
739
739
|
Returns:
|
|
740
740
|
List of matching groups with dataset counts
|
|
741
741
|
|
|
742
|
-
Typical workflow: ckan_group_search \u2192 ckan_group_show (get details) \u2192 ckan_package_search with fq="groups:name"`,inputSchema:v.object({server_url:v.string().url(),pattern:v.string().min(1).describe("
|
|
742
|
+
Typical workflow: ckan_group_search \u2192 ckan_group_show (get details) \u2192 ckan_package_search with fq="groups:name"`,inputSchema:v.object({server_url:v.string().url().describe("Base URL of the CKAN server (e.g., https://dati.gov.it/opendata)"),pattern:v.string().min(1).describe("Name pattern to search for (wildcards added automatically, e.g., 'energia', 'salute')"),response_format:fe}).strict(),annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!0}},async e=>{try{let r=`groups:*${e.pattern}*`,n=await F(e.server_url,"package_search",{q:r,rows:0,"facet.field":JSON.stringify(["groups"]),"facet.limit":500}),o=vO(n),s=n.count||0;if(e.response_format==="json"){let a={count:o.length,total_datasets:s,groups:o.map(c=>({name:c.name,display_name:c.display_name,dataset_count:c.count}))};return{content:[{type:"text",text:W(JSON.stringify(a,null,2))}],structuredContent:a}}let i=`# CKAN Group Search Results
|
|
743
743
|
|
|
744
744
|
`;if(i+=`**Server**: ${e.server_url}
|
|
745
745
|
`,i+=`**Pattern**: "${e.pattern}"
|
|
@@ -1093,7 +1093,7 @@ ckan_package_search({
|
|
|
1093
1093
|
})
|
|
1094
1094
|
\`\`\`
|
|
1095
1095
|
|
|
1096
|
-
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.
|
|
1096
|
+
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.98"})}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}
|
|
1097
1097
|
data:
|
|
1098
1098
|
|
|
1099
1099
|
`;this._retryInterval!==void 0&&(i=`id: ${s}
|
|
@@ -1287,4 +1287,4 @@ data:
|
|
|
1287
1287
|
</div>
|
|
1288
1288
|
</div>
|
|
1289
1289
|
</body>
|
|
1290
|
-
</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.
|
|
1290
|
+
</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.98",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