@nysds/mcp-server 1.18.1 → 1.18.3
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 +44 -29
- package/data/cem/custom-elements.json +108 -72
- package/data/guides/frameworks/react.md +70 -0
- package/data/guides/themes.md +61 -0
- package/data/tokens/tokens.css +1 -1
- package/data/tokens/tokens.json +1092 -399
- package/dist/lib/token-parser.d.ts +19 -31
- package/dist/lib/token-parser.d.ts.map +1 -1
- package/dist/lib/token-parser.js +57 -87
- package/dist/tools/guide-tools.d.ts.map +1 -1
- package/dist/tools/guide-tools.js +3 -1
- package/dist/tools/token-tools.d.ts +2 -3
- package/dist/tools/token-tools.d.ts.map +1 -1
- package/dist/tools/token-tools.js +66 -343
- package/package.json +3 -3
|
@@ -4,312 +4,74 @@
|
|
|
4
4
|
* MCP tools for working with NYSDS design tokens.
|
|
5
5
|
*
|
|
6
6
|
* Tools:
|
|
7
|
-
* -
|
|
8
|
-
* -
|
|
9
|
-
* - get_token_info: Get detailed token info with optional context validation
|
|
7
|
+
* - find_tokens: Search or browse tokens (discovery)
|
|
8
|
+
* - get_token: Get full details for a specific token (deep dive)
|
|
10
9
|
* - get_token_graph: Get token dependency graph
|
|
11
10
|
*/
|
|
12
11
|
import { z } from "zod";
|
|
13
|
-
import { getCSSTokens,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
selectors: ["[data-theme='admin']", ".nys-theme-admin"],
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
id: "business",
|
|
32
|
-
name: "Business",
|
|
33
|
-
description: "For commerce and economic development agencies",
|
|
34
|
-
primaryColor: "#084b52",
|
|
35
|
-
selectors: ["[data-theme='business']", ".nys-theme-business"],
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
id: "environment",
|
|
39
|
-
name: "Environment",
|
|
40
|
-
description: "For environmental and conservation agencies",
|
|
41
|
-
primaryColor: "#233f2b",
|
|
42
|
-
selectors: ["[data-theme='environment']", ".nys-theme-environment"],
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
id: "health",
|
|
46
|
-
name: "Health",
|
|
47
|
-
description: "For health and human services agencies",
|
|
48
|
-
primaryColor: "#43285d",
|
|
49
|
-
selectors: ["[data-theme='health']", ".nys-theme-health"],
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
id: "local",
|
|
53
|
-
name: "Local Government",
|
|
54
|
-
description: "For local government entities",
|
|
55
|
-
primaryColor: "#402217",
|
|
56
|
-
selectors: ["[data-theme='local']", ".nys-theme-local"],
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
id: "safety",
|
|
60
|
-
name: "Public Safety",
|
|
61
|
-
description: "For public safety agencies",
|
|
62
|
-
primaryColor: "#435d6e",
|
|
63
|
-
selectors: ["[data-theme='safety']", ".nys-theme-safety"],
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
id: "transportation",
|
|
67
|
-
name: "Transportation",
|
|
68
|
-
description: "For DOT and transit authorities",
|
|
69
|
-
primaryColor: "#0b5583",
|
|
70
|
-
selectors: ["[data-theme='transportation']", ".nys-theme-transportation"],
|
|
71
|
-
},
|
|
12
|
+
import { getCSSTokens, getCSSTokenByVariable, buildTokenGraph, getRecommendedTokens, getPrimitiveTokens, getAlternativeTokens, } from "../lib/token-parser.js";
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// Shared Constants
|
|
15
|
+
// ============================================================================
|
|
16
|
+
const CATEGORY_ENUM = [
|
|
17
|
+
"color",
|
|
18
|
+
"font",
|
|
19
|
+
"space",
|
|
20
|
+
"size",
|
|
21
|
+
"radius",
|
|
22
|
+
"shadow",
|
|
23
|
+
"border",
|
|
24
|
+
"form",
|
|
25
|
+
"gutter",
|
|
26
|
+
"icon",
|
|
72
27
|
];
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
const warnings = [];
|
|
80
|
-
let valid = true;
|
|
81
|
-
const varName = token.cssVariable;
|
|
82
|
-
// Context-specific validation rules
|
|
83
|
-
if (context === "text") {
|
|
84
|
-
if (varName.includes("-surface-")) {
|
|
85
|
-
valid = false;
|
|
86
|
-
warnings.push("Surface colors should not be used for text. Use --nys-color-text-* tokens.");
|
|
87
|
-
alternatives.push("--nys-color-text", "--nys-color-text-weak", "--nys-color-text-weaker");
|
|
88
|
-
}
|
|
89
|
-
else if (varName.includes("-text-")) {
|
|
90
|
-
recommendations.push("Pair with --nys-color-surface for optimal contrast on light backgrounds");
|
|
91
|
-
recommendations.push("Pair with --nys-color-surface-reverse for dark backgrounds");
|
|
92
|
-
}
|
|
93
|
-
else if (varName.includes("-link-")) {
|
|
94
|
-
recommendations.push("Ensure links are distinguishable from body text");
|
|
95
|
-
recommendations.push("Include visible focus and hover states");
|
|
96
|
-
}
|
|
97
|
-
else if (varName.includes("-danger-") || varName.includes("-warning-")) {
|
|
98
|
-
recommendations.push("Pair with corresponding icon for accessibility");
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
else if (context === "background") {
|
|
102
|
-
if (varName.includes("-text-")) {
|
|
103
|
-
valid = false;
|
|
104
|
-
warnings.push("Text colors should not be used for backgrounds. Use --nys-color-surface-* tokens.");
|
|
105
|
-
alternatives.push("--nys-color-surface", "--nys-color-surface-raised", "--nys-color-surface-reverse");
|
|
106
|
-
}
|
|
107
|
-
else if (varName.includes("-surface-")) {
|
|
108
|
-
if (varName.includes("-reverse")) {
|
|
109
|
-
recommendations.push("Use --nys-color-text-reverse for text on dark surfaces");
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
recommendations.push("Use --nys-color-text for text on light surfaces");
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
else if (varName.includes("-weak") &&
|
|
116
|
-
(varName.includes("-success-") ||
|
|
117
|
-
varName.includes("-info-") ||
|
|
118
|
-
varName.includes("-warning-") ||
|
|
119
|
-
varName.includes("-danger-"))) {
|
|
120
|
-
recommendations.push("Use for alert/notification backgrounds");
|
|
121
|
-
recommendations.push("Pair with corresponding -strong variant for text color");
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
else if (context === "border") {
|
|
125
|
-
if (varName.includes("-base-")) {
|
|
126
|
-
recommendations.push("Good for borders and dividers");
|
|
127
|
-
}
|
|
128
|
-
else if (varName.includes("-focus")) {
|
|
129
|
-
recommendations.push("Reserved for focus ring outlines");
|
|
130
|
-
recommendations.push("Use 2px solid for visible focus indication");
|
|
131
|
-
}
|
|
132
|
-
else if (varName.includes("-theme-")) {
|
|
133
|
-
recommendations.push("Use for branded accent borders");
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
else if (context === "icon") {
|
|
137
|
-
if (varName.includes("-ink-")) {
|
|
138
|
-
recommendations.push("Primary choice for icons");
|
|
139
|
-
if (varName.includes("-reverse")) {
|
|
140
|
-
recommendations.push("Use on dark backgrounds");
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
else if (varName.includes("-text-")) {
|
|
144
|
-
recommendations.push("Icons can use text colors for consistency");
|
|
145
|
-
}
|
|
146
|
-
else if (varName.includes("-success-") ||
|
|
147
|
-
varName.includes("-danger-") ||
|
|
148
|
-
varName.includes("-warning-") ||
|
|
149
|
-
varName.includes("-info-")) {
|
|
150
|
-
recommendations.push("Use for status icons to reinforce meaning with color");
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
// Find similar tokens as alternatives
|
|
154
|
-
if (alternatives.length === 0) {
|
|
155
|
-
const tokens = getCSSTokens();
|
|
156
|
-
const category = token.category;
|
|
157
|
-
const similar = tokens
|
|
158
|
-
.filter((t) => t.category === category &&
|
|
159
|
-
t.cssVariable !== varName &&
|
|
160
|
-
((context === "text" && t.cssVariable.includes("-text-")) ||
|
|
161
|
-
(context === "background" && t.cssVariable.includes("-surface-")) ||
|
|
162
|
-
(context === "border" && t.cssVariable.includes("-base-")) ||
|
|
163
|
-
(context === "icon" && t.cssVariable.includes("-ink-"))))
|
|
164
|
-
.slice(0, 3)
|
|
165
|
-
.map((t) => t.cssVariable);
|
|
166
|
-
alternatives.push(...similar);
|
|
167
|
-
}
|
|
168
|
-
return {
|
|
169
|
-
valid,
|
|
170
|
-
cssVariable: token.cssVariable,
|
|
171
|
-
context,
|
|
172
|
-
recommendations,
|
|
173
|
-
alternatives,
|
|
174
|
-
warnings: warnings.length > 0 ? warnings : undefined,
|
|
175
|
-
};
|
|
176
|
-
}
|
|
28
|
+
const TOKEN_TOOL_ANNOTATIONS = {
|
|
29
|
+
readOnlyHint: true,
|
|
30
|
+
destructiveHint: false,
|
|
31
|
+
idempotentHint: true,
|
|
32
|
+
openWorldHint: false,
|
|
33
|
+
};
|
|
177
34
|
// ============================================================================
|
|
178
35
|
// Tool Registration
|
|
179
36
|
// ============================================================================
|
|
180
37
|
export function registerTokenTools(server) {
|
|
181
38
|
// -------------------------------------------------------------------------
|
|
182
|
-
//
|
|
39
|
+
// find_tokens - Search or browse tokens (discovery)
|
|
183
40
|
// -------------------------------------------------------------------------
|
|
184
|
-
server.tool("
|
|
185
|
-
|
|
186
|
-
.
|
|
187
|
-
.default("tokens")
|
|
188
|
-
.describe("What to return: 'tokens' for CSS variables, 'categories' for category list with counts, 'themes' for agency themes"),
|
|
189
|
-
category: z
|
|
190
|
-
.enum([
|
|
191
|
-
"color",
|
|
192
|
-
"font",
|
|
193
|
-
"space",
|
|
194
|
-
"size",
|
|
195
|
-
"radius",
|
|
196
|
-
"shadow",
|
|
197
|
-
"border",
|
|
198
|
-
"form",
|
|
199
|
-
"gutter",
|
|
200
|
-
"icon",
|
|
201
|
-
])
|
|
202
|
-
.optional()
|
|
203
|
-
.describe("Filter tokens by category (only applies when output='tokens')"),
|
|
204
|
-
layer: z
|
|
205
|
-
.enum(["primitive", "applied", "theme", "appearance"])
|
|
41
|
+
server.tool("find_tokens", "Search or browse NYSDS design tokens. Omit query to list all. Returns CSS variable names for use with var().", {
|
|
42
|
+
query: z
|
|
43
|
+
.string()
|
|
206
44
|
.optional()
|
|
207
|
-
.describe("
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
.
|
|
211
|
-
.
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
.describe("Include token descriptions (only applies when output='tokens')"),
|
|
216
|
-
}, async ({ output, category, layer, includeResolvedValues, includeDescriptions, }) => {
|
|
217
|
-
// Return categories
|
|
218
|
-
if (output === "categories") {
|
|
219
|
-
const categories = getCSSTokenCategories();
|
|
220
|
-
const total = categories.reduce((sum, c) => sum + c.count, 0);
|
|
221
|
-
return {
|
|
222
|
-
content: [
|
|
223
|
-
{
|
|
224
|
-
type: "text",
|
|
225
|
-
text: formatResponse({ categories, totalTokens: total }),
|
|
226
|
-
},
|
|
227
|
-
],
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
// Return themes
|
|
231
|
-
if (output === "themes") {
|
|
232
|
-
return {
|
|
233
|
-
content: [
|
|
234
|
-
{
|
|
235
|
-
type: "text",
|
|
236
|
-
text: formatResponse({
|
|
237
|
-
themes: AGENCY_THEMES,
|
|
238
|
-
usage: {
|
|
239
|
-
htmlAttribute: '<html data-theme="admin">',
|
|
240
|
-
cssClass: '<body class="nys-theme-admin">',
|
|
241
|
-
cssCustomProperty: "Themes modify --nys-color-theme-* tokens",
|
|
242
|
-
},
|
|
243
|
-
totalThemes: AGENCY_THEMES.length,
|
|
244
|
-
}),
|
|
245
|
-
},
|
|
246
|
-
],
|
|
247
|
-
};
|
|
248
|
-
}
|
|
249
|
-
// Return tokens (default)
|
|
45
|
+
.describe("Free-text search across token names and descriptions. Omit to list all."),
|
|
46
|
+
category: z.enum(CATEGORY_ENUM).optional().describe("Filter by category"),
|
|
47
|
+
include: z
|
|
48
|
+
.enum(["recommended", "primitive", "all"])
|
|
49
|
+
.default("recommended")
|
|
50
|
+
.describe("'recommended' (default) excludes color primitives; 'primitive' returns only primitives; 'all' returns everything"),
|
|
51
|
+
}, TOKEN_TOOL_ANNOTATIONS, async ({ query, category, include }) => {
|
|
52
|
+
// Pick token set based on include value
|
|
250
53
|
let tokens;
|
|
251
|
-
if (
|
|
252
|
-
tokens =
|
|
54
|
+
if (include === "primitive") {
|
|
55
|
+
tokens = getPrimitiveTokens();
|
|
253
56
|
}
|
|
254
|
-
else if (
|
|
255
|
-
tokens =
|
|
57
|
+
else if (include === "all") {
|
|
58
|
+
tokens = getCSSTokens();
|
|
256
59
|
}
|
|
257
60
|
else {
|
|
258
|
-
tokens =
|
|
61
|
+
tokens = getRecommendedTokens();
|
|
259
62
|
}
|
|
260
|
-
//
|
|
261
|
-
const formatted = tokens.map((t) => {
|
|
262
|
-
const result = {
|
|
263
|
-
cssVariable: t.cssVariable,
|
|
264
|
-
cssValue: t.cssValue,
|
|
265
|
-
};
|
|
266
|
-
if (includeResolvedValues && t.resolvedValue) {
|
|
267
|
-
result.resolvedValue = t.resolvedValue;
|
|
268
|
-
}
|
|
269
|
-
if (includeDescriptions && t.description) {
|
|
270
|
-
result.description = t.description;
|
|
271
|
-
}
|
|
272
|
-
return result;
|
|
273
|
-
});
|
|
274
|
-
return {
|
|
275
|
-
content: [
|
|
276
|
-
{
|
|
277
|
-
type: "text",
|
|
278
|
-
text: formatResponse({ count: tokens.length, tokens: formatted }),
|
|
279
|
-
},
|
|
280
|
-
],
|
|
281
|
-
};
|
|
282
|
-
});
|
|
283
|
-
// -------------------------------------------------------------------------
|
|
284
|
-
// find_tokens - Search tokens
|
|
285
|
-
// -------------------------------------------------------------------------
|
|
286
|
-
server.tool("find_tokens", "Search for design tokens by CSS variable name, value, or description", {
|
|
287
|
-
query: z
|
|
288
|
-
.string()
|
|
289
|
-
.describe("Search query to match against CSS variable names, values, and descriptions"),
|
|
290
|
-
category: z
|
|
291
|
-
.enum([
|
|
292
|
-
"color",
|
|
293
|
-
"font",
|
|
294
|
-
"space",
|
|
295
|
-
"size",
|
|
296
|
-
"radius",
|
|
297
|
-
"shadow",
|
|
298
|
-
"border",
|
|
299
|
-
"form",
|
|
300
|
-
"gutter",
|
|
301
|
-
"icon",
|
|
302
|
-
])
|
|
303
|
-
.optional()
|
|
304
|
-
.describe("Optionally filter results to a specific category"),
|
|
305
|
-
}, async ({ query, category }) => {
|
|
306
|
-
let results = searchCSSTokens(query);
|
|
63
|
+
// Apply category filter
|
|
307
64
|
if (category) {
|
|
308
|
-
|
|
65
|
+
tokens = tokens.filter((t) => t.category.toLowerCase() === category.toLowerCase());
|
|
66
|
+
}
|
|
67
|
+
// Apply query filter (case-insensitive match on cssVariable or description)
|
|
68
|
+
if (query) {
|
|
69
|
+
const lowerQuery = query.toLowerCase();
|
|
70
|
+
tokens = tokens.filter((t) => t.cssVariable.toLowerCase().includes(lowerQuery) ||
|
|
71
|
+
t.description?.toLowerCase().includes(lowerQuery));
|
|
309
72
|
}
|
|
310
|
-
const
|
|
73
|
+
const results = tokens.map((t) => ({
|
|
311
74
|
cssVariable: t.cssVariable,
|
|
312
|
-
cssValue: t.cssValue,
|
|
313
75
|
description: t.description,
|
|
314
76
|
category: t.category,
|
|
315
77
|
}));
|
|
@@ -317,46 +79,35 @@ export function registerTokenTools(server) {
|
|
|
317
79
|
content: [
|
|
318
80
|
{
|
|
319
81
|
type: "text",
|
|
320
|
-
text:
|
|
321
|
-
query,
|
|
322
|
-
count: results.length,
|
|
323
|
-
results: formatted,
|
|
324
|
-
}),
|
|
82
|
+
text: JSON.stringify({ count: results.length, results }, null, 2),
|
|
325
83
|
},
|
|
326
84
|
],
|
|
327
85
|
};
|
|
328
86
|
});
|
|
329
87
|
// -------------------------------------------------------------------------
|
|
330
|
-
//
|
|
88
|
+
// get_token - Get full details for a specific token (deep dive)
|
|
331
89
|
// -------------------------------------------------------------------------
|
|
332
|
-
server.tool("
|
|
90
|
+
server.tool("get_token", "Get full details for a specific design token including resolved values and alternatives.", {
|
|
333
91
|
token: z
|
|
334
92
|
.string()
|
|
335
93
|
.describe('CSS variable name (e.g., "--nys-color-text" or "color-text")'),
|
|
336
|
-
|
|
337
|
-
.enum(["text", "background", "border", "icon"])
|
|
338
|
-
.optional()
|
|
339
|
-
.describe("Optional: validate token usage for a specific context. When provided, includes recommendations and warnings."),
|
|
340
|
-
}, async ({ token, context }) => {
|
|
94
|
+
}, TOKEN_TOOL_ANNOTATIONS, async ({ token }) => {
|
|
341
95
|
const tokenInfo = getCSSTokenByVariable(token);
|
|
342
96
|
if (!tokenInfo) {
|
|
343
97
|
return {
|
|
344
98
|
content: [
|
|
345
99
|
{
|
|
346
100
|
type: "text",
|
|
347
|
-
text:
|
|
101
|
+
text: JSON.stringify({
|
|
348
102
|
error: `Token not found: ${token}`,
|
|
349
|
-
suggestion: "
|
|
350
|
-
}),
|
|
103
|
+
suggestion: "Use find_tokens to search for available tokens",
|
|
104
|
+
}, null, 2),
|
|
351
105
|
},
|
|
352
106
|
],
|
|
107
|
+
isError: true,
|
|
353
108
|
};
|
|
354
109
|
}
|
|
355
|
-
|
|
356
|
-
const graph = buildTokenGraph();
|
|
357
|
-
const node = graph.get(tokenInfo.cssVariable);
|
|
358
|
-
const usedBy = node?.usedBy || [];
|
|
359
|
-
// Base token info
|
|
110
|
+
const alternatives = getAlternativeTokens(tokenInfo);
|
|
360
111
|
const result = {
|
|
361
112
|
cssVariable: tokenInfo.cssVariable,
|
|
362
113
|
cssValue: tokenInfo.cssValue,
|
|
@@ -364,30 +115,14 @@ export function registerTokenTools(server) {
|
|
|
364
115
|
description: tokenInfo.description,
|
|
365
116
|
category: tokenInfo.category,
|
|
366
117
|
layer: tokenInfo.layer,
|
|
367
|
-
|
|
368
|
-
usage: `var(${tokenInfo.cssVariable})`,
|
|
118
|
+
alternatives,
|
|
369
119
|
resourceUri: "nysds://tokens",
|
|
370
120
|
};
|
|
371
|
-
// If context provided, add validation info
|
|
372
|
-
if (context) {
|
|
373
|
-
const validation = validateTokenInContext(tokenInfo, context);
|
|
374
|
-
result.validation = {
|
|
375
|
-
context,
|
|
376
|
-
valid: validation.valid,
|
|
377
|
-
recommendations: validation.recommendations.length > 0
|
|
378
|
-
? validation.recommendations
|
|
379
|
-
: undefined,
|
|
380
|
-
warnings: validation.warnings,
|
|
381
|
-
alternatives: validation.alternatives.length > 0
|
|
382
|
-
? validation.alternatives
|
|
383
|
-
: undefined,
|
|
384
|
-
};
|
|
385
|
-
}
|
|
386
121
|
return {
|
|
387
122
|
content: [
|
|
388
123
|
{
|
|
389
124
|
type: "text",
|
|
390
|
-
text:
|
|
125
|
+
text: JSON.stringify(result, null, 2),
|
|
391
126
|
},
|
|
392
127
|
],
|
|
393
128
|
};
|
|
@@ -401,18 +136,7 @@ export function registerTokenTools(server) {
|
|
|
401
136
|
.default("all")
|
|
402
137
|
.describe("Filter the graph to specific token types"),
|
|
403
138
|
category: z
|
|
404
|
-
.enum(
|
|
405
|
-
"color",
|
|
406
|
-
"font",
|
|
407
|
-
"space",
|
|
408
|
-
"size",
|
|
409
|
-
"radius",
|
|
410
|
-
"shadow",
|
|
411
|
-
"border",
|
|
412
|
-
"form",
|
|
413
|
-
"gutter",
|
|
414
|
-
"icon",
|
|
415
|
-
])
|
|
139
|
+
.enum(CATEGORY_ENUM)
|
|
416
140
|
.optional()
|
|
417
141
|
.describe("Filter to a specific category"),
|
|
418
142
|
limit: z
|
|
@@ -422,7 +146,7 @@ export function registerTokenTools(server) {
|
|
|
422
146
|
.max(100)
|
|
423
147
|
.default(20)
|
|
424
148
|
.describe("Maximum number of tokens to return (default: 20)"),
|
|
425
|
-
}, async ({ filter, category, limit }) => {
|
|
149
|
+
}, TOKEN_TOOL_ANNOTATIONS, async ({ filter, category, limit }) => {
|
|
426
150
|
const graph = buildTokenGraph();
|
|
427
151
|
const tokens = getCSSTokens();
|
|
428
152
|
// Build lookup for categories
|
|
@@ -430,7 +154,8 @@ export function registerTokenTools(server) {
|
|
|
430
154
|
for (const t of tokens) {
|
|
431
155
|
tokenCategories.set(t.cssVariable, t.category);
|
|
432
156
|
}
|
|
433
|
-
|
|
157
|
+
const allNodes = Array.from(graph.values());
|
|
158
|
+
let nodes = allNodes;
|
|
434
159
|
// Apply category filter
|
|
435
160
|
if (category) {
|
|
436
161
|
nodes = nodes.filter((n) => tokenCategories.get(n.cssVariable) === category);
|
|
@@ -448,8 +173,6 @@ export function registerTokenTools(server) {
|
|
|
448
173
|
}
|
|
449
174
|
// Apply limit
|
|
450
175
|
nodes = nodes.slice(0, limit);
|
|
451
|
-
// Calculate stats
|
|
452
|
-
const allNodes = Array.from(graph.values());
|
|
453
176
|
const stats = {
|
|
454
177
|
totalTokens: allNodes.length,
|
|
455
178
|
aliasTokens: allNodes.filter((n) => n.referencesVariable).length,
|
|
@@ -467,7 +190,7 @@ export function registerTokenTools(server) {
|
|
|
467
190
|
content: [
|
|
468
191
|
{
|
|
469
192
|
type: "text",
|
|
470
|
-
text:
|
|
193
|
+
text: JSON.stringify({
|
|
471
194
|
filter,
|
|
472
195
|
category: category || "all",
|
|
473
196
|
nodes: nodes.map((n) => ({
|
|
@@ -476,7 +199,7 @@ export function registerTokenTools(server) {
|
|
|
476
199
|
usedBy: n.usedBy.length > 0 ? n.usedBy : undefined,
|
|
477
200
|
})),
|
|
478
201
|
stats,
|
|
479
|
-
}),
|
|
202
|
+
}, null, 2),
|
|
480
203
|
},
|
|
481
204
|
],
|
|
482
205
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nysds/mcp-server",
|
|
3
|
-
"version": "1.18.
|
|
3
|
+
"version": "1.18.3",
|
|
4
4
|
"description": "MCP server for the New York State Design System. Exposes components, tokens, and documentation to AI assistants.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -30,8 +30,8 @@
|
|
|
30
30
|
"zod": "^3.25"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
|
-
"@nysds/styles": "^1.18.
|
|
34
|
-
"@nysds/tokens": "^1.18.
|
|
33
|
+
"@nysds/styles": "^1.18.3",
|
|
34
|
+
"@nysds/tokens": "^1.18.3",
|
|
35
35
|
"@types/node": "^22.0.0",
|
|
36
36
|
"typescript": "^5.9.3"
|
|
37
37
|
},
|