@nysds/mcp-server 1.0.0 → 1.14.0

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.
Files changed (43) hide show
  1. package/dist/index.d.ts +9 -0
  2. package/dist/index.d.ts.map +1 -0
  3. package/dist/index.js +16 -0
  4. package/dist/lib/cem-parser.d.ts +96 -0
  5. package/dist/lib/cem-parser.d.ts.map +1 -0
  6. package/dist/lib/cem-parser.js +82 -0
  7. package/dist/lib/search.d.ts +20 -0
  8. package/dist/lib/search.d.ts.map +1 -0
  9. package/dist/lib/search.js +87 -0
  10. package/dist/lib/token-parser.d.ts +140 -0
  11. package/dist/lib/token-parser.d.ts.map +1 -0
  12. package/dist/lib/token-parser.js +458 -0
  13. package/dist/prompts/nysds-mode.d.ts +8 -0
  14. package/dist/prompts/nysds-mode.d.ts.map +1 -0
  15. package/dist/prompts/nysds-mode.js +51 -0
  16. package/dist/resources/components.d.ts +12 -0
  17. package/dist/resources/components.d.ts.map +1 -0
  18. package/dist/resources/components.js +62 -0
  19. package/dist/resources/guides.d.ts +11 -0
  20. package/dist/resources/guides.d.ts.map +1 -0
  21. package/dist/resources/guides.js +80 -0
  22. package/dist/resources/index.d.ts +8 -0
  23. package/dist/resources/index.d.ts.map +1 -0
  24. package/dist/resources/index.js +13 -0
  25. package/dist/resources/tokens.d.ts +17 -0
  26. package/dist/resources/tokens.d.ts.map +1 -0
  27. package/dist/resources/tokens.js +312 -0
  28. package/dist/server.d.ts +11 -0
  29. package/dist/server.d.ts.map +1 -0
  30. package/dist/server.js +30 -0
  31. package/dist/tools/component-tools.d.ts +14 -0
  32. package/dist/tools/component-tools.d.ts.map +1 -0
  33. package/dist/tools/component-tools.js +127 -0
  34. package/dist/tools/index.d.ts +8 -0
  35. package/dist/tools/index.d.ts.map +1 -0
  36. package/dist/tools/index.js +13 -0
  37. package/dist/tools/token-tools.d.ts +17 -0
  38. package/dist/tools/token-tools.d.ts.map +1 -0
  39. package/dist/tools/token-tools.js +504 -0
  40. package/dist/tools/validation-tools.d.ts +12 -0
  41. package/dist/tools/validation-tools.d.ts.map +1 -0
  42. package/dist/tools/validation-tools.js +222 -0
  43. package/package.json +1 -1
