@cobwds/mcp-server 1.19.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.
Files changed (65) hide show
  1. package/README.md +235 -0
  2. package/data/cem/custom-elements.json +15923 -0
  3. package/data/guides/.gitkeep +0 -0
  4. package/data/guides/fonts.md +56 -0
  5. package/data/guides/form-validation.md +169 -0
  6. package/data/guides/frameworks/angular.md +71 -0
  7. package/data/guides/frameworks/dotnet.md +42 -0
  8. package/data/guides/frameworks/drupal.md +39 -0
  9. package/data/guides/frameworks/react.md +115 -0
  10. package/data/guides/frameworks/vanilla.md +45 -0
  11. package/data/guides/installation.md +73 -0
  12. package/data/guides/page-structure.md +161 -0
  13. package/data/guides/styles.md +48 -0
  14. package/data/guides/themes.md +61 -0
  15. package/data/tokens/tokens.css +479 -0
  16. package/data/tokens/tokens.json +1553 -0
  17. package/dist/index.d.ts +9 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +16 -0
  20. package/dist/lib/cem-parser.d.ts +102 -0
  21. package/dist/lib/cem-parser.d.ts.map +1 -0
  22. package/dist/lib/cem-parser.js +92 -0
  23. package/dist/lib/search.d.ts +20 -0
  24. package/dist/lib/search.d.ts.map +1 -0
  25. package/dist/lib/search.js +87 -0
  26. package/dist/lib/token-parser.d.ts +128 -0
  27. package/dist/lib/token-parser.d.ts.map +1 -0
  28. package/dist/lib/token-parser.js +431 -0
  29. package/dist/prompts/cobwds-mode.d.ts +8 -0
  30. package/dist/prompts/cobwds-mode.d.ts.map +1 -0
  31. package/dist/prompts/cobwds-mode.js +60 -0
  32. package/dist/resources/components.d.ts +12 -0
  33. package/dist/resources/components.d.ts.map +1 -0
  34. package/dist/resources/components.js +62 -0
  35. package/dist/resources/guides.d.ts +11 -0
  36. package/dist/resources/guides.d.ts.map +1 -0
  37. package/dist/resources/guides.js +76 -0
  38. package/dist/resources/index.d.ts +8 -0
  39. package/dist/resources/index.d.ts.map +1 -0
  40. package/dist/resources/index.js +13 -0
  41. package/dist/resources/tokens.d.ts +17 -0
  42. package/dist/resources/tokens.d.ts.map +1 -0
  43. package/dist/resources/tokens.js +312 -0
  44. package/dist/server.d.ts +11 -0
  45. package/dist/server.d.ts.map +1 -0
  46. package/dist/server.js +30 -0
  47. package/dist/tools/component-tools.d.ts +12 -0
  48. package/dist/tools/component-tools.d.ts.map +1 -0
  49. package/dist/tools/component-tools.js +95 -0
  50. package/dist/tools/guide-tools.d.ts +9 -0
  51. package/dist/tools/guide-tools.d.ts.map +1 -0
  52. package/dist/tools/guide-tools.js +80 -0
  53. package/dist/tools/index.d.ts +8 -0
  54. package/dist/tools/index.d.ts.map +1 -0
  55. package/dist/tools/index.js +17 -0
  56. package/dist/tools/token-tools.d.ts +13 -0
  57. package/dist/tools/token-tools.d.ts.map +1 -0
  58. package/dist/tools/token-tools.js +207 -0
  59. package/dist/tools/utility-tools.d.ts +8 -0
  60. package/dist/tools/utility-tools.d.ts.map +1 -0
  61. package/dist/tools/utility-tools.js +293 -0
  62. package/dist/tools/validation-tools.d.ts +11 -0
  63. package/dist/tools/validation-tools.d.ts.map +1 -0
  64. package/dist/tools/validation-tools.js +60 -0
  65. package/package.json +54 -0
