@nysds/mcp-server 1.16.0-alpha4 → 1.16.0-alpha5
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 +40 -44
- package/data/guides/fonts.md +77 -0
- package/data/guides/form-validation.md +169 -0
- package/data/guides/frameworks/angular.md +71 -0
- package/data/guides/frameworks/dotnet.md +42 -0
- package/data/guides/frameworks/drupal.md +39 -0
- package/data/guides/frameworks/react.md +45 -0
- package/data/guides/frameworks/vanilla.md +45 -0
- package/data/guides/installation.md +73 -0
- package/data/guides/page-structure.md +160 -0
- package/data/guides/styles.md +48 -0
- package/dist/lib/cem-parser.d.ts +6 -0
- package/dist/lib/cem-parser.d.ts.map +1 -1
- package/dist/lib/cem-parser.js +18 -9
- package/dist/lib/format.d.ts +22 -0
- package/dist/lib/format.d.ts.map +1 -0
- package/dist/lib/format.js +33 -0
- package/dist/prompts/nysds-mode.d.ts.map +1 -1
- package/dist/prompts/nysds-mode.js +17 -8
- package/dist/resources/guides.d.ts.map +1 -1
- package/dist/resources/guides.js +22 -26
- package/dist/tools/component-tools.d.ts +3 -5
- package/dist/tools/component-tools.d.ts.map +1 -1
- package/dist/tools/component-tools.js +51 -85
- package/dist/tools/guide-tools.d.ts +9 -0
- package/dist/tools/guide-tools.d.ts.map +1 -0
- package/dist/tools/guide-tools.js +78 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +4 -0
- package/dist/tools/token-tools.d.ts +2 -5
- package/dist/tools/token-tools.d.ts.map +1 -1
- package/dist/tools/token-tools.js +88 -108
- package/dist/tools/utility-tools.d.ts +8 -0
- package/dist/tools/utility-tools.d.ts.map +1 -0
- package/dist/tools/utility-tools.js +282 -0
- package/dist/tools/validation-tools.d.ts +1 -2
- package/dist/tools/validation-tools.d.ts.map +1 -1
- package/dist/tools/validation-tools.js +1 -163
- package/package.json +3 -2
|
@@ -3,123 +3,89 @@
|
|
|
3
3
|
*
|
|
4
4
|
* MCP tools for working with NYSDS components.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* -
|
|
8
|
-
* -
|
|
9
|
-
* - find_components: Search by name/description (fuzzy)
|
|
10
|
-
* - get_usage_guide: Installation and usage patterns
|
|
6
|
+
* Tools:
|
|
7
|
+
* - find_components: Search or list all components
|
|
8
|
+
* - get_component: Full documentation for a specific component
|
|
11
9
|
*/
|
|
12
10
|
import { z } from "zod";
|
|
13
11
|
import { getComponent, getAllComponents } from "../lib/cem-parser.js";
|
|
14
12
|
import { searchComponents } from "../lib/search.js";
|
|
15
13
|
export function registerComponentTools(server) {
|
|
16
|
-
//
|
|
17
|
-
server.tool("
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
14
|
+
// find_components - Search or list all components
|
|
15
|
+
server.tool("find_components", "Search for NYSDS components by name or description. Omit query to list all components.", {
|
|
16
|
+
query: z
|
|
17
|
+
.string()
|
|
18
|
+
.optional()
|
|
19
|
+
.describe("Search query to match against component names and descriptions. Omit to list all components."),
|
|
20
|
+
}, async ({ query }) => {
|
|
21
|
+
// If no query, return all components
|
|
22
|
+
if (!query || query.trim() === "") {
|
|
23
|
+
const components = getAllComponents();
|
|
24
|
+
const list = components.map((c) => ({
|
|
25
|
+
tagName: c.tagName,
|
|
26
|
+
name: c.name,
|
|
27
|
+
summary: c.summary || c.description?.split("\n")[0] || "No description",
|
|
28
|
+
resourceUri: `nysds://component/${c.tagName}`,
|
|
29
|
+
}));
|
|
30
|
+
return {
|
|
31
|
+
content: [
|
|
32
|
+
{
|
|
33
|
+
type: "text",
|
|
34
|
+
text: JSON.stringify(list, null, 2),
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
// Otherwise search
|
|
40
|
+
const results = searchComponents(query).map((r) => ({
|
|
41
|
+
...r,
|
|
42
|
+
resourceUri: `nysds://component/${r.tagName}`,
|
|
23
43
|
}));
|
|
24
44
|
return {
|
|
25
45
|
content: [
|
|
26
46
|
{
|
|
27
47
|
type: "text",
|
|
28
|
-
text: JSON.stringify(
|
|
48
|
+
text: JSON.stringify(results, null, 2),
|
|
29
49
|
},
|
|
30
50
|
],
|
|
31
51
|
};
|
|
32
52
|
});
|
|
33
|
-
//
|
|
34
|
-
server.tool("
|
|
53
|
+
// get_component - Full documentation for a specific component
|
|
54
|
+
server.tool("get_component", "Get full documentation for a specific NYSDS component including properties, events, slots, and CSS custom properties", {
|
|
35
55
|
tagName: z
|
|
36
56
|
.string()
|
|
37
57
|
.describe("The tag name of the component (e.g., 'nys-button')"),
|
|
38
|
-
|
|
58
|
+
includeExamples: z
|
|
59
|
+
.boolean()
|
|
60
|
+
.default(false)
|
|
61
|
+
.describe("Include HTML code examples from component JSDoc. Set to true when you need usage patterns."),
|
|
62
|
+
}, async ({ tagName, includeExamples }) => {
|
|
39
63
|
const component = getComponent(tagName);
|
|
40
64
|
if (!component) {
|
|
41
65
|
return {
|
|
42
66
|
content: [
|
|
43
67
|
{
|
|
44
68
|
type: "text",
|
|
45
|
-
text: `Component "${tagName}" not found. Use
|
|
69
|
+
text: `Component "${tagName}" not found. Use find_components to see available components.`,
|
|
46
70
|
},
|
|
47
71
|
],
|
|
48
72
|
isError: true,
|
|
49
73
|
};
|
|
50
74
|
}
|
|
75
|
+
// Remove members array to avoid duplication with attributes
|
|
76
|
+
// Attributes contains the HTML API, members duplicates this plus private methods
|
|
77
|
+
const { members: _members, examples, ...componentWithoutMembers } = component;
|
|
51
78
|
return {
|
|
52
79
|
content: [
|
|
53
80
|
{
|
|
54
81
|
type: "text",
|
|
55
|
-
text: JSON.stringify(
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
query: z
|
|
63
|
-
.string()
|
|
64
|
-
.describe("Search query to match against component names and descriptions"),
|
|
65
|
-
}, async ({ query }) => {
|
|
66
|
-
const results = searchComponents(query);
|
|
67
|
-
return {
|
|
68
|
-
content: [
|
|
69
|
-
{
|
|
70
|
-
type: "text",
|
|
71
|
-
text: JSON.stringify(results, null, 2),
|
|
72
|
-
},
|
|
73
|
-
],
|
|
74
|
-
};
|
|
75
|
-
});
|
|
76
|
-
// get_usage_guide - Installation and usage patterns
|
|
77
|
-
server.tool("get_usage_guide", "Get installation and usage guide for NYSDS components", {}, async () => {
|
|
78
|
-
const guide = `# NYSDS Component Usage Guide
|
|
79
|
-
|
|
80
|
-
## Installation
|
|
81
|
-
|
|
82
|
-
\`\`\`bash
|
|
83
|
-
npm install @nysds/components
|
|
84
|
-
\`\`\`
|
|
85
|
-
|
|
86
|
-
## Basic Usage
|
|
87
|
-
|
|
88
|
-
Import components individually:
|
|
89
|
-
|
|
90
|
-
\`\`\`javascript
|
|
91
|
-
import '@nysds/components/nys-button';
|
|
92
|
-
import '@nysds/components/nys-alert';
|
|
93
|
-
\`\`\`
|
|
94
|
-
|
|
95
|
-
Or import all components:
|
|
96
|
-
|
|
97
|
-
\`\`\`javascript
|
|
98
|
-
import '@nysds/components';
|
|
99
|
-
\`\`\`
|
|
100
|
-
|
|
101
|
-
## Using Components in HTML
|
|
102
|
-
|
|
103
|
-
\`\`\`html
|
|
104
|
-
<nys-button label="Click me" variant="primary"></nys-button>
|
|
105
|
-
<nys-alert type="info">This is an informational message.</nys-alert>
|
|
106
|
-
\`\`\`
|
|
107
|
-
|
|
108
|
-
## CSS Custom Properties
|
|
109
|
-
|
|
110
|
-
NYSDS components use CSS custom properties for theming. Import the base styles:
|
|
111
|
-
|
|
112
|
-
\`\`\`css
|
|
113
|
-
@import '@nysds/components/dist/styles.css';
|
|
114
|
-
\`\`\`
|
|
115
|
-
|
|
116
|
-
Use the get_design_tokens tool to explore available tokens.
|
|
117
|
-
`;
|
|
118
|
-
return {
|
|
119
|
-
content: [
|
|
120
|
-
{
|
|
121
|
-
type: "text",
|
|
122
|
-
text: guide,
|
|
82
|
+
text: JSON.stringify({
|
|
83
|
+
...componentWithoutMembers,
|
|
84
|
+
examples: includeExamples && examples && examples.length > 0
|
|
85
|
+
? examples
|
|
86
|
+
: undefined,
|
|
87
|
+
resourceUri: `nysds://component/${tagName}`,
|
|
88
|
+
}, null, 2),
|
|
123
89
|
},
|
|
124
90
|
],
|
|
125
91
|
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guide Tools
|
|
3
|
+
*
|
|
4
|
+
* Consolidated MCP tool for NYSDS guides and documentation.
|
|
5
|
+
* Loads guide content from data/guides/ markdown files.
|
|
6
|
+
*/
|
|
7
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
8
|
+
export declare function registerGuideTools(server: McpServer): void;
|
|
9
|
+
//# sourceMappingURL=guide-tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guide-tools.d.ts","sourceRoot":"","sources":["../../src/tools/guide-tools.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AA6CzE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAyC1D"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guide Tools
|
|
3
|
+
*
|
|
4
|
+
* Consolidated MCP tool for NYSDS guides and documentation.
|
|
5
|
+
* Loads guide content from data/guides/ markdown files.
|
|
6
|
+
*/
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
import { readFileSync } from "fs";
|
|
9
|
+
import { join, dirname } from "path";
|
|
10
|
+
import { fileURLToPath } from "url";
|
|
11
|
+
// ESM-compatible __dirname
|
|
12
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
13
|
+
const __dirname = dirname(__filename);
|
|
14
|
+
// Path to guides directory (relative to dist/tools/)
|
|
15
|
+
const GUIDES_DIR = join(__dirname, "../../data/guides");
|
|
16
|
+
/**
|
|
17
|
+
* Load a guide markdown file
|
|
18
|
+
*/
|
|
19
|
+
function loadGuide(filename) {
|
|
20
|
+
try {
|
|
21
|
+
return readFileSync(join(GUIDES_DIR, filename), "utf-8");
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return `Guide not found: ${filename}`;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Load a framework-specific guide
|
|
29
|
+
*/
|
|
30
|
+
function loadFrameworkGuide(framework) {
|
|
31
|
+
try {
|
|
32
|
+
return readFileSync(join(GUIDES_DIR, "frameworks", `${framework}.md`), "utf-8");
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return `Framework guide not found: ${framework}`;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
const TOPIC_TO_FILE = {
|
|
39
|
+
installation: "installation.md",
|
|
40
|
+
"form-validation": "form-validation.md",
|
|
41
|
+
styles: "styles.md",
|
|
42
|
+
fonts: "fonts.md",
|
|
43
|
+
"page-structure": "page-structure.md",
|
|
44
|
+
};
|
|
45
|
+
export function registerGuideTools(server) {
|
|
46
|
+
server.tool("get_guide", "Get NYSDS guides for installation, forms, styles, fonts, page structure, or framework setup", {
|
|
47
|
+
topic: z
|
|
48
|
+
.enum([
|
|
49
|
+
"installation",
|
|
50
|
+
"form-validation",
|
|
51
|
+
"styles",
|
|
52
|
+
"fonts",
|
|
53
|
+
"page-structure",
|
|
54
|
+
])
|
|
55
|
+
.describe("The guide topic to retrieve"),
|
|
56
|
+
framework: z
|
|
57
|
+
.enum(["angular", "react", "dotnet", "drupal", "vanilla"])
|
|
58
|
+
.optional()
|
|
59
|
+
.describe("When provided, returns framework-specific setup guide instead of the topic guide. Use with topic 'installation' to get framework install instructions."),
|
|
60
|
+
}, async ({ topic, framework }) => {
|
|
61
|
+
let content;
|
|
62
|
+
if (framework) {
|
|
63
|
+
content = loadFrameworkGuide(framework);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
const filename = TOPIC_TO_FILE[topic];
|
|
67
|
+
content = filename ? loadGuide(filename) : `Unknown topic: ${topic}`;
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
content: [
|
|
71
|
+
{
|
|
72
|
+
type: "text",
|
|
73
|
+
text: content,
|
|
74
|
+
},
|
|
75
|
+
],
|
|
76
|
+
};
|
|
77
|
+
});
|
|
78
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAOzE,wBAAgB,aAAa,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAMrD"}
|
package/dist/tools/index.js
CHANGED
|
@@ -6,8 +6,12 @@
|
|
|
6
6
|
import { registerComponentTools } from "./component-tools.js";
|
|
7
7
|
import { registerTokenTools } from "./token-tools.js";
|
|
8
8
|
import { registerValidationTools } from "./validation-tools.js";
|
|
9
|
+
import { registerUtilityTools } from "./utility-tools.js";
|
|
10
|
+
import { registerGuideTools } from "./guide-tools.js";
|
|
9
11
|
export function registerTools(server) {
|
|
10
12
|
registerComponentTools(server);
|
|
11
13
|
registerTokenTools(server);
|
|
12
14
|
registerValidationTools(server);
|
|
15
|
+
registerUtilityTools(server);
|
|
16
|
+
registerGuideTools(server);
|
|
13
17
|
}
|
|
@@ -4,12 +4,9 @@
|
|
|
4
4
|
* MCP tools for working with NYSDS design tokens.
|
|
5
5
|
*
|
|
6
6
|
* Tools:
|
|
7
|
-
* -
|
|
7
|
+
* - get_tokens: Get tokens, categories, or themes
|
|
8
8
|
* - find_tokens: Search tokens by CSS variable, value, or description
|
|
9
|
-
* -
|
|
10
|
-
* - get_token_value: Get detailed info for a specific token
|
|
11
|
-
* - validate_token_usage: Validate token usage in context
|
|
12
|
-
* - list_token_categories: List categories with token counts
|
|
9
|
+
* - get_token_info: Get detailed token info with optional context validation
|
|
13
10
|
* - get_token_graph: Get token dependency graph
|
|
14
11
|
*/
|
|
15
12
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token-tools.d.ts","sourceRoot":"","sources":["../../src/tools/token-tools.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"token-tools.d.ts","sourceRoot":"","sources":["../../src/tools/token-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAqOzE,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAwX1D"}
|
|
@@ -4,16 +4,14 @@
|
|
|
4
4
|
* MCP tools for working with NYSDS design tokens.
|
|
5
5
|
*
|
|
6
6
|
* Tools:
|
|
7
|
-
* -
|
|
7
|
+
* - get_tokens: Get tokens, categories, or themes
|
|
8
8
|
* - find_tokens: Search tokens by CSS variable, value, or description
|
|
9
|
-
* -
|
|
10
|
-
* - get_token_value: Get detailed info for a specific token
|
|
11
|
-
* - validate_token_usage: Validate token usage in context
|
|
12
|
-
* - list_token_categories: List categories with token counts
|
|
9
|
+
* - get_token_info: Get detailed token info with optional context validation
|
|
13
10
|
* - get_token_graph: Get token dependency graph
|
|
14
11
|
*/
|
|
15
12
|
import { z } from "zod";
|
|
16
13
|
import { getCSSTokens, getCSSTokensByCategory, getCSSTokensByLayer, searchCSSTokens, getCSSTokenByVariable, getCSSTokenCategories, buildTokenGraph, } from "../lib/token-parser.js";
|
|
14
|
+
import { formatResponse } from "../lib/format.js";
|
|
17
15
|
const AGENCY_THEMES = [
|
|
18
16
|
{
|
|
19
17
|
id: "default",
|
|
@@ -181,9 +179,13 @@ function validateTokenInContext(token, context) {
|
|
|
181
179
|
// ============================================================================
|
|
182
180
|
export function registerTokenTools(server) {
|
|
183
181
|
// -------------------------------------------------------------------------
|
|
184
|
-
//
|
|
182
|
+
// get_tokens - Consolidated token retrieval (tokens, categories, or themes)
|
|
185
183
|
// -------------------------------------------------------------------------
|
|
186
|
-
server.tool("
|
|
184
|
+
server.tool("get_tokens", "Get NYSDS design tokens, token categories, or agency themes", {
|
|
185
|
+
output: z
|
|
186
|
+
.enum(["tokens", "categories", "themes"])
|
|
187
|
+
.default("tokens")
|
|
188
|
+
.describe("What to return: 'tokens' for CSS variables, 'categories' for category list with counts, 'themes' for agency themes"),
|
|
187
189
|
category: z
|
|
188
190
|
.enum([
|
|
189
191
|
"color",
|
|
@@ -198,20 +200,53 @@ export function registerTokenTools(server) {
|
|
|
198
200
|
"icon",
|
|
199
201
|
])
|
|
200
202
|
.optional()
|
|
201
|
-
.describe("Filter by
|
|
203
|
+
.describe("Filter tokens by category (only applies when output='tokens')"),
|
|
202
204
|
layer: z
|
|
203
205
|
.enum(["primitive", "applied", "theme", "appearance"])
|
|
204
206
|
.optional()
|
|
205
|
-
.describe("Filter by
|
|
207
|
+
.describe("Filter tokens by layer (only applies when output='tokens'). primitive = raw values, applied = semantic tokens, theme = agency theme tokens, appearance = light/dark mode"),
|
|
206
208
|
includeResolvedValues: z
|
|
207
209
|
.boolean()
|
|
208
210
|
.default(false)
|
|
209
|
-
.describe("Include resolved hex/rem values
|
|
211
|
+
.describe("Include resolved hex/rem values (only applies when output='tokens')"),
|
|
210
212
|
includeDescriptions: z
|
|
211
213
|
.boolean()
|
|
212
214
|
.default(true)
|
|
213
|
-
.describe("Include token descriptions"),
|
|
214
|
-
}, async ({ category, layer, includeResolvedValues, includeDescriptions }) => {
|
|
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)
|
|
215
250
|
let tokens;
|
|
216
251
|
if (category) {
|
|
217
252
|
tokens = getCSSTokensByCategory(category);
|
|
@@ -240,10 +275,7 @@ export function registerTokenTools(server) {
|
|
|
240
275
|
content: [
|
|
241
276
|
{
|
|
242
277
|
type: "text",
|
|
243
|
-
text:
|
|
244
|
-
count: tokens.length,
|
|
245
|
-
tokens: formatted,
|
|
246
|
-
}, null, 2),
|
|
278
|
+
text: formatResponse({ count: tokens.length, tokens: formatted }),
|
|
247
279
|
},
|
|
248
280
|
],
|
|
249
281
|
};
|
|
@@ -285,54 +317,37 @@ export function registerTokenTools(server) {
|
|
|
285
317
|
content: [
|
|
286
318
|
{
|
|
287
319
|
type: "text",
|
|
288
|
-
text:
|
|
320
|
+
text: formatResponse({
|
|
289
321
|
query,
|
|
290
322
|
count: results.length,
|
|
291
323
|
results: formatted,
|
|
292
|
-
}
|
|
324
|
+
}),
|
|
293
325
|
},
|
|
294
326
|
],
|
|
295
327
|
};
|
|
296
328
|
});
|
|
297
329
|
// -------------------------------------------------------------------------
|
|
298
|
-
//
|
|
330
|
+
// get_token_info - Get detailed token info with optional context validation
|
|
299
331
|
// -------------------------------------------------------------------------
|
|
300
|
-
server.tool("
|
|
301
|
-
return {
|
|
302
|
-
content: [
|
|
303
|
-
{
|
|
304
|
-
type: "text",
|
|
305
|
-
text: JSON.stringify({
|
|
306
|
-
themes: AGENCY_THEMES,
|
|
307
|
-
usage: {
|
|
308
|
-
htmlAttribute: '<html data-theme="admin">',
|
|
309
|
-
cssClass: '<body class="nys-theme-admin">',
|
|
310
|
-
cssCustomProperty: "Themes modify --nys-color-theme-* tokens",
|
|
311
|
-
},
|
|
312
|
-
totalThemes: AGENCY_THEMES.length,
|
|
313
|
-
}, null, 2),
|
|
314
|
-
},
|
|
315
|
-
],
|
|
316
|
-
};
|
|
317
|
-
});
|
|
318
|
-
// -------------------------------------------------------------------------
|
|
319
|
-
// get_token_value - Get detailed token info
|
|
320
|
-
// -------------------------------------------------------------------------
|
|
321
|
-
server.tool("get_token_value", "Get detailed information about a specific design token including its value, description, and which tokens use it", {
|
|
332
|
+
server.tool("get_token_info", "Get detailed information about a specific design token. Optionally validate usage in a specific context (text, background, border, icon).", {
|
|
322
333
|
token: z
|
|
323
334
|
.string()
|
|
324
335
|
.describe('CSS variable name (e.g., "--nys-color-text" or "color-text")'),
|
|
325
|
-
|
|
336
|
+
context: z
|
|
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 }) => {
|
|
326
341
|
const tokenInfo = getCSSTokenByVariable(token);
|
|
327
342
|
if (!tokenInfo) {
|
|
328
343
|
return {
|
|
329
344
|
content: [
|
|
330
345
|
{
|
|
331
346
|
type: "text",
|
|
332
|
-
text:
|
|
347
|
+
text: formatResponse({
|
|
333
348
|
error: `Token not found: ${token}`,
|
|
334
349
|
suggestion: "Try searching with find_tokens to discover available tokens",
|
|
335
|
-
}
|
|
350
|
+
}),
|
|
336
351
|
},
|
|
337
352
|
],
|
|
338
353
|
};
|
|
@@ -341,73 +356,38 @@ export function registerTokenTools(server) {
|
|
|
341
356
|
const graph = buildTokenGraph();
|
|
342
357
|
const node = graph.get(tokenInfo.cssVariable);
|
|
343
358
|
const usedBy = node?.usedBy || [];
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
usedBy: usedBy.length > 0 ? usedBy : undefined,
|
|
356
|
-
usage: `var(${tokenInfo.cssVariable})`,
|
|
357
|
-
}, null, 2),
|
|
358
|
-
},
|
|
359
|
-
],
|
|
359
|
+
// Base token info
|
|
360
|
+
const result = {
|
|
361
|
+
cssVariable: tokenInfo.cssVariable,
|
|
362
|
+
cssValue: tokenInfo.cssValue,
|
|
363
|
+
resolvedValue: tokenInfo.resolvedValue,
|
|
364
|
+
description: tokenInfo.description,
|
|
365
|
+
category: tokenInfo.category,
|
|
366
|
+
layer: tokenInfo.layer,
|
|
367
|
+
usedBy: usedBy.length > 0 ? usedBy : undefined,
|
|
368
|
+
usage: `var(${tokenInfo.cssVariable})`,
|
|
369
|
+
resourceUri: "nysds://tokens",
|
|
360
370
|
};
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
if (!tokenInfo) {
|
|
375
|
-
return {
|
|
376
|
-
content: [
|
|
377
|
-
{
|
|
378
|
-
type: "text",
|
|
379
|
-
text: JSON.stringify({
|
|
380
|
-
error: `Token not found: ${token}`,
|
|
381
|
-
suggestion: "Try searching with find_tokens to discover available tokens",
|
|
382
|
-
}, null, 2),
|
|
383
|
-
},
|
|
384
|
-
],
|
|
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,
|
|
385
384
|
};
|
|
386
385
|
}
|
|
387
|
-
const validation = validateTokenInContext(tokenInfo, context);
|
|
388
|
-
return {
|
|
389
|
-
content: [
|
|
390
|
-
{
|
|
391
|
-
type: "text",
|
|
392
|
-
text: JSON.stringify(validation, null, 2),
|
|
393
|
-
},
|
|
394
|
-
],
|
|
395
|
-
};
|
|
396
|
-
});
|
|
397
|
-
// -------------------------------------------------------------------------
|
|
398
|
-
// list_token_categories - List categories with counts
|
|
399
|
-
// -------------------------------------------------------------------------
|
|
400
|
-
server.tool("list_token_categories", "List all token categories with the number of tokens in each", {}, async () => {
|
|
401
|
-
const categories = getCSSTokenCategories();
|
|
402
|
-
const total = categories.reduce((sum, c) => sum + c.count, 0);
|
|
403
386
|
return {
|
|
404
387
|
content: [
|
|
405
388
|
{
|
|
406
389
|
type: "text",
|
|
407
|
-
text:
|
|
408
|
-
categories,
|
|
409
|
-
totalTokens: total,
|
|
410
|
-
}, null, 2),
|
|
390
|
+
text: formatResponse(result),
|
|
411
391
|
},
|
|
412
392
|
],
|
|
413
393
|
};
|
|
@@ -440,8 +420,8 @@ export function registerTokenTools(server) {
|
|
|
440
420
|
.int()
|
|
441
421
|
.min(1)
|
|
442
422
|
.max(100)
|
|
443
|
-
.default(
|
|
444
|
-
.describe("Maximum number of tokens to return"),
|
|
423
|
+
.default(20)
|
|
424
|
+
.describe("Maximum number of tokens to return (default: 20)"),
|
|
445
425
|
}, async ({ filter, category, limit }) => {
|
|
446
426
|
const graph = buildTokenGraph();
|
|
447
427
|
const tokens = getCSSTokens();
|
|
@@ -487,7 +467,7 @@ export function registerTokenTools(server) {
|
|
|
487
467
|
content: [
|
|
488
468
|
{
|
|
489
469
|
type: "text",
|
|
490
|
-
text:
|
|
470
|
+
text: formatResponse({
|
|
491
471
|
filter,
|
|
492
472
|
category: category || "all",
|
|
493
473
|
nodes: nodes.map((n) => ({
|
|
@@ -496,7 +476,7 @@ export function registerTokenTools(server) {
|
|
|
496
476
|
usedBy: n.usedBy.length > 0 ? n.usedBy : undefined,
|
|
497
477
|
})),
|
|
498
478
|
stats,
|
|
499
|
-
}
|
|
479
|
+
}),
|
|
500
480
|
},
|
|
501
481
|
],
|
|
502
482
|
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility Tools
|
|
3
|
+
*
|
|
4
|
+
* MCP tools for NYSDS utility classes.
|
|
5
|
+
*/
|
|
6
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
7
|
+
export declare function registerUtilityTools(server: McpServer): void;
|
|
8
|
+
//# sourceMappingURL=utility-tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utility-tools.d.ts","sourceRoot":"","sources":["../../src/tools/utility-tools.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAwOzE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA8D5D"}
|