@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.
- package/README.md +235 -0
- package/data/cem/custom-elements.json +15923 -0
- package/data/guides/.gitkeep +0 -0
- package/data/guides/fonts.md +56 -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 +115 -0
- package/data/guides/frameworks/vanilla.md +45 -0
- package/data/guides/installation.md +73 -0
- package/data/guides/page-structure.md +161 -0
- package/data/guides/styles.md +48 -0
- package/data/guides/themes.md +61 -0
- package/data/tokens/tokens.css +479 -0
- package/data/tokens/tokens.json +1553 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +16 -0
- package/dist/lib/cem-parser.d.ts +102 -0
- package/dist/lib/cem-parser.d.ts.map +1 -0
- package/dist/lib/cem-parser.js +92 -0
- package/dist/lib/search.d.ts +20 -0
- package/dist/lib/search.d.ts.map +1 -0
- package/dist/lib/search.js +87 -0
- package/dist/lib/token-parser.d.ts +128 -0
- package/dist/lib/token-parser.d.ts.map +1 -0
- package/dist/lib/token-parser.js +431 -0
- package/dist/prompts/cobwds-mode.d.ts +8 -0
- package/dist/prompts/cobwds-mode.d.ts.map +1 -0
- package/dist/prompts/cobwds-mode.js +60 -0
- package/dist/resources/components.d.ts +12 -0
- package/dist/resources/components.d.ts.map +1 -0
- package/dist/resources/components.js +62 -0
- package/dist/resources/guides.d.ts +11 -0
- package/dist/resources/guides.d.ts.map +1 -0
- package/dist/resources/guides.js +76 -0
- package/dist/resources/index.d.ts +8 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +13 -0
- package/dist/resources/tokens.d.ts +17 -0
- package/dist/resources/tokens.d.ts.map +1 -0
- package/dist/resources/tokens.js +312 -0
- package/dist/server.d.ts +11 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +30 -0
- package/dist/tools/component-tools.d.ts +12 -0
- package/dist/tools/component-tools.d.ts.map +1 -0
- package/dist/tools/component-tools.js +95 -0
- 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 +80 -0
- package/dist/tools/index.d.ts +8 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +17 -0
- package/dist/tools/token-tools.d.ts +13 -0
- package/dist/tools/token-tools.d.ts.map +1 -0
- package/dist/tools/token-tools.js +207 -0
- 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 +293 -0
- package/dist/tools/validation-tools.d.ts +11 -0
- package/dist/tools/validation-tools.d.ts.map +1 -0
- package/dist/tools/validation-tools.js +60 -0
- 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
|
+
}
|