@vadenai/mcp-server 0.1.0 → 0.2.1
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 +24 -2
- package/dist/guides/generate-guide.js +8 -1
- package/dist/index.js +2 -2
- package/dist/tools/components.js +82 -0
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -30,7 +30,7 @@ This MCP Server solves this by providing **design context** that agents can refe
|
|
|
30
30
|
| `get_design_tokens` | Returns design tokens (colors, fonts, spacing, radius, etc.) | none |
|
|
31
31
|
| `get_theme_css` | Returns CSS variables (`:root`, `.dark`, `@theme`) | none |
|
|
32
32
|
| `get_component_list` | Returns a list of available components | none |
|
|
33
|
-
| `get_component_spec` | Returns the spec for a component (props, variants,
|
|
33
|
+
| `get_component_spec` | Returns the spec for a component (props, variants, CVA classes, resolved colors) | `component`: component name |
|
|
34
34
|
| `search_components` | Searches components by keyword (Japanese supported) | `query`: search query |
|
|
35
35
|
| `get_wireframes` | Returns wireframe screen list and navigation flows | none |
|
|
36
36
|
| `get_wireframe_detail` | Returns screen details (components, states, behaviors) | `screen_id`: screen ID |
|
|
@@ -105,6 +105,28 @@ Supported: hover, focus-visible, active, disabled
|
|
|
105
105
|
|
|
106
106
|
---
|
|
107
107
|
|
|
108
|
+
## Style Config (botanical-organic)
|
|
109
|
+
|
|
110
|
+
**Type**: single
|
|
111
|
+
|
|
112
|
+
**Base Styles**:
|
|
113
|
+
`inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-full text-sm font-medium ...`
|
|
114
|
+
|
|
115
|
+
**variant**:
|
|
116
|
+
- default: `bg-primary text-primary-foreground shadow-sm hover:bg-primary/90 hover:shadow`
|
|
117
|
+
- destructive: `bg-destructive text-destructive-foreground hover:bg-destructive/90`
|
|
118
|
+
- outline: `border border-primary/50 bg-transparent text-primary hover:bg-primary/5`
|
|
119
|
+
- secondary: `bg-secondary text-secondary-foreground hover:bg-secondary/80`
|
|
120
|
+
- ghost: `text-primary hover:bg-accent`
|
|
121
|
+
- link: `text-primary underline-offset-4 hover:underline`
|
|
122
|
+
|
|
123
|
+
**Resolved Colors** (preferred appearance):
|
|
124
|
+
- primary: bg=#7C3AED, fg=#FFFFFF
|
|
125
|
+
- secondary: bg=#F472B6, fg=#1E293B
|
|
126
|
+
- destructive: #EF4444
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
108
130
|
## Registry Spec (JSON)
|
|
109
131
|
```json
|
|
110
132
|
{
|
|
@@ -119,7 +141,7 @@ Supported: hover, focus-visible, active, disabled
|
|
|
119
141
|
}
|
|
120
142
|
````
|
|
121
143
|
|
|
122
|
-
Components with registered metadata return both a guide and registry JSON. Components without metadata return registry JSON only.
|
|
144
|
+
Components with registered metadata return both a guide and registry JSON. Components without metadata return registry JSON only. When the project has a generated design system, a **Style Config** section with CVA class definitions and resolved color values is included between the guide and registry spec.
|
|
123
145
|
|
|
124
146
|
**`get_component_list`** — Array of component summaries
|
|
125
147
|
|
|
@@ -95,10 +95,17 @@ export function generateComponentGuide(info) {
|
|
|
95
95
|
}
|
|
96
96
|
// Important rules (common to all)
|
|
97
97
|
lines.push("## Important Rules");
|
|
98
|
-
lines.push("- Always use design token CSS variables — never hardcode colors or spacing.");
|
|
98
|
+
lines.push("- Always use design token CSS variables — never hardcode colors or spacing. However, Style Config classes override tokens when explicitly specified (see Style Precedence below).");
|
|
99
99
|
lines.push("- Follow the variant system — do not create ad-hoc style overrides.");
|
|
100
100
|
if (meta.type === "multipart") {
|
|
101
101
|
lines.push("- Use the slot-based structure — each slot has specific styling responsibilities.");
|
|
102
102
|
}
|
|
103
|
+
lines.push("");
|
|
104
|
+
// Style precedence rules
|
|
105
|
+
lines.push("## Style Precedence");
|
|
106
|
+
lines.push("When Style Config and Semantic Tokens conflict, apply this order:");
|
|
107
|
+
lines.push("1. **Style Config classes take highest priority** — they encode component-specific design intent (e.g. `text-white` overrides `text-primary-foreground`).");
|
|
108
|
+
lines.push("2. **Semantic Tokens as fallback** — use tokens only for attributes not specified in the Style Config.");
|
|
109
|
+
lines.push("3. **Resolved Colors are reference values** — they show the actual rendered colors but do not override Style Config classes.");
|
|
103
110
|
return lines.join("\n");
|
|
104
111
|
}
|
package/dist/index.js
CHANGED
|
@@ -17,7 +17,7 @@ import { handleGetConcept, handleGetDesignRationale } from "./tools/concept.js";
|
|
|
17
17
|
import { handleGetDesignTokens, handleGetThemeCss, } from "./tools/design-tokens.js";
|
|
18
18
|
import { handleGetWireframeDetail, handleGetWireframes, } from "./tools/wireframes.js";
|
|
19
19
|
// --- コマンドライン引数パース ---
|
|
20
|
-
const VERSION = "0.1
|
|
20
|
+
const VERSION = "0.2.1";
|
|
21
21
|
function parseArgs() {
|
|
22
22
|
const args = process.argv.slice(2);
|
|
23
23
|
if (args.includes("--help") || args.includes("-h")) {
|
|
@@ -92,7 +92,7 @@ const TOOLS = [
|
|
|
92
92
|
},
|
|
93
93
|
{
|
|
94
94
|
name: "get_component_spec",
|
|
95
|
-
description: "
|
|
95
|
+
description: "指定したコンポーネントの仕様(props・バリアント等)を返します。プロジェクトにデザインシステムが生成済みの場合、CVAクラス定義・解決済みカラー値も含まれます",
|
|
96
96
|
inputSchema: {
|
|
97
97
|
type: "object",
|
|
98
98
|
properties: {
|
package/dist/tools/components.js
CHANGED
|
@@ -93,11 +93,24 @@ export async function handleGetComponentSpec(client, projectId, componentName) {
|
|
|
93
93
|
description: spec.description,
|
|
94
94
|
categories: spec.categories,
|
|
95
95
|
});
|
|
96
|
+
// スタイル設定を取得(失敗しても既存レスポンスは返す)
|
|
97
|
+
let styleSection = "";
|
|
98
|
+
try {
|
|
99
|
+
const styleData = await client.get(`/api/projects/${encodeURIComponent(projectId)}/design-system/component-styles/${encodeURIComponent(componentName)}`);
|
|
100
|
+
styleSection = formatStyleSection(styleData);
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
// DS未生成等でスタイルが取得できない場合はスキップ
|
|
104
|
+
}
|
|
96
105
|
const parts = [];
|
|
97
106
|
if (guide) {
|
|
98
107
|
parts.push(guide);
|
|
99
108
|
parts.push("", "---", "");
|
|
100
109
|
}
|
|
110
|
+
if (styleSection) {
|
|
111
|
+
parts.push(styleSection);
|
|
112
|
+
parts.push("", "---", "");
|
|
113
|
+
}
|
|
101
114
|
parts.push("## Registry Spec (JSON)");
|
|
102
115
|
parts.push("```json");
|
|
103
116
|
parts.push(JSON.stringify(spec, null, 2));
|
|
@@ -227,6 +240,75 @@ export async function handleSearchComponents(client, projectId, query) {
|
|
|
227
240
|
const text = `## Search Results for "${query}"\n\n${header}${rows}\n\nUse \`get_component_spec\` with a component name for full details.`;
|
|
228
241
|
return [{ type: "text", text }];
|
|
229
242
|
}
|
|
243
|
+
function formatStyleSection(data) {
|
|
244
|
+
const lines = [];
|
|
245
|
+
const styleId = data.styleId;
|
|
246
|
+
const type = data.type;
|
|
247
|
+
const overrideApplied = data.overrideApplied;
|
|
248
|
+
lines.push(`## Style Config${styleId ? ` (${styleId})` : ""}${overrideApplied ? " [override applied]" : ""}`);
|
|
249
|
+
lines.push("");
|
|
250
|
+
lines.push("> **Priority**: Resolve conflicts in this order — (1) **Style Config classes** (highest), (2) **Semantic Tokens** (fallback when class is not specified), (3) **Resolved Colors** (reference-only; never override classes).");
|
|
251
|
+
lines.push("");
|
|
252
|
+
lines.push(`**Type**: ${type}`);
|
|
253
|
+
lines.push("");
|
|
254
|
+
if (type === "single") {
|
|
255
|
+
const baseStyles = data.baseStyles;
|
|
256
|
+
const variants = data.variants;
|
|
257
|
+
lines.push("**Base Styles**:");
|
|
258
|
+
lines.push(`\`${baseStyles}\``);
|
|
259
|
+
lines.push("");
|
|
260
|
+
if (variants) {
|
|
261
|
+
for (const [groupName, groupVariants] of Object.entries(variants)) {
|
|
262
|
+
lines.push(`**${groupName}**:`);
|
|
263
|
+
for (const [name, classes] of Object.entries(groupVariants)) {
|
|
264
|
+
lines.push(`- ${name}: \`${classes}\``);
|
|
265
|
+
}
|
|
266
|
+
lines.push("");
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
else if (type === "multipart") {
|
|
271
|
+
const slots = data.slots;
|
|
272
|
+
if (slots) {
|
|
273
|
+
lines.push("**Slots**:");
|
|
274
|
+
for (const [slotName, classes] of Object.entries(slots)) {
|
|
275
|
+
lines.push(`- ${slotName}: \`${classes}\``);
|
|
276
|
+
}
|
|
277
|
+
lines.push("");
|
|
278
|
+
}
|
|
279
|
+
const variants = data.variants;
|
|
280
|
+
if (variants && Object.keys(variants).length > 0) {
|
|
281
|
+
for (const [groupName, groupVariants] of Object.entries(variants)) {
|
|
282
|
+
lines.push(`**${groupName}**:`);
|
|
283
|
+
for (const [name, classes] of Object.entries(groupVariants)) {
|
|
284
|
+
lines.push(`- ${name}: \`${classes}\``);
|
|
285
|
+
}
|
|
286
|
+
lines.push("");
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
const resolvedColors = data.resolvedColors;
|
|
291
|
+
if (resolvedColors && Object.keys(resolvedColors).length > 0) {
|
|
292
|
+
lines.push("**Resolved Colors** (preferred appearance):");
|
|
293
|
+
for (const [name, value] of Object.entries(resolvedColors)) {
|
|
294
|
+
if (typeof value === "string") {
|
|
295
|
+
lines.push(`- ${name}: ${value}`);
|
|
296
|
+
}
|
|
297
|
+
else if (value && typeof value === "object") {
|
|
298
|
+
const pair = value;
|
|
299
|
+
if (typeof pair.background === "string" ||
|
|
300
|
+
typeof pair.foreground === "string") {
|
|
301
|
+
lines.push(`- ${name}: bg=${pair.background ?? "-"}, fg=${pair.foreground ?? "-"}`);
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
lines.push(`- ${name}: \`${JSON.stringify(value)}\``);
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
lines.push("");
|
|
309
|
+
}
|
|
310
|
+
return lines.join("\n");
|
|
311
|
+
}
|
|
230
312
|
/** テスト用にキャッシュをクリアする */
|
|
231
313
|
export function clearRegistryCache() {
|
|
232
314
|
cache = new WeakMap();
|
package/package.json
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
],
|
|
11
11
|
"homepage": "https://vaden.ai",
|
|
12
12
|
"license": "MIT",
|
|
13
|
-
"version": "0.1
|
|
13
|
+
"version": "0.2.1",
|
|
14
14
|
"type": "module",
|
|
15
15
|
"publishConfig": {
|
|
16
16
|
"access": "public"
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
"postbuild": "node scripts/postbuild.js",
|
|
35
35
|
"prepack": "npm run build",
|
|
36
36
|
"test": "vitest run",
|
|
37
|
+
"test:unit": "vitest run",
|
|
37
38
|
"typecheck": "tsc --noEmit"
|
|
38
39
|
},
|
|
39
40
|
"files": [
|