@@ -0,0 +1,207 @@
1
+ /**
2
+ * Token Tools
3
+ *
4
+ * MCP tools for working with COBWDS design tokens.
5
+ *
6
+ * Tools:
7
+ * - find_tokens: Search or browse tokens (discovery)
8
+ * - get_token: Get full details for a specific token (deep dive)
9
+ * - get_token_graph: Get token dependency graph
10
+ */
11
+ import { z } from "zod";
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",
27
+ ];
28
+ const TOKEN_TOOL_ANNOTATIONS = {
29
+ readOnlyHint: true,
30
+ destructiveHint: false,
31
+ idempotentHint: true,
32
+ openWorldHint: false,
33
+ };
34
+ // ============================================================================
35
+ // Tool Registration
36
+ // ============================================================================
37
+ export function registerTokenTools(server) {
38
+ // -------------------------------------------------------------------------
39
+ // find_tokens - Search or browse tokens (discovery)
40
+ // -------------------------------------------------------------------------
41
+ server.tool("find_tokens", "Search or browse COBWDS design tokens. Omit query to list all. Returns CSS variable names for use with var().", {
42
+ query: z
43
+ .string()
44
+ .optional()
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
53
+ let tokens;
54
+ if (include === "primitive") {
55
+ tokens = getPrimitiveTokens();
56
+ }
57
+ else if (include === "all") {
58
+ tokens = getCSSTokens();
59
+ }
60
+ else {
61
+ tokens = getRecommendedTokens();
62
+ }
63
+ // Apply category filter
64
+ if (category) {
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));
72
+ }
73
+ const results = tokens.map((t) => ({
74
+ cssVariable: t.cssVariable,
75
+ description: t.description,
76
+ category: t.category,
77
+ }));
78
+ return {
79
+ content: [
80
+ {
81
+ type: "text",
82
+ text: JSON.stringify({ count: results.length, results }, null, 2),
83
+ },
84
+ ],
85
+ };
86
+ });
87
+ // -------------------------------------------------------------------------
88
+ // get_token - Get full details for a specific token (deep dive)
89
+ // -------------------------------------------------------------------------
90
+ server.tool("get_token", "Get full details for a specific design token including resolved values and alternatives.", {
91
+ token: z
92
+ .string()
93
+ .describe('CSS variable name (e.g., "--cob-color-text" or "color-text")'),
94
+ }, TOKEN_TOOL_ANNOTATIONS, async ({ token }) => {
95
+ const tokenInfo = getCSSTokenByVariable(token);
96
+ if (!tokenInfo) {
97
+ return {
98
+ content: [
99
+ {
100
+ type: "text",
101
+ text: JSON.stringify({
102
+ error: `Token not found: ${token}`,
103
+ suggestion: "Use find_tokens to search for available tokens",
104
+ }, null, 2),
105
+ },
106
+ ],
107
+ isError: true,
108
+ };
109
+ }
110
+ const alternatives = getAlternativeTokens(tokenInfo);
111
+ const result = {
112
+ cssVariable: tokenInfo.cssVariable,
113
+ cssValue: tokenInfo.cssValue,
114
+ resolvedValue: tokenInfo.resolvedValue,
115
+ description: tokenInfo.description,
116
+ category: tokenInfo.category,
117
+ layer: tokenInfo.layer,
118
+ alternatives,
119
+ resourceUri: "cobwds://tokens",
120
+ };
121
+ return {
122
+ content: [
123
+ {
124
+ type: "text",
125
+ text: JSON.stringify(result, null, 2),
126
+ },
127
+ ],
128
+ };
129
+ });
130
+ // -------------------------------------------------------------------------
131
+ // get_token_graph - Token dependency graph
132
+ // -------------------------------------------------------------------------
133
+ server.tool("get_token_graph", "Get the token dependency graph showing which tokens reference which and which are used by which", {
134
+ filter: z
135
+ .enum(["all", "aliases-only", "primitives-only", "most-used"])
136
+ .default("all")
137
+ .describe("Filter the graph to specific token types"),
138
+ category: z
139
+ .enum(CATEGORY_ENUM)
140
+ .optional()
141
+ .describe("Filter to a specific category"),
142
+ limit: z
143
+ .number()
144
+ .int()
145
+ .min(1)
146
+ .max(100)
147
+ .default(20)
148
+ .describe("Maximum number of tokens to return (default: 20)"),
149
+ }, TOKEN_TOOL_ANNOTATIONS, async ({ filter, category, limit }) => {
150
+ const graph = buildTokenGraph();
151
+ const tokens = getCSSTokens();
152
+ // Build lookup for categories
153
+ const tokenCategories = new Map();
154
+ for (const t of tokens) {
155
+ tokenCategories.set(t.cssVariable, t.category);
156
+ }
157
+ const allNodes = Array.from(graph.values());
158
+ let nodes = allNodes;
159
+ // Apply category filter
160
+ if (category) {
161
+ nodes = nodes.filter((n) => tokenCategories.get(n.cssVariable) === category);
162
+ }
163
+ // Apply type filter
164
+ if (filter === "aliases-only") {
165
+ nodes = nodes.filter((n) => n.referencesVariable);
166
+ }
167
+ else if (filter === "primitives-only") {
168
+ nodes = nodes.filter((n) => !n.referencesVariable);
169
+ }
170
+ else if (filter === "most-used") {
171
+ nodes = nodes.filter((n) => n.usedBy.length > 0);
172
+ nodes.sort((a, b) => b.usedBy.length - a.usedBy.length);
173
+ }
174
+ // Apply limit
175
+ nodes = nodes.slice(0, limit);
176
+ const stats = {
177
+ totalTokens: allNodes.length,
178
+ aliasTokens: allNodes.filter((n) => n.referencesVariable).length,
179
+ primitiveTokens: allNodes.filter((n) => !n.referencesVariable).length,
180
+ mostUsed: allNodes
181
+ .filter((n) => n.usedBy.length > 0)
182
+ .sort((a, b) => b.usedBy.length - a.usedBy.length)
183
+ .slice(0, 5)
184
+ .map((n) => ({
185
+ cssVariable: n.cssVariable,
186
+ usedByCount: n.usedBy.length,
187
+ })),
188
+ };
189
+ return {
190
+ content: [
191
+ {
192
+ type: "text",
193
+ text: JSON.stringify({
194
+ filter,
195
+ category: category || "all",
196
+ nodes: nodes.map((n) => ({
197
+ cssVariable: n.cssVariable,
198
+ referencesVariable: n.referencesVariable,
199
+ usedBy: n.usedBy.length > 0 ? n.usedBy : undefined,
200
+ })),
201
+ stats,
202
+ }, null, 2),
203
+ },
204
+ ],
205
+ };
206
+ });
207
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Utility Tools
3
+ *
4
+ * MCP tools for COBWDS 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;AAmPzE,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CA8D5D"}
@@ -0,0 +1,293 @@
1
+ /**
2
+ * Utility Tools
3
+ *
4
+ * MCP tools for COBWDS utility classes.
5
+ */
6
+ import { z } from "zod";
7
+ const UTILITY_DOCS = {
8
+ grid: `## Grid System
9
+
10
+ COBWDS provides a 12-column responsive grid system.
11
+
12
+ ### Structure
13
+ \`\`\`html
14
+ <div class="cob-grid-container">
15
+ <div class="cob-grid-row">
16
+ <div class="cob-grid-col-6">Half width</div>
17
+ <div class="cob-grid-col-6">Half width</div>
18
+ </div>
19
+ </div>
20
+ \`\`\`
21
+
22
+ ### Column Classes
23
+ - \`cob-grid-col-[1-12]\` - Fixed column widths (1-12 columns)
24
+ - \`cob-grid-col\` - Equal width columns (auto-distributes)
25
+ - \`cob-grid-col-auto\` - Column sized to content
26
+ - \`cob-grid-col-fill\` - Column fills remaining space
27
+
28
+ ### Gap Classes
29
+ - \`cob-grid-gap-0\` - No gap
30
+ - \`cob-grid-gap-2px\` - 2px gap
31
+ - \`cob-grid-gap-50\` - 4px gap (0.25rem)
32
+ - \`cob-grid-gap-100\` - 8px gap (0.5rem)
33
+ - \`cob-grid-gap-150\` - 12px gap (0.75rem)
34
+ - \`cob-grid-gap-200\` - 16px gap (1rem)
35
+ - \`cob-grid-gap-250\` - 20px gap (1.25rem)
36
+ - \`cob-grid-gap-300\` - 24px gap (1.5rem)
37
+ - \`cob-grid-gap-400\` - 32px gap (2rem)
38
+ - \`cob-grid-gap-500\` - 40px gap (2.5rem)
39
+ - \`cob-grid-gap-600\` - 48px gap (3rem)
40
+ - \`cob-grid-gap-700\` - 56px gap (3.5rem)
41
+ - \`cob-grid-gap-800\` - 64px gap (4rem)
42
+ - \`cob-grid-gap-1200\` - 96px gap (6rem)
43
+
44
+ ### Offset Classes
45
+ - \`cob-grid-offset-[1-12]\` - Offset column by 1-12 columns
46
+
47
+ ### Example: Form with Sidebar
48
+ \`\`\`html
49
+ <div class="cob-grid-container">
50
+ <div class="cob-grid-row">
51
+ <div class="cob-grid-col-12 cob-desktop:cob-grid-col-4">
52
+ <!-- Sidebar content (stepper, navigation) -->
53
+ </div>
54
+ <div class="cob-grid-col-12 cob-desktop:cob-grid-col-8">
55
+ <!-- Main content (form) -->
56
+ </div>
57
+ </div>
58
+ </div>
59
+ \`\`\``,
60
+ flex: `## Flexbox Utilities
61
+
62
+ ### Display
63
+ - \`cob-display-flex\` - Sets display: flex
64
+
65
+ ### Direction
66
+ - \`cob-flex-row\` - Row direction (default)
67
+ - \`cob-flex-column\` - Column direction
68
+
69
+ ### Wrapping
70
+ - \`cob-flex-wrap\` - Allow items to wrap
71
+ - \`cob-flex-no-wrap\` - Prevent wrapping
72
+
73
+ ### Alignment (Cross Axis)
74
+ - \`cob-flex-align-start\` - Align items to start
75
+ - \`cob-flex-align-center\` - Align items to center
76
+ - \`cob-flex-align-end\` - Align items to end
77
+ - \`cob-flex-align-stretch\` - Stretch items to fill
78
+
79
+ ### Justification (Main Axis)
80
+ - \`cob-flex-justify-start\` - Justify to start
81
+ - \`cob-flex-justify-center\` - Justify to center
82
+ - \`cob-flex-justify-end\` - Justify to end
83
+
84
+ ### Flex Sizing
85
+ - \`cob-flex-[1-12]\` - Flex grow/shrink values
86
+ - \`cob-flex-auto\` - flex: auto (grow and shrink)
87
+ - \`cob-flex-fill\` - Fill available space
88
+
89
+ ### Example: Button Group
90
+ \`\`\`html
91
+ <div class="cob-display-flex cob-flex-justify-end cob-flex-gap-200">
92
+ <cob-button label="Cancel" variant="outline"></cob-button>
93
+ <cob-button label="Submit"></cob-button>
94
+ </div>
95
+ \`\`\``,
96
+ spacing: `## Spacing Utilities
97
+
98
+ Pattern: \`cob-{property}-{direction}-{value}\`
99
+
100
+ ### Properties
101
+ - \`margin\` - External spacing
102
+ - \`padding\` - Internal spacing
103
+
104
+ ### Directions
105
+ - \`t\` - Top
106
+ - \`r\` - Right
107
+ - \`b\` - Bottom
108
+ - \`l\` - Left
109
+ - \`x\` - Horizontal (left + right)
110
+ - \`y\` - Vertical (top + bottom)
111
+ - (none) - All sides
112
+
113
+ ### Values
114
+ - \`0\` - 0
115
+ - \`1px\` - 1px
116
+ - \`2px\` - 2px
117
+ - \`50\` - var(--cob-space-50) = 0.125rem (2px)
118
+ - \`100\` - var(--cob-space-100) = 0.25rem (4px)
119
+ - \`150\` - var(--cob-space-150) = 0.375rem (6px)
120
+ - \`200\` - var(--cob-space-200) = 0.5rem (8px)
121
+ - \`250\` - var(--cob-space-250) = 0.625rem (10px)
122
+ - \`300\` - var(--cob-space-300) = 0.75rem (12px)
123
+ - \`400\` - var(--cob-space-400) = 1rem (16px)
124
+ - \`500\` - var(--cob-space-500) = 1.25rem (20px)
125
+ - \`600\` - var(--cob-space-600) = 1.5rem (24px)
126
+ - \`700\` - var(--cob-space-700) = 2rem (32px)
127
+ - \`800\` - var(--cob-space-800) = 2.5rem (40px)
128
+ - \`1200\` - var(--cob-space-1200) = 4rem (64px)
129
+
130
+ ### Examples
131
+ \`\`\`html
132
+ <!-- Add bottom margin to an alert -->
133
+ <cob-alert class="cob-margin-b-300">...</cob-alert>
134
+
135
+ <!-- Add padding to a container -->
136
+ <div class="cob-padding-400">...</div>
137
+
138
+ <!-- Horizontal margin -->
139
+ <div class="cob-margin-x-200">...</div>
140
+ \`\`\``,
141
+ display: `## Display Utilities
142
+
143
+ - \`cob-display-none\` - Hide element
144
+ - \`cob-display-block\` - Block display
145
+ - \`cob-display-inline\` - Inline display
146
+ - \`cob-display-inline-block\` - Inline-block display
147
+ - \`cob-display-flex\` - Flex display
148
+
149
+ ### Example: Hide on Mobile
150
+ \`\`\`html
151
+ <div class="cob-display-none cob-tablet:cob-display-block">
152
+ Only visible on tablet and larger
153
+ </div>
154
+ \`\`\``,
155
+ opacity: `## Opacity Utilities
156
+
157
+ - \`cob-opacity-0\` - Fully transparent
158
+ - \`cob-opacity-25\` - 25% opacity
159
+ - \`cob-opacity-50\` - 50% opacity
160
+ - \`cob-opacity-75\` - 75% opacity
161
+ - \`cob-opacity-100\` - Fully opaque`,
162
+ zindex: `## Z-Index Utilities
163
+
164
+ - \`cob-z-0\` - z-index: 0
165
+ - \`cob-z-10\` - z-index: 10
166
+ - \`cob-z-20\` - z-index: 20
167
+ - \`cob-z-30\` - z-index: 30
168
+ - \`cob-z-40\` - z-index: 40
169
+ - \`cob-z-50\` - z-index: 50
170
+ - \`cob-z-auto\` - z-index: auto`,
171
+ typography: `## Typography Utilities
172
+
173
+ ### Text Alignment
174
+ - \`cob-text-left\` - Left align text
175
+ - \`cob-text-center\` - Center align text
176
+ - \`cob-text-right\` - Right align text
177
+
178
+ ### Font Weight
179
+ - \`cob-font-normal\` - Normal weight
180
+ - \`cob-font-medium\` - Medium weight
181
+ - \`cob-font-semibold\` - Semibold weight
182
+ - \`cob-font-bold\` - Bold weight
183
+
184
+ ### Text Transform
185
+ - \`cob-text-uppercase\` - Uppercase text
186
+ - \`cob-text-lowercase\` - Lowercase text
187
+ - \`cob-text-capitalize\` - Capitalize text`,
188
+ responsive: `## Responsive Breakpoints
189
+
190
+ COBWDS utility classes support responsive prefixes.
191
+
192
+ ### Breakpoints
193
+ - (no prefix) - All screen sizes (mobile-first)
194
+ - \`cob-mobile-lg:\` - 30em (480px) and up
195
+ - \`cob-tablet:\` - 40em (640px) and up
196
+ - \`cob-desktop:\` - 64em (1024px) and up
197
+
198
+ ### Pattern
199
+ \`cob-{breakpoint}:cob-{class}\`
200
+
201
+ ### Examples
202
+ \`\`\`html
203
+ <!-- Full width on mobile, half on tablet, third on desktop -->
204
+ <div class="cob-grid-col-12 cob-tablet:cob-grid-col-6 cob-desktop:cob-grid-col-4">
205
+ Responsive column
206
+ </div>
207
+
208
+ <!-- Stack on mobile, row on tablet -->
209
+ <div class="cob-display-flex cob-flex-column cob-tablet:cob-flex-row">
210
+ Responsive flex direction
211
+ </div>
212
+
213
+ <!-- Hide on mobile, show on desktop -->
214
+ <div class="cob-display-none cob-desktop:cob-display-block">
215
+ Desktop only content
216
+ </div>
217
+ \`\`\``,
218
+ componentSpacing: `## Component Spacing
219
+
220
+ When adding spacing around COBWDS components, use utility classes rather than wrapper elements.
221
+
222
+ ### Examples
223
+ \`\`\`html
224
+ <!-- Add bottom margin to an alert -->
225
+ <cob-alert class="cob-margin-b-300" type="info">
226
+ This alert has bottom margin.
227
+ </cob-alert>
228
+
229
+ <!-- Add top margin to a button -->
230
+ <cob-button class="cob-margin-t-400" label="Submit"></cob-button>
231
+
232
+ <!-- Stack form fields with consistent spacing -->
233
+ <cob-textinput class="cob-margin-b-300" label="First Name"></cob-textinput>
234
+ <cob-textinput class="cob-margin-b-300" label="Last Name"></cob-textinput>
235
+ <cob-textinput class="cob-margin-b-400" label="Email"></cob-textinput>
236
+ <cob-button label="Submit"></cob-button>
237
+ \`\`\``,
238
+ };
239
+ export function registerUtilityTools(server) {
240
+ // get_utility_classes - Comprehensive utility class reference
241
+ server.tool("get_utility_classes", "Get COBWDS utility class reference for layout, spacing, and styling", {
242
+ category: z
243
+ .enum([
244
+ "grid",
245
+ "flex",
246
+ "spacing",
247
+ "display",
248
+ "opacity",
249
+ "zindex",
250
+ "typography",
251
+ "responsive",
252
+ "all",
253
+ ])
254
+ .optional()
255
+ .describe("Category of utility classes to retrieve. Defaults to 'all'."),
256
+ }, async ({ category = "all" }) => {
257
+ let content;
258
+ if (category === "all") {
259
+ content = `# COBWDS Utility Classes
260
+
261
+ ${UTILITY_DOCS.grid}
262
+
263
+ ${UTILITY_DOCS.flex}
264
+
265
+ ${UTILITY_DOCS.spacing}
266
+
267
+ ${UTILITY_DOCS.display}
268
+
269
+ ${UTILITY_DOCS.opacity}
270
+
271
+ ${UTILITY_DOCS.zindex}
272
+
273
+ ${UTILITY_DOCS.typography}
274
+
275
+ ${UTILITY_DOCS.responsive}
276
+
277
+ ${UTILITY_DOCS.componentSpacing}`;
278
+ }
279
+ else {
280
+ content =
281
+ UTILITY_DOCS[category] ||
282
+ `Unknown category: ${category}`;
283
+ }
284
+ return {
285
+ content: [
286
+ {
287
+ type: "text",
288
+ text: content,
289
+ },
290
+ ],
291
+ };
292
+ });
293
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Validation Tools
3
+ *
4
+ * MCP tools for validating COBWDS component usage.
5
+ *
6
+ * Tools:
7
+ * - validate_component_api: Validate prop/attribute usage
8
+ */
9
+ import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
10
+ export declare function registerValidationTools(server: McpServer): void;
11
+ //# sourceMappingURL=validation-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validation-tools.d.ts","sourceRoot":"","sources":["../../src/tools/validation-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAGzE,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAgE/D"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Validation Tools
3
+ *
4
+ * MCP tools for validating COBWDS component usage.
5
+ *
6
+ * Tools:
7
+ * - validate_component_api: Validate prop/attribute usage
8
+ */
9
+ import { z } from "zod";
10
+ import { getComponent } from "../lib/cem-parser.js";
11
+ export function registerValidationTools(server) {
12
+ // validate_component_api - Validate prop/attribute usage
13
+ server.tool("validate_component_api", "Validate that the provided attributes/properties are valid for a given COBWDS component", {
14
+ tagName: z
15
+ .string()
16
+ .describe("The tag name of the component (e.g., 'cob-button')"),
17
+ attributes: z
18
+ .record(z.string())
19
+ .describe("Object of attribute names and values to validate"),
20
+ }, async ({ tagName, attributes }) => {
21
+ const component = getComponent(tagName);
22
+ if (!component) {
23
+ return {
24
+ content: [
25
+ {
26
+ type: "text",
27
+ text: `Component "${tagName}" not found.`,
28
+ },
29
+ ],
30
+ isError: true,
31
+ };
32
+ }
33
+ const validAttributes = new Set(component.attributes?.map((a) => a.name) || []);
34
+ const validProperties = new Set(component.members
35
+ ?.filter((m) => m.kind === "field")
36
+ .map((m) => m.name) || []);
37
+ const errors = [];
38
+ const warnings = [];
39
+ for (const attr of Object.keys(attributes)) {
40
+ if (!validAttributes.has(attr) && !validProperties.has(attr)) {
41
+ errors.push(`Unknown attribute/property: "${attr}"`);
42
+ }
43
+ }
44
+ const result = {
45
+ valid: errors.length === 0,
46
+ errors,
47
+ warnings,
48
+ validAttributes: Array.from(validAttributes),
49
+ validProperties: Array.from(validProperties),
50
+ };
51
+ return {
52
+ content: [
53
+ {
54
+ type: "text",
55
+ text: JSON.stringify(result, null, 2),
56
+ },
57
+ ],
58
+ };
59
+ });
60
+ }
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@cobwds/mcp-server",
3
+ "version": "1.19.3",
4
+ "description": "MCP server for the City of Boston Web Design System. Exposes components, tokens, and documentation to AI assistants.",
5
+ "type": "module",
6
+ "bin": {
7
+ "cobwds-mcp": "dist/index.js"
8
+ },
9
+ "main": "dist/index.js",
10
+ "types": "dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "import": "./dist/index.js",
14
+ "types": "./dist/index.d.ts"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist/",
19
+ "data/"
20
+ ],
21
+ "scripts": {
22
+ "copy-data": "mkdir -p data/cem data/tokens && cp ../../custom-elements.json data/cem/ && cp ../tokens/src/tokens.json data/tokens/ && cp ../tokens/dist/tokens.css data/tokens/",
23
+ "build": "npm run copy-data && tsc",
24
+ "dev": "tsc --watch",
25
+ "start": "node dist/index.js",
26
+ "inspect": "npx -y @modelcontextprotocol/inspector node dist/index.js"
27
+ },
28
+ "dependencies": {
29
+ "@modelcontextprotocol/sdk": "^1.26.0",
30
+ "zod": "^3.25"
31
+ },
32
+ "devDependencies": {
33
+ "@cobwds/styles": "^1.19.3",
34
+ "@cobwds/tokens": "^1.19.3",
35
+ "@types/node": "^22.0.0",
36
+ "typescript": "^5.9.3"
37
+ },
38
+ "keywords": [
39
+ "mcp",
40
+ "model-context-protocol",
41
+ "city-of-boston",
42
+ "design-system",
43
+ "web-components",
44
+ "ai-assistant"
45
+ ],
46
+ "author": "City of Boston Web Design System Team",
47
+ "license": "MIT",
48
+ "repository": {
49
+ "type": "git",
50
+ "url": "git+https://github.com/CityOfBoston/nywds-poc.git",
51
+ "directory": "packages/mcp-server"
52
+ },
53
+ "sideEffects": false
54
+ }