@@ -0,0 +1,458 @@
1
+ /**
2
+ * Design Token Parser
3
+ *
4
+ * Reads and parses NYSDS design tokens with a CSS-centric approach.
5
+ * Returns data aligned with tokens.css output (not JSON internals).
6
+ *
7
+ * Key transformations:
8
+ * - Token paths are converted to CSS variable names
9
+ * - Alias references become var() expressions
10
+ * - Layer prefixes (primitive, applied) are stripped
11
+ */
12
+ import { readFileSync, existsSync } from "node:fs";
13
+ import { resolve, dirname } from "node:path";
14
+ import { fileURLToPath } from "node:url";
15
+ // ESM path resolution
16
+ const __filename = fileURLToPath(import.meta.url);
17
+ const __dirname = dirname(__filename);
18
+ // ============================================================================
19
+ // Token Data Cache
20
+ // ============================================================================
21
+ let cachedLegacyTokens = null;
22
+ let cachedCSSTokens = null;
23
+ let cachedTokenGraph = null;
24
+ let cachedRawTokens = null;
25
+ // ============================================================================
26
+ // Path Resolution
27
+ // ============================================================================
28
+ /**
29
+ * Get the path to tokens.json file
30
+ * Uses ESM-compatible path resolution with fallbacks for different contexts
31
+ */
32
+ export function getTokensPath() {
33
+ // Fallback paths for different execution contexts
34
+ const possiblePaths = [
35
+ // From lib/ directory (normal execution)
36
+ resolve(__dirname, "../../../../tokens/src/tokens.json"),
37
+ // From mcp-server package root
38
+ resolve(__dirname, "../../../tokens/src/tokens.json"),
39
+ // From monorepo root
40
+ resolve(__dirname, "../../../../../packages/tokens/src/tokens.json"),
41
+ // Direct path from monorepo root
42
+ resolve(process.cwd(), "packages/tokens/src/tokens.json"),
43
+ // From mcp-server package
44
+ resolve(process.cwd(), "../tokens/src/tokens.json"),
45
+ ];
46
+ for (const path of possiblePaths) {
47
+ if (existsSync(path)) {
48
+ return path;
49
+ }
50
+ }
51
+ return null;
52
+ }
53
+ /**
54
+ * Get the path to tokens.css file
55
+ */
56
+ export function getTokensCSSPath() {
57
+ const possiblePaths = [
58
+ resolve(__dirname, "../../../../tokens/dist/tokens.css"),
59
+ resolve(__dirname, "../../../tokens/dist/tokens.css"),
60
+ resolve(__dirname, "../../../../../packages/tokens/dist/tokens.css"),
61
+ resolve(process.cwd(), "packages/tokens/dist/tokens.css"),
62
+ resolve(process.cwd(), "../tokens/dist/tokens.css"),
63
+ ];
64
+ for (const path of possiblePaths) {
65
+ if (existsSync(path)) {
66
+ return path;
67
+ }
68
+ }
69
+ return null;
70
+ }
71
+ // ============================================================================
72
+ // CSS Variable Transformation
73
+ // ============================================================================
74
+ /**
75
+ * Transform a JSON token path to CSS variable name
76
+ *
77
+ * Examples:
78
+ * - "primitive.color.neutral.900" → "--nys-color-neutral-900"
79
+ * - "applied.color.text.default" → "--nys-color-text"
80
+ * - "color.theme.default" → "--nys-color-theme"
81
+ * - "font.size.md" → "--nys-font-size-md"
82
+ */
83
+ export function toCSSVariable(jsonPath) {
84
+ let name = "--nys-" +
85
+ jsonPath
86
+ // Strip layer prefixes
87
+ .replace(/^(primitive|applied|appearance|theme)\./, "")
88
+ // Dots to hyphens
89
+ .replace(/\./g, "-");
90
+ // Strip trailing -default suffix
91
+ name = name.replace(/-default$/, "");
92
+ return name;
93
+ }
94
+ /**
95
+ * Convert an alias reference to CSS var() syntax
96
+ *
97
+ * Examples:
98
+ * - "{primitive.color.neutral.900}" → "var(--nys-color-neutral-900)"
99
+ * - "{font.size.md}" → "var(--nys-font-size-md)"
100
+ */
101
+ export function aliasToVarRef(aliasValue) {
102
+ // Extract the path from {path.to.token}
103
+ const match = aliasValue.match(/^\{(.+)\}$/);
104
+ if (!match) {
105
+ return { cssValue: aliasValue, referencesVariable: "" };
106
+ }
107
+ const referencesVariable = toCSSVariable(match[1]);
108
+ const cssValue = `var(${referencesVariable})`;
109
+ return { cssValue, referencesVariable };
110
+ }
111
+ /**
112
+ * Determine the category from a JSON path
113
+ */
114
+ function getCategoryFromPath(jsonPath) {
115
+ const parts = jsonPath.split(".");
116
+ // Skip layer prefix if present
117
+ const startIndex = ["primitive", "applied", "appearance", "theme"].includes(parts[0])
118
+ ? 1
119
+ : 0;
120
+ return parts[startIndex] || "unknown";
121
+ }
122
+ /**
123
+ * Determine the layer from a JSON path
124
+ *
125
+ * Layers:
126
+ * - primitive: Raw values (colors, sizes, fonts, spacing, etc.)
127
+ * - applied: Semantic tokens that reference primitives (includes color.theme.* defaults)
128
+ * - theme: Agency theme overrides
129
+ * - appearance: Light/dark mode variations
130
+ */
131
+ function getLayerFromPath(jsonPath) {
132
+ const parts = jsonPath.split(".");
133
+ // Check for explicit layer prefixes
134
+ if (["primitive", "applied", "appearance", "theme"].includes(parts[0])) {
135
+ return parts[0];
136
+ }
137
+ // color.theme.* tokens are applied semantic tokens (agency themes override these)
138
+ if (parts[0] === "color" && parts[1] === "theme") {
139
+ return "applied";
140
+ }
141
+ // Non-prefixed categories (space, size, font, radius, etc.) contain raw values
142
+ // so they are classified as "primitive"
143
+ return "primitive";
144
+ }
145
+ // ============================================================================
146
+ // Token Parsing
147
+ // ============================================================================
148
+ /**
149
+ * Load raw token data from tokens.json
150
+ */
151
+ function loadRawTokens() {
152
+ if (cachedRawTokens) {
153
+ return cachedRawTokens;
154
+ }
155
+ const tokensPath = getTokensPath();
156
+ if (!tokensPath) {
157
+ console.error("Warning: No tokens file found");
158
+ return null;
159
+ }
160
+ try {
161
+ const content = readFileSync(tokensPath, "utf-8");
162
+ cachedRawTokens = JSON.parse(content);
163
+ return cachedRawTokens;
164
+ }
165
+ catch (error) {
166
+ console.error("Warning: Could not parse tokens file:", error);
167
+ return null;
168
+ }
169
+ }
170
+ /**
171
+ * Parse tokens recursively into CSS-centric format
172
+ */
173
+ function parseCSSTokens(obj, prefix = "", resolvedValues = new Map()) {
174
+ const tokens = [];
175
+ for (const [key, value] of Object.entries(obj)) {
176
+ if (key.startsWith("$"))
177
+ continue; // Skip meta properties
178
+ const jsonPath = prefix ? `${prefix}.${key}` : key;
179
+ if (typeof value === "object" &&
180
+ value !== null &&
181
+ "$value" in value) {
182
+ // This is a token
183
+ const tokenObj = value;
184
+ const rawValue = tokenObj.$value;
185
+ const description = tokenObj.$description;
186
+ const cssVariable = toCSSVariable(jsonPath);
187
+ const category = getCategoryFromPath(jsonPath);
188
+ const layer = getLayerFromPath(jsonPath);
189
+ let cssValue;
190
+ let referencesVariable;
191
+ let resolvedValue;
192
+ // Handle different value types
193
+ if (typeof rawValue === "string" && rawValue.startsWith("{")) {
194
+ // Alias reference
195
+ const aliasResult = aliasToVarRef(rawValue);
196
+ cssValue = aliasResult.cssValue;
197
+ referencesVariable = aliasResult.referencesVariable;
198
+ // Try to resolve the value
199
+ resolvedValue = resolvedValues.get(referencesVariable);
200
+ }
201
+ else if (Array.isArray(rawValue)) {
202
+ // Complex value (like shadows) - format as string
203
+ cssValue = JSON.stringify(rawValue);
204
+ resolvedValue = cssValue;
205
+ }
206
+ else if (typeof rawValue === "object" && rawValue !== null) {
207
+ // Object value (like single shadow)
208
+ cssValue = JSON.stringify(rawValue);
209
+ resolvedValue = cssValue;
210
+ }
211
+ else {
212
+ // Direct value
213
+ cssValue = String(rawValue);
214
+ resolvedValue = cssValue;
215
+ }
216
+ // Store resolved value for other tokens to reference
217
+ if (resolvedValue) {
218
+ resolvedValues.set(cssVariable, resolvedValue);
219
+ }
220
+ tokens.push({
221
+ cssVariable,
222
+ cssValue,
223
+ referencesVariable,
224
+ resolvedValue,
225
+ description,
226
+ category,
227
+ layer,
228
+ jsonPath,
229
+ });
230
+ }
231
+ else if (typeof value === "object" && value !== null) {
232
+ // Recurse into nested group
233
+ tokens.push(...parseCSSTokens(value, jsonPath, resolvedValues));
234
+ }
235
+ }
236
+ return tokens;
237
+ }
238
+ /**
239
+ * Resolve all alias values to their final resolved values
240
+ */
241
+ function resolveAllValues(tokens) {
242
+ const byVariable = new Map();
243
+ for (const token of tokens) {
244
+ byVariable.set(token.cssVariable, token);
245
+ }
246
+ // Iterate to resolve nested aliases (max 10 levels to prevent infinite loops)
247
+ for (let i = 0; i < 10; i++) {
248
+ let changed = false;
249
+ for (const token of tokens) {
250
+ if (token.referencesVariable && !token.resolvedValue) {
251
+ const referenced = byVariable.get(token.referencesVariable);
252
+ if (referenced?.resolvedValue) {
253
+ token.resolvedValue = referenced.resolvedValue;
254
+ changed = true;
255
+ }
256
+ }
257
+ }
258
+ if (!changed)
259
+ break;
260
+ }
261
+ }
262
+ // ============================================================================
263
+ // Token Graph
264
+ // ============================================================================
265
+ /**
266
+ * Build a dependency graph of tokens
267
+ * Shows which tokens reference which, and which tokens are used by which
268
+ */
269
+ export function buildTokenGraph() {
270
+ if (cachedTokenGraph) {
271
+ return cachedTokenGraph;
272
+ }
273
+ const tokens = getCSSTokens();
274
+ const graph = new Map();
275
+ // Initialize all nodes
276
+ for (const token of tokens) {
277
+ graph.set(token.cssVariable, {
278
+ cssVariable: token.cssVariable,
279
+ referencesVariable: token.referencesVariable,
280
+ usedBy: [],
281
+ });
282
+ }
283
+ // Build usedBy relationships
284
+ for (const token of tokens) {
285
+ if (token.referencesVariable) {
286
+ const referenced = graph.get(token.referencesVariable);
287
+ if (referenced) {
288
+ referenced.usedBy.push(token.cssVariable);
289
+ }
290
+ }
291
+ }
292
+ cachedTokenGraph = graph;
293
+ return graph;
294
+ }
295
+ // ============================================================================
296
+ // Public API - CSS-Centric
297
+ // ============================================================================
298
+ /**
299
+ * Get all tokens in CSS-centric format
300
+ */
301
+ export function getCSSTokens() {
302
+ if (cachedCSSTokens) {
303
+ return cachedCSSTokens;
304
+ }
305
+ const rawTokens = loadRawTokens();
306
+ if (!rawTokens) {
307
+ cachedCSSTokens = [];
308
+ return cachedCSSTokens;
309
+ }
310
+ cachedCSSTokens = parseCSSTokens(rawTokens);
311
+ resolveAllValues(cachedCSSTokens);
312
+ return cachedCSSTokens;
313
+ }
314
+ /**
315
+ * Get CSS tokens filtered by category
316
+ */
317
+ export function getCSSTokensByCategory(category) {
318
+ const tokens = getCSSTokens();
319
+ return tokens.filter((t) => t.category.toLowerCase() === category.toLowerCase());
320
+ }
321
+ /**
322
+ * Get CSS tokens filtered by layer
323
+ */
324
+ export function getCSSTokensByLayer(layer) {
325
+ const tokens = getCSSTokens();
326
+ return tokens.filter((t) => t.layer.toLowerCase() === layer.toLowerCase());
327
+ }
328
+ /**
329
+ * Search CSS tokens by variable name, value, or description
330
+ */
331
+ export function searchCSSTokens(query) {
332
+ const tokens = getCSSTokens();
333
+ const lowerQuery = query.toLowerCase();
334
+ return tokens.filter((t) => t.cssVariable.toLowerCase().includes(lowerQuery) ||
335
+ t.cssValue.toLowerCase().includes(lowerQuery) ||
336
+ t.resolvedValue?.toLowerCase().includes(lowerQuery) ||
337
+ t.description?.toLowerCase().includes(lowerQuery));
338
+ }
339
+ /**
340
+ * Get a single token by CSS variable name
341
+ */
342
+ export function getCSSTokenByVariable(variableName) {
343
+ const tokens = getCSSTokens();
344
+ // Normalize: accept with or without -- prefix
345
+ const normalized = variableName.startsWith("--")
346
+ ? variableName
347
+ : `--nys-${variableName}`;
348
+ return tokens.find((t) => t.cssVariable === normalized);
349
+ }
350
+ /**
351
+ * Get all unique categories
352
+ */
353
+ export function getCSSTokenCategories() {
354
+ const tokens = getCSSTokens();
355
+ const counts = new Map();
356
+ for (const token of tokens) {
357
+ counts.set(token.category, (counts.get(token.category) || 0) + 1);
358
+ }
359
+ return Array.from(counts.entries())
360
+ .map(([category, count]) => ({ category, count }))
361
+ .sort((a, b) => a.category.localeCompare(b.category));
362
+ }
363
+ /**
364
+ * Get raw tokens.css content
365
+ */
366
+ export function getTokensCSS() {
367
+ const cssPath = getTokensCSSPath();
368
+ if (!cssPath) {
369
+ return null;
370
+ }
371
+ try {
372
+ return readFileSync(cssPath, "utf-8");
373
+ }
374
+ catch {
375
+ return null;
376
+ }
377
+ }
378
+ // ============================================================================
379
+ // Public API - Legacy (Backward Compatible)
380
+ // ============================================================================
381
+ /**
382
+ * Parse DTCG format tokens recursively (legacy format)
383
+ */
384
+ function parseDTCGTokens(obj, prefix = "", category = "") {
385
+ const tokens = [];
386
+ for (const [key, value] of Object.entries(obj)) {
387
+ if (key.startsWith("$"))
388
+ continue; // Skip meta properties
389
+ const name = prefix ? `${prefix}.${key}` : key;
390
+ const currentCategory = category || key;
391
+ if (typeof value === "object" &&
392
+ value !== null &&
393
+ "$value" in value) {
394
+ // This is a token
395
+ const tokenObj = value;
396
+ tokens.push({
397
+ name,
398
+ value: String(tokenObj.$value),
399
+ category: currentCategory,
400
+ description: tokenObj.$description,
401
+ });
402
+ }
403
+ else if (typeof value === "object" && value !== null) {
404
+ // Recurse into nested group
405
+ tokens.push(...parseDTCGTokens(value, name, currentCategory));
406
+ }
407
+ }
408
+ return tokens;
409
+ }
410
+ /**
411
+ * Load all design tokens (legacy format)
412
+ */
413
+ export function getAllTokens() {
414
+ if (cachedLegacyTokens) {
415
+ return cachedLegacyTokens;
416
+ }
417
+ const rawTokens = loadRawTokens();
418
+ if (!rawTokens) {
419
+ cachedLegacyTokens = [];
420
+ return cachedLegacyTokens;
421
+ }
422
+ cachedLegacyTokens = parseDTCGTokens(rawTokens);
423
+ return cachedLegacyTokens;
424
+ }
425
+ /**
426
+ * Get tokens filtered by category (legacy format)
427
+ */
428
+ export function getTokensByCategory(category) {
429
+ const tokens = getAllTokens();
430
+ return tokens.filter((t) => t.category.toLowerCase() === category.toLowerCase());
431
+ }
432
+ /**
433
+ * Search tokens by name or value (legacy format)
434
+ */
435
+ export function searchTokens(query) {
436
+ const tokens = getAllTokens();
437
+ const lowerQuery = query.toLowerCase();
438
+ return tokens.filter((t) => t.name.toLowerCase().includes(lowerQuery) ||
439
+ t.value.toLowerCase().includes(lowerQuery) ||
440
+ t.description?.toLowerCase().includes(lowerQuery));
441
+ }
442
+ /**
443
+ * Get available token categories (legacy format)
444
+ */
445
+ export function getTokenCategories() {
446
+ const tokens = getAllTokens();
447
+ const categories = new Set(tokens.map((t) => t.category));
448
+ return Array.from(categories).sort();
449
+ }
450
+ /**
451
+ * Clear all cached tokens (useful for testing)
452
+ */
453
+ export function clearTokenCache() {
454
+ cachedLegacyTokens = null;
455
+ cachedCSSTokens = null;
456
+ cachedTokenGraph = null;
457
+ cachedRawTokens = null;
458
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * NYSDS Mode Prompt
3
+ *
4
+ * Activates NYSDS-aware coding assistance.
5
+ */
6
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
7
+ export declare function registerPrompts(server: McpServer): void;
8
+ //# sourceMappingURL=nysds-mode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nysds-mode.d.ts","sourceRoot":"","sources":["../../src/prompts/nysds-mode.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,wBAAgB,eAAe,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAkDvD"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * NYSDS Mode Prompt
3
+ *
4
+ * Activates NYSDS-aware coding assistance.
5
+ */
6
+ export function registerPrompts(server) {
7
+ server.prompt("nysds_mode", "Activates NYSDS-aware coding assistance with knowledge of components, tokens, and best practices", {}, async () => {
8
+ return {
9
+ messages: [
10
+ {
11
+ role: "user",
12
+ content: {
13
+ type: "text",
14
+ text: `You are now in NYSDS (New York State Design System) mode. You have access to comprehensive knowledge about NYSDS web components and design tokens.
15
+
16
+ ## Your Capabilities
17
+
18
+ 1. **Component Knowledge**: You can list, search, and provide detailed documentation for all NYSDS web components using the available tools.
19
+
20
+ 2. **Design Tokens**: You can access and explain NYSDS design tokens for colors, spacing, typography, and more.
21
+
22
+ 3. **Code Generation**: When generating code that uses UI components, prefer NYSDS components over generic HTML or other libraries.
23
+
24
+ 4. **Validation**: You can validate component usage to ensure correct attribute and property usage.
25
+
26
+ 5. **Framework Integration**: You can provide setup guides for various frameworks (React, Angular, Vue, .NET, Drupal).
27
+
28
+ ## Best Practices
29
+
30
+ - Always use semantic NYSDS components (e.g., \`<nys-button>\` instead of \`<button>\`)
31
+ - Use NYSDS design tokens via CSS custom properties for consistent styling
32
+ - Follow accessibility guidelines built into NYSDS components
33
+ - Reference the official documentation at https://designsystem.ny.gov/
34
+
35
+ ## Available Tools
36
+
37
+ - \`list_components\`: See all available components
38
+ - \`get_component_docs\`: Get detailed docs for a specific component
39
+ - \`find_components\`: Search for components by functionality
40
+ - \`get_design_tokens\`: Access design token values
41
+ - \`validate_component_api\`: Validate component usage
42
+ - \`setup_framework\`: Get framework-specific setup guides
43
+ - \`get_usage_guide\`: General installation and usage guide
44
+
45
+ When helping with UI development for New York State projects, prioritize NYSDS components and patterns.`,
46
+ },
47
+ },
48
+ ],
49
+ };
50
+ });
51
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Component Resources
3
+ *
4
+ * MCP resources for NYSDS component documentation.
5
+ *
6
+ * P0 Resources:
7
+ * - nysds://components - Component overview list
8
+ * - nysds://component/{tag} - Individual component docs
9
+ */
10
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
11
+ export declare function registerComponentResources(server: McpServer): void;
12
+ //# sourceMappingURL=components.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../src/resources/components.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAiElE"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Component Resources
3
+ *
4
+ * MCP resources for NYSDS component documentation.
5
+ *
6
+ * P0 Resources:
7
+ * - nysds://components - Component overview list
8
+ * - nysds://component/{tag} - Individual component docs
9
+ */
10
+ import { getAllComponents, getComponent } from "../lib/cem-parser.js";
11
+ export function registerComponentResources(server) {
12
+ // nysds://components - Component overview list
13
+ server.resource("components", "nysds://components", {
14
+ description: "List of all NYSDS web components with summaries",
15
+ mimeType: "application/json",
16
+ }, async () => {
17
+ const components = getAllComponents();
18
+ const list = components.map((c) => ({
19
+ tagName: c.tagName,
20
+ name: c.name,
21
+ summary: c.summary || c.description?.split("\n")[0] || "No description",
22
+ }));
23
+ return {
24
+ contents: [
25
+ {
26
+ uri: "nysds://components",
27
+ mimeType: "application/json",
28
+ text: JSON.stringify(list, null, 2),
29
+ },
30
+ ],
31
+ };
32
+ });
33
+ // nysds://component/{tag} - Individual component docs
34
+ server.resource("component", "nysds://component/{tag}", {
35
+ description: "Full documentation for a specific NYSDS component",
36
+ mimeType: "application/json",
37
+ }, async (uri) => {
38
+ // Extract tag from URI: nysds://component/nys-button -> nys-button
39
+ const tag = uri.pathname.split("/").pop() || "";
40
+ const component = getComponent(tag);
41
+ if (!component) {
42
+ return {
43
+ contents: [
44
+ {
45
+ uri: uri.href,
46
+ mimeType: "text/plain",
47
+ text: `Component "${tag}" not found`,
48
+ },
49
+ ],
50
+ };
51
+ }
52
+ return {
53
+ contents: [
54
+ {
55
+ uri: uri.href,
56
+ mimeType: "application/json",
57
+ text: JSON.stringify(component, null, 2),
58
+ },
59
+ ],
60
+ };
61
+ });
62
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Guide Resources
3
+ *
4
+ * MCP resources for NYSDS installation and usage guides.
5
+ *
6
+ * P0 Resources:
7
+ * - nysds://installation - Installation guide
8
+ */
9
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
10
+ export declare function registerGuideResources(server: McpServer): void;
11
+ //# sourceMappingURL=guides.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guides.d.ts","sourceRoot":"","sources":["../../src/resources/guides.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA6E9D"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Guide Resources
3
+ *
4
+ * MCP resources for NYSDS installation and usage guides.
5
+ *
6
+ * P0 Resources:
7
+ * - nysds://installation - Installation guide
8
+ */
9
+ export function registerGuideResources(server) {
10
+ // nysds://installation - Installation guide
11
+ server.resource("installation", "nysds://installation", {
12
+ description: "NYSDS installation and setup guide",
13
+ mimeType: "text/markdown",
14
+ }, async () => {
15
+ const guide = `# NYSDS Installation Guide
16
+
17
+ ## Quick Start
18
+
19
+ Install the NYSDS components package:
20
+
21
+ \`\`\`bash
22
+ npm install @nysds/components
23
+ \`\`\`
24
+
25
+ ## Import Components
26
+
27
+ ### Option 1: Import All Components
28
+
29
+ \`\`\`javascript
30
+ import '@nysds/components';
31
+ \`\`\`
32
+
33
+ ### Option 2: Import Individual Components
34
+
35
+ \`\`\`javascript
36
+ import '@nysds/components/nys-button';
37
+ import '@nysds/components/nys-alert';
38
+ \`\`\`
39
+
40
+ ## Include Styles
41
+
42
+ Import the base CSS for design tokens:
43
+
44
+ \`\`\`css
45
+ @import '@nysds/components/dist/styles.css';
46
+ \`\`\`
47
+
48
+ ## Usage
49
+
50
+ Once imported, use components as HTML elements:
51
+
52
+ \`\`\`html
53
+ <nys-button label="Submit" variant="primary"></nys-button>
54
+ <nys-alert type="success">Operation completed successfully!</nys-alert>
55
+ \`\`\`
56
+
57
+ ## Framework Integration
58
+
59
+ For framework-specific setup (React, Angular, Vue, etc.), use the \`setup_framework\` tool.
60
+
61
+ ## Browser Support
62
+
63
+ NYSDS components support all modern browsers (Chrome, Firefox, Safari, Edge).
64
+
65
+ ## Resources
66
+
67
+ - Documentation: https://designsystem.ny.gov/
68
+ - GitHub: https://github.com/ITS-HCD/nysds
69
+ `;
70
+ return {
71
+ contents: [
72
+ {
73
+ uri: "nysds://installation",
74
+ mimeType: "text/markdown",
75
+ text: guide,
76
+ },
77
+ ],
78
+ };
79
+ });
80
+ }