@adobe/design-data-agent-mcp 1.9.5 → 1.9.7
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 +5 -1
- package/package.json +2 -2
- package/skills/design-data/SKILL.md +1 -1
- package/src/dataset-freshness.js +95 -0
- package/src/tools/read.js +9 -1
package/README.md
CHANGED
|
@@ -38,7 +38,11 @@ package version — there's no separate data update to run. Pin `@latest` (as ab
|
|
|
38
38
|
fetches the newest published version rather than reusing whatever it last cached; `-y` alone
|
|
39
39
|
only skips the install confirmation, it doesn't force a re-fetch. Already on `/plugin`? Run
|
|
40
40
|
`/plugin update design-data-agent@spectrum-design-data`. Call the primer tool and check
|
|
41
|
-
`provenance.designDataVersion` to see which dataset version is embedded.
|
|
41
|
+
`provenance.designDataVersion` to see which dataset version is embedded. The primer tool
|
|
42
|
+
also does a best-effort check against the latest published `@adobe/spectrum-design-data`
|
|
43
|
+
version — if the embedded dataset is behind, it adds a `provenance.datasetStatus` field and
|
|
44
|
+
logs a one-line warning to stderr. This is silent on any network failure (offline/air-gapped
|
|
45
|
+
use is unaffected); set `DESIGN_DATA_SKIP_VERSION_CHECK=1` to disable the check entirely.
|
|
42
46
|
|
|
43
47
|
## MCP server
|
|
44
48
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adobe/design-data-agent-mcp",
|
|
3
|
-
"version": "1.9.
|
|
3
|
+
"version": "1.9.7",
|
|
4
4
|
"description": "MCP server and Claude Code skill for the design-data agent surface — read tools run in-process via wasm",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
33
33
|
"@adobe/design-data": "3.0.7",
|
|
34
34
|
"@adobe/design-data-wasm": "0.7.0",
|
|
35
|
-
"@adobe/spectrum-design-data": "
|
|
35
|
+
"@adobe/spectrum-design-data": "3.0.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"ava": "^6.0.1"
|
|
@@ -6,7 +6,7 @@ description: >
|
|
|
6
6
|
system, token lookup, spec-conformance, drift detection, or token authoring on custom data.
|
|
7
7
|
metadata:
|
|
8
8
|
author: adobe
|
|
9
|
-
version: "1.9.
|
|
9
|
+
version: "1.9.7"
|
|
10
10
|
when_to_use: >
|
|
11
11
|
Trigger on: design system, design tokens, spec-conformant, drift, validate tokens, token
|
|
12
12
|
authoring, custom dataset, DESIGN_DATA_PATH, design-data validate, design-data diff,
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// Copyright 2026 Adobe. All rights reserved.
|
|
2
|
+
// This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
|
3
|
+
// you may not use this file except in compliance with the License. You may obtain a copy
|
|
4
|
+
// of the License at http://www.apache.org/licenses/LICENSE-2.0
|
|
5
|
+
//
|
|
6
|
+
// Unless required by applicable law or agreed to in writing, software distributed under
|
|
7
|
+
// the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
|
8
|
+
// OF ANY KIND, either express or implied. See the License for the specific language
|
|
9
|
+
// governing permissions and limitations under the License.
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Best-effort runtime check that the embedded dataset (provenance.designDataVersion,
|
|
13
|
+
* baked into @adobe/design-data-wasm at build time) isn't behind the latest published
|
|
14
|
+
* @adobe/spectrum-design-data. See spectrum-design-data-9fe.5 — a plain `npx -y <pkg>`
|
|
15
|
+
* (no @latest tag) can silently reuse a cached older wasm build.
|
|
16
|
+
*
|
|
17
|
+
* Deliberately silent on any failure (offline, registry down, timeout): this is a
|
|
18
|
+
* courtesy signal, never a reason to break the primer response.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
const REGISTRY_URL =
|
|
22
|
+
"https://registry.npmjs.org/@adobe/spectrum-design-data/latest";
|
|
23
|
+
const TIMEOUT_MS = 1500;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Numeric major.minor.patch compare. ponytail: ignores prerelease/build tags;
|
|
27
|
+
* add real semver only if a data prerelease ships.
|
|
28
|
+
*/
|
|
29
|
+
export function isBehind(embedded, latest) {
|
|
30
|
+
const a = String(embedded).split(".").map(Number);
|
|
31
|
+
const b = String(latest).split(".").map(Number);
|
|
32
|
+
for (let i = 0; i < Math.max(a.length, b.length); i++) {
|
|
33
|
+
const x = a[i] ?? 0;
|
|
34
|
+
const y = b[i] ?? 0;
|
|
35
|
+
if (x !== y) return x < y;
|
|
36
|
+
}
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
let warned = false;
|
|
41
|
+
let cached; // Promise<status|null>, memoized per process — cleared on failure so a
|
|
42
|
+
// transient network blip doesn't permanently disable the check (see fetchLatest).
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @param {string} embeddedVersion - provenance.designDataVersion from ds.primer()
|
|
46
|
+
* @returns {Promise<{latestVersion: string, isStale: boolean, message?: string}|null>}
|
|
47
|
+
*/
|
|
48
|
+
export function checkDatasetFreshness(embeddedVersion) {
|
|
49
|
+
if (!embeddedVersion || process.env.DESIGN_DATA_SKIP_VERSION_CHECK) {
|
|
50
|
+
return Promise.resolve(null);
|
|
51
|
+
}
|
|
52
|
+
if (!cached) {
|
|
53
|
+
cached = fetchLatest(embeddedVersion).then((status) => {
|
|
54
|
+
// A null result means the check failed (offline/timeout/registry error) —
|
|
55
|
+
// don't memoize failure, so the next primer call retries instead of being
|
|
56
|
+
// stuck with no freshness signal for the rest of the process.
|
|
57
|
+
if (status === null) cached = undefined;
|
|
58
|
+
return status;
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
return cached;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async function fetchLatest(embeddedVersion) {
|
|
65
|
+
const controller = new AbortController();
|
|
66
|
+
const timer = setTimeout(() => controller.abort(), TIMEOUT_MS);
|
|
67
|
+
try {
|
|
68
|
+
const res = await fetch(REGISTRY_URL, { signal: controller.signal });
|
|
69
|
+
if (!res.ok) return null;
|
|
70
|
+
const { version: latestVersion } = await res.json();
|
|
71
|
+
const isStale = isBehind(embeddedVersion, latestVersion);
|
|
72
|
+
const status = { latestVersion, isStale };
|
|
73
|
+
if (isStale) {
|
|
74
|
+
status.message =
|
|
75
|
+
`Embedded dataset (${embeddedVersion}) is behind the latest published ` +
|
|
76
|
+
`@adobe/spectrum-design-data (${latestVersion}). Reinstall with ` +
|
|
77
|
+
`npx -y @adobe/design-data-agent-mcp@latest to pick up the newer snapshot.`;
|
|
78
|
+
if (!warned) {
|
|
79
|
+
warned = true;
|
|
80
|
+
console.error(`[design-data] ${status.message}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return status;
|
|
84
|
+
} catch {
|
|
85
|
+
return null;
|
|
86
|
+
} finally {
|
|
87
|
+
clearTimeout(timer);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Test-only: clear the memoized check + warn-once flag between cases. */
|
|
92
|
+
export function __resetFreshnessCache() {
|
|
93
|
+
warned = false;
|
|
94
|
+
cached = undefined;
|
|
95
|
+
}
|
package/src/tools/read.js
CHANGED
|
@@ -32,6 +32,7 @@ import { readFileSync, existsSync, readdirSync } from "fs";
|
|
|
32
32
|
import { join } from "path";
|
|
33
33
|
import { loadDataset } from "@adobe/design-data/load";
|
|
34
34
|
import { config } from "../config.js";
|
|
35
|
+
import { checkDatasetFreshness } from "../dataset-freshness.js";
|
|
35
36
|
|
|
36
37
|
// Note: this module intentionally never spawns the native binary — primer and
|
|
37
38
|
// describe_component must keep working with no CLI on PATH at all (see the
|
|
@@ -107,6 +108,11 @@ export function createReadTools() {
|
|
|
107
108
|
const wasm = await getWasm();
|
|
108
109
|
const ds = await getDataset();
|
|
109
110
|
const { provenance } = ds.primer();
|
|
111
|
+
// Best-effort staleness check (spectrum-design-data-9fe.5) — silent on
|
|
112
|
+
// failure, never blocks the primer response.
|
|
113
|
+
const datasetStatus = await checkDatasetFreshness(
|
|
114
|
+
provenance.designDataVersion,
|
|
115
|
+
);
|
|
110
116
|
return {
|
|
111
117
|
// top-level source is the legacy skill-contract field; provenance.source
|
|
112
118
|
// duplicates it intentionally — provenance is the richer metrics object
|
|
@@ -124,7 +130,9 @@ export function createReadTools() {
|
|
|
124
130
|
},
|
|
125
131
|
components: wasm.getFieldValues("component") ?? [],
|
|
126
132
|
properties: wasm.getFieldValues("property") ?? [],
|
|
127
|
-
provenance
|
|
133
|
+
provenance: datasetStatus
|
|
134
|
+
? { ...provenance, datasetStatus }
|
|
135
|
+
: provenance,
|
|
128
136
|
};
|
|
129
137
|
},
|
|
130
138
|
},
|