@aborruso/ckan-mcp-server 0.4.126 → 0.4.127
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 +14 -0
- package/dist/index.js +49 -1
- package/package.json +1 -1
package/LOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# LOG
|
|
2
2
|
|
|
3
|
+
## 2026-09-24
|
|
4
|
+
|
|
5
|
+
### v0.4.127
|
|
6
|
+
|
|
7
|
+
Ships #554: `dct:temporal` coverage in `ckan_package_show` (markdown + JSON, every period, `start_equals_issued` flag) and `CKAN_ALLOWED_DOMAINS` declared optional in `server.json` for the MCP Registry. Smoke 17/17.
|
|
8
|
+
|
|
9
|
+
### `ckan_package_show`: temporal coverage (dct:temporal)
|
|
10
|
+
|
|
11
|
+
New `readTemporalCoverage()` reads `dct:temporal` in both shapes dati.gov.it uses: root `temporal_coverage` (JSON string, e.g. Comune di Coriano) and extras `temporal_start`/`temporal_end`/`temporal_coverage` (Regione Toscana, 12,426 datasets). Rendered as **Temporal Coverage (dct:temporal)** in markdown and `temporal_coverage: [{start, end, start_equals_issued}]` in JSON, every period kept; before, JSON had nothing and markdown only the extras case. `start_equals_issued` is a factual flag for start = issued with no end: a full scan of the 17,860 datasets with `temporal_start` found a third like that, and on the origin portals (dati.toscana.it, opendata.maggioli.cloud, opendata.uniba.it, all dcatapit) `temporal_coverage` is empty in the CKAN API while their RDF export emits `dct:temporal` with `startDate` = `dct:issued`. So it is an export artefact, not a publisher entry. INPS, MIT, LaMMA weather runs and Camera di Commercio Marche carry real spans.
|
|
12
|
+
|
|
13
|
+
### server.json: declare `CKAN_ALLOWED_DOMAINS` as optional
|
|
14
|
+
|
|
15
|
+
Claude Desktop's configure dialog asked for six env vars, `CKAN_ALLOWED_DOMAINS` marked required, inferred from the README HTTP table. The registry package is stdio, where the allowlist is optional. `server.json` now declares the one variable explicitly (`isRequired: false`, placeholder). Takes effect on the next registry publish.
|
|
16
|
+
|
|
3
17
|
## 2026-09-23
|
|
4
18
|
|
|
5
19
|
### v0.4.126 - why MQA URL tests fail
|
package/dist/index.js
CHANGED
|
@@ -1517,6 +1517,42 @@ var readDcatExtra = (dataset, key) => {
|
|
|
1517
1517
|
const rootValue = dataset[key];
|
|
1518
1518
|
return typeof rootValue === "string" ? rootValue : "";
|
|
1519
1519
|
};
|
|
1520
|
+
var readExtra = (dataset, key) => {
|
|
1521
|
+
const extras = Array.isArray(dataset.extras) ? dataset.extras : [];
|
|
1522
|
+
for (const e of extras) {
|
|
1523
|
+
if (e && typeof e === "object" && e.key === key) {
|
|
1524
|
+
return e.value;
|
|
1525
|
+
}
|
|
1526
|
+
}
|
|
1527
|
+
return void 0;
|
|
1528
|
+
};
|
|
1529
|
+
var toPeriod = (item) => {
|
|
1530
|
+
if (!item || typeof item !== "object") return null;
|
|
1531
|
+
const { temporal_start, temporal_end } = item;
|
|
1532
|
+
const start = typeof temporal_start === "string" && temporal_start ? temporal_start : null;
|
|
1533
|
+
const end = typeof temporal_end === "string" && temporal_end ? temporal_end : null;
|
|
1534
|
+
return start || end ? { start, end } : null;
|
|
1535
|
+
};
|
|
1536
|
+
var parseTemporalCoverage = (raw) => {
|
|
1537
|
+
let value = raw;
|
|
1538
|
+
if (typeof value === "string") {
|
|
1539
|
+
try {
|
|
1540
|
+
value = JSON.parse(value);
|
|
1541
|
+
} catch {
|
|
1542
|
+
return [];
|
|
1543
|
+
}
|
|
1544
|
+
}
|
|
1545
|
+
const items = Array.isArray(value) ? value : [value];
|
|
1546
|
+
return items.map(toPeriod).filter((p) => p !== null);
|
|
1547
|
+
};
|
|
1548
|
+
var readTemporalCoverage = (dataset) => {
|
|
1549
|
+
const fromRoot = parseTemporalCoverage(dataset.temporal_coverage);
|
|
1550
|
+
if (fromRoot.length > 0) return fromRoot;
|
|
1551
|
+
const fromExtra = parseTemporalCoverage(readExtra(dataset, "temporal_coverage"));
|
|
1552
|
+
if (fromExtra.length > 0) return fromExtra;
|
|
1553
|
+
return parseTemporalCoverage({ temporal_start: readExtra(dataset, "temporal_start"), temporal_end: readExtra(dataset, "temporal_end") });
|
|
1554
|
+
};
|
|
1555
|
+
var startEqualsIssued = (period, issued) => period.end === null && typeof issued === "string" && period.start !== null && period.start.slice(0, 10) === issued.slice(0, 10);
|
|
1520
1556
|
var scoreDatasetRelevance = (query, dataset, weights = DEFAULT_RELEVANCE_WEIGHTS, fullCoverage = false) => {
|
|
1521
1557
|
const terms = extractQueryTerms(query);
|
|
1522
1558
|
const titleText = dataset.title || dataset.name || "";
|
|
@@ -1655,6 +1691,15 @@ var formatPackageShowMarkdown = (result, serverUrl) => {
|
|
|
1655
1691
|
const accessRights = dcatField("access_rights");
|
|
1656
1692
|
if (accessRights) markdown += `- **Access Rights (dct:accessRights)**: ${sanitizeInline(accessRights)}
|
|
1657
1693
|
`;
|
|
1694
|
+
const periods = readTemporalCoverage(result);
|
|
1695
|
+
if (periods.length > 0) {
|
|
1696
|
+
const spans = periods.map((p) => {
|
|
1697
|
+
const span = `${p.start ? formatDate(p.start) : "?"} \u2192 ${p.end ? formatDate(p.end) : "open"}`;
|
|
1698
|
+
return startEqualsIssued(p, result.issued) ? `${span} (start equals issued, no end)` : span;
|
|
1699
|
+
});
|
|
1700
|
+
markdown += `- **Temporal Coverage (dct:temporal)**: ${sanitizeInline(spans.join("; "))}
|
|
1701
|
+
`;
|
|
1702
|
+
}
|
|
1658
1703
|
markdown += `
|
|
1659
1704
|
`;
|
|
1660
1705
|
if (result.organization) {
|
|
@@ -1888,6 +1933,7 @@ function compactPackageShow(result, serverUrl) {
|
|
|
1888
1933
|
holder_name: result.holder_name || null,
|
|
1889
1934
|
hvd_category: result.hvd_category || null,
|
|
1890
1935
|
applicable_legislation: result.applicable_legislation || null,
|
|
1936
|
+
temporal_coverage: readTemporalCoverage(result).map((p) => ({ ...p, start_equals_issued: startEqualsIssued(p, result.issued) })),
|
|
1891
1937
|
resources: (result.resources || []).map((r) => ({
|
|
1892
1938
|
id: r.id,
|
|
1893
1939
|
name: r.name || null,
|
|
@@ -2500,6 +2546,8 @@ Returns (JSON format):
|
|
|
2500
2546
|
author, maintainer,
|
|
2501
2547
|
frequency, language, publisher_name, holder_name,
|
|
2502
2548
|
hvd_category, applicable_legislation,
|
|
2549
|
+
temporal_coverage (array of {start, end, start_equals_issued} from dct:temporal; empty if absent;
|
|
2550
|
+
start_equals_issued=true when start = issued and no end: on dcatapit portals an export default, not a data period),
|
|
2503
2551
|
resources (id, name, format, url, size, datastore_active, created, last_modified, api_json_url),
|
|
2504
2552
|
view_url, api_json_url
|
|
2505
2553
|
|
|
@@ -5994,7 +6042,7 @@ var registerAllPrompts = (server) => {
|
|
|
5994
6042
|
function createServer() {
|
|
5995
6043
|
return new McpServer({
|
|
5996
6044
|
name: "ckan-mcp-server",
|
|
5997
|
-
version: "0.4.
|
|
6045
|
+
version: "0.4.127"
|
|
5998
6046
|
});
|
|
5999
6047
|
}
|
|
6000
6048
|
function registerAll(server) {
|