@aborruso/ckan-mcp-server 0.4.9 → 0.4.11
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/.devin/wiki.json +273 -0
- package/AGENTS.md +32 -137
- package/CLAUDE.md +18 -0
- package/LOG.md +13 -0
- package/README.md +44 -5
- package/dist/index.js +238 -1
- package/dist/worker.js +158 -44
- package/openspec/changes/add-mcp-prompts/proposal.md +13 -0
- package/openspec/changes/add-mcp-prompts/specs/mcp-prompts/spec.md +22 -0
- package/openspec/changes/add-mcp-prompts/tasks.md +10 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2222,11 +2222,247 @@ function registerAllResources(server2) {
|
|
|
2222
2222
|
registerOrganizationResource(server2);
|
|
2223
2223
|
}
|
|
2224
2224
|
|
|
2225
|
+
// src/prompts/theme.ts
|
|
2226
|
+
import { z as z8 } from "zod";
|
|
2227
|
+
|
|
2228
|
+
// src/prompts/types.ts
|
|
2229
|
+
var createTextPrompt = (text) => ({
|
|
2230
|
+
messages: [
|
|
2231
|
+
{
|
|
2232
|
+
role: "user",
|
|
2233
|
+
content: {
|
|
2234
|
+
type: "text",
|
|
2235
|
+
text
|
|
2236
|
+
}
|
|
2237
|
+
}
|
|
2238
|
+
]
|
|
2239
|
+
});
|
|
2240
|
+
|
|
2241
|
+
// src/prompts/theme.ts
|
|
2242
|
+
var THEME_PROMPT_NAME = "ckan-search-by-theme";
|
|
2243
|
+
var buildThemePromptText = (serverUrl, theme, rows) => `# Guided search: datasets by theme
|
|
2244
|
+
|
|
2245
|
+
## Step 1: Find the theme/group
|
|
2246
|
+
Use \`ckan_group_search\` to locate the group that matches the theme.
|
|
2247
|
+
|
|
2248
|
+
Example:
|
|
2249
|
+
|
|
2250
|
+
ckan_group_search({
|
|
2251
|
+
server_url: "${serverUrl}",
|
|
2252
|
+
pattern: "${theme}"
|
|
2253
|
+
})
|
|
2254
|
+
|
|
2255
|
+
## Step 2: Search datasets in that group
|
|
2256
|
+
Use \`ckan_package_search\` with a group filter.
|
|
2257
|
+
|
|
2258
|
+
Example:
|
|
2259
|
+
|
|
2260
|
+
ckan_package_search({
|
|
2261
|
+
server_url: "${serverUrl}",
|
|
2262
|
+
fq: "groups:<group_name>",
|
|
2263
|
+
sort: "metadata_modified desc",
|
|
2264
|
+
rows: ${rows}
|
|
2265
|
+
})
|
|
2266
|
+
|
|
2267
|
+
## If no group matches
|
|
2268
|
+
Fallback to a tag-based search using facets:
|
|
2269
|
+
|
|
2270
|
+
ckan_package_search({
|
|
2271
|
+
server_url: "${serverUrl}",
|
|
2272
|
+
q: "tags:${theme}",
|
|
2273
|
+
sort: "metadata_modified desc",
|
|
2274
|
+
rows: ${rows}
|
|
2275
|
+
})`;
|
|
2276
|
+
var registerThemePrompt = (server2) => {
|
|
2277
|
+
server2.registerPrompt(
|
|
2278
|
+
THEME_PROMPT_NAME,
|
|
2279
|
+
{
|
|
2280
|
+
title: "Search datasets by theme",
|
|
2281
|
+
description: "Guided prompt to discover a theme and search datasets under it.",
|
|
2282
|
+
argsSchema: {
|
|
2283
|
+
server_url: z8.string().url().describe("Base URL of the CKAN server"),
|
|
2284
|
+
theme: z8.string().min(1).describe("Theme or group name to search"),
|
|
2285
|
+
rows: z8.coerce.number().int().positive().default(10).describe("Max results to return")
|
|
2286
|
+
}
|
|
2287
|
+
},
|
|
2288
|
+
async ({ server_url, theme, rows }) => createTextPrompt(buildThemePromptText(server_url, theme, rows))
|
|
2289
|
+
);
|
|
2290
|
+
};
|
|
2291
|
+
|
|
2292
|
+
// src/prompts/organization.ts
|
|
2293
|
+
import { z as z9 } from "zod";
|
|
2294
|
+
var ORGANIZATION_PROMPT_NAME = "ckan-search-by-organization";
|
|
2295
|
+
var buildOrganizationPromptText = (serverUrl, organization, rows) => `# Guided search: datasets by organization
|
|
2296
|
+
|
|
2297
|
+
## Step 1: Discover matching organizations
|
|
2298
|
+
Use \`ckan_package_search\` with an organization wildcard and facets:
|
|
2299
|
+
|
|
2300
|
+
ckan_package_search({
|
|
2301
|
+
server_url: "${serverUrl}",
|
|
2302
|
+
q: "organization:*${organization}*",
|
|
2303
|
+
rows: 0,
|
|
2304
|
+
facet_field: ["organization"],
|
|
2305
|
+
facet_limit: 50
|
|
2306
|
+
})
|
|
2307
|
+
|
|
2308
|
+
## Step 2: Search datasets for the chosen organization
|
|
2309
|
+
Use \`ckan_package_search\` with a filter query:
|
|
2310
|
+
|
|
2311
|
+
ckan_package_search({
|
|
2312
|
+
server_url: "${serverUrl}",
|
|
2313
|
+
fq: "organization:<org-id>",
|
|
2314
|
+
sort: "metadata_modified desc",
|
|
2315
|
+
rows: ${rows}
|
|
2316
|
+
})`;
|
|
2317
|
+
var registerOrganizationPrompt = (server2) => {
|
|
2318
|
+
server2.registerPrompt(
|
|
2319
|
+
ORGANIZATION_PROMPT_NAME,
|
|
2320
|
+
{
|
|
2321
|
+
title: "Search datasets by organization",
|
|
2322
|
+
description: "Guided prompt to find a publisher and list its datasets.",
|
|
2323
|
+
argsSchema: {
|
|
2324
|
+
server_url: z9.string().url().describe("Base URL of the CKAN server"),
|
|
2325
|
+
organization: z9.string().min(1).describe("Organization name or keyword"),
|
|
2326
|
+
rows: z9.coerce.number().int().positive().default(10).describe("Max results to return")
|
|
2327
|
+
}
|
|
2328
|
+
},
|
|
2329
|
+
async ({ server_url, organization, rows }) => createTextPrompt(buildOrganizationPromptText(server_url, organization, rows))
|
|
2330
|
+
);
|
|
2331
|
+
};
|
|
2332
|
+
|
|
2333
|
+
// src/prompts/format.ts
|
|
2334
|
+
import { z as z10 } from "zod";
|
|
2335
|
+
var FORMAT_PROMPT_NAME = "ckan-search-by-format";
|
|
2336
|
+
var buildFormatPromptText = (serverUrl, format, rows) => `# Guided search: datasets by resource format
|
|
2337
|
+
|
|
2338
|
+
Use \`ckan_package_search\` with a format filter:
|
|
2339
|
+
|
|
2340
|
+
ckan_package_search({
|
|
2341
|
+
server_url: "${serverUrl}",
|
|
2342
|
+
fq: "res_format:${format}",
|
|
2343
|
+
sort: "metadata_modified desc",
|
|
2344
|
+
rows: ${rows}
|
|
2345
|
+
})
|
|
2346
|
+
|
|
2347
|
+
Tip: try uppercase (CSV/JSON) or common variants if results are sparse.`;
|
|
2348
|
+
var registerFormatPrompt = (server2) => {
|
|
2349
|
+
server2.registerPrompt(
|
|
2350
|
+
FORMAT_PROMPT_NAME,
|
|
2351
|
+
{
|
|
2352
|
+
title: "Search datasets by resource format",
|
|
2353
|
+
description: "Guided prompt to find datasets with a given resource format.",
|
|
2354
|
+
argsSchema: {
|
|
2355
|
+
server_url: z10.string().url().describe("Base URL of the CKAN server"),
|
|
2356
|
+
format: z10.string().min(1).describe("Resource format (e.g., CSV, JSON)"),
|
|
2357
|
+
rows: z10.coerce.number().int().positive().default(10).describe("Max results to return")
|
|
2358
|
+
}
|
|
2359
|
+
},
|
|
2360
|
+
async ({ server_url, format, rows }) => createTextPrompt(buildFormatPromptText(server_url, format, rows))
|
|
2361
|
+
);
|
|
2362
|
+
};
|
|
2363
|
+
|
|
2364
|
+
// src/prompts/recent.ts
|
|
2365
|
+
import { z as z11 } from "zod";
|
|
2366
|
+
var RECENT_PROMPT_NAME = "ckan-recent-datasets";
|
|
2367
|
+
var buildRecentPromptText = (serverUrl, rows) => `# Guided search: recent datasets
|
|
2368
|
+
|
|
2369
|
+
Use \`ckan_package_search\` sorted by modification date:
|
|
2370
|
+
|
|
2371
|
+
ckan_package_search({
|
|
2372
|
+
server_url: "${serverUrl}",
|
|
2373
|
+
q: "*:*",
|
|
2374
|
+
sort: "metadata_modified desc",
|
|
2375
|
+
rows: ${rows}
|
|
2376
|
+
})
|
|
2377
|
+
|
|
2378
|
+
Optional: add a date filter for the last N days:
|
|
2379
|
+
|
|
2380
|
+
ckan_package_search({
|
|
2381
|
+
server_url: "${serverUrl}",
|
|
2382
|
+
q: "metadata_modified:[NOW-30DAYS TO *]",
|
|
2383
|
+
sort: "metadata_modified desc",
|
|
2384
|
+
rows: ${rows}
|
|
2385
|
+
})`;
|
|
2386
|
+
var registerRecentPrompt = (server2) => {
|
|
2387
|
+
server2.registerPrompt(
|
|
2388
|
+
RECENT_PROMPT_NAME,
|
|
2389
|
+
{
|
|
2390
|
+
title: "Find recently updated datasets",
|
|
2391
|
+
description: "Guided prompt to list recently updated datasets on a CKAN portal.",
|
|
2392
|
+
argsSchema: {
|
|
2393
|
+
server_url: z11.string().url().describe("Base URL of the CKAN server"),
|
|
2394
|
+
rows: z11.coerce.number().int().positive().default(10).describe("Max results to return")
|
|
2395
|
+
}
|
|
2396
|
+
},
|
|
2397
|
+
async ({ server_url, rows }) => createTextPrompt(buildRecentPromptText(server_url, rows))
|
|
2398
|
+
);
|
|
2399
|
+
};
|
|
2400
|
+
|
|
2401
|
+
// src/prompts/dataset-analysis.ts
|
|
2402
|
+
import { z as z12 } from "zod";
|
|
2403
|
+
var DATASET_ANALYSIS_PROMPT_NAME = "ckan-analyze-dataset";
|
|
2404
|
+
var buildDatasetAnalysisPromptText = (serverUrl, id) => `# Guided analysis: dataset
|
|
2405
|
+
|
|
2406
|
+
## Step 1: Get dataset metadata
|
|
2407
|
+
Use \`ckan_package_show\` to load full metadata and resources:
|
|
2408
|
+
|
|
2409
|
+
ckan_package_show({
|
|
2410
|
+
server_url: "${serverUrl}",
|
|
2411
|
+
id: "${id}"
|
|
2412
|
+
})
|
|
2413
|
+
|
|
2414
|
+
## Step 2: Inspect resources
|
|
2415
|
+
For each resource, use \`ckan_resource_show\` to confirm fields like format, url, and datastore availability:
|
|
2416
|
+
|
|
2417
|
+
ckan_resource_show({
|
|
2418
|
+
server_url: "${serverUrl}",
|
|
2419
|
+
id: "<resource-id>"
|
|
2420
|
+
})
|
|
2421
|
+
|
|
2422
|
+
## Step 3: Explore DataStore (if available)
|
|
2423
|
+
If a resource has \`datastore_active=true\`, use:
|
|
2424
|
+
|
|
2425
|
+
ckan_datastore_search({
|
|
2426
|
+
server_url: "${serverUrl}",
|
|
2427
|
+
resource_id: "<resource-id>",
|
|
2428
|
+
limit: 10
|
|
2429
|
+
})
|
|
2430
|
+
|
|
2431
|
+
For aggregates, use SQL:
|
|
2432
|
+
|
|
2433
|
+
ckan_datastore_search_sql({
|
|
2434
|
+
server_url: "${serverUrl}",
|
|
2435
|
+
sql: "SELECT * FROM "<resource-id>" LIMIT 10"
|
|
2436
|
+
})`;
|
|
2437
|
+
var registerDatasetAnalysisPrompt = (server2) => {
|
|
2438
|
+
server2.registerPrompt(
|
|
2439
|
+
DATASET_ANALYSIS_PROMPT_NAME,
|
|
2440
|
+
{
|
|
2441
|
+
title: "Analyze a dataset",
|
|
2442
|
+
description: "Guided prompt to inspect dataset metadata and explore DataStore tables.",
|
|
2443
|
+
argsSchema: {
|
|
2444
|
+
server_url: z12.string().url().describe("Base URL of the CKAN server"),
|
|
2445
|
+
id: z12.string().min(1).describe("Dataset id or name (CKAN package id)")
|
|
2446
|
+
}
|
|
2447
|
+
},
|
|
2448
|
+
async ({ server_url, id }) => createTextPrompt(buildDatasetAnalysisPromptText(server_url, id))
|
|
2449
|
+
);
|
|
2450
|
+
};
|
|
2451
|
+
|
|
2452
|
+
// src/prompts/index.ts
|
|
2453
|
+
var registerAllPrompts = (server2) => {
|
|
2454
|
+
registerThemePrompt(server2);
|
|
2455
|
+
registerOrganizationPrompt(server2);
|
|
2456
|
+
registerFormatPrompt(server2);
|
|
2457
|
+
registerRecentPrompt(server2);
|
|
2458
|
+
registerDatasetAnalysisPrompt(server2);
|
|
2459
|
+
};
|
|
2460
|
+
|
|
2225
2461
|
// src/server.ts
|
|
2226
2462
|
function createServer() {
|
|
2227
2463
|
return new McpServer({
|
|
2228
2464
|
name: "ckan-mcp-server",
|
|
2229
|
-
version: "0.4.
|
|
2465
|
+
version: "0.4.11"
|
|
2230
2466
|
});
|
|
2231
2467
|
}
|
|
2232
2468
|
function registerAll(server2) {
|
|
@@ -2237,6 +2473,7 @@ function registerAll(server2) {
|
|
|
2237
2473
|
registerTagTools(server2);
|
|
2238
2474
|
registerGroupTools(server2);
|
|
2239
2475
|
registerAllResources(server2);
|
|
2476
|
+
registerAllPrompts(server2);
|
|
2240
2477
|
}
|
|
2241
2478
|
|
|
2242
2479
|
// src/transport/stdio.ts
|