@vadenai/mcp-server 0.1.0 → 0.2.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.
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, etc.) | `component`: component name |
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
 
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.0";
20
+ const VERSION = "0.2.0";
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: "指定したコンポーネントの仕様(props・バリアント等)を返します",
95
+ description: "指定したコンポーネントの仕様(props・バリアント等)を返します。プロジェクトにデザインシステムが生成済みの場合、CVAクラス定義・解決済みカラー値も含まれます",
96
96
  inputSchema: {
97
97
  type: "object",
98
98
  properties: {
@@ -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,73 @@ 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(`**Type**: ${type}`);
251
+ lines.push("");
252
+ if (type === "single") {
253
+ const baseStyles = data.baseStyles;
254
+ const variants = data.variants;
255
+ lines.push("**Base Styles**:");
256
+ lines.push(`\`${baseStyles}\``);
257
+ lines.push("");
258
+ if (variants) {
259
+ for (const [groupName, groupVariants] of Object.entries(variants)) {
260
+ lines.push(`**${groupName}**:`);
261
+ for (const [name, classes] of Object.entries(groupVariants)) {
262
+ lines.push(`- ${name}: \`${classes}\``);
263
+ }
264
+ lines.push("");
265
+ }
266
+ }
267
+ }
268
+ else if (type === "multipart") {
269
+ const slots = data.slots;
270
+ if (slots) {
271
+ lines.push("**Slots**:");
272
+ for (const [slotName, classes] of Object.entries(slots)) {
273
+ lines.push(`- ${slotName}: \`${classes}\``);
274
+ }
275
+ lines.push("");
276
+ }
277
+ const variants = data.variants;
278
+ if (variants && Object.keys(variants).length > 0) {
279
+ for (const [groupName, groupVariants] of Object.entries(variants)) {
280
+ lines.push(`**${groupName}**:`);
281
+ for (const [name, classes] of Object.entries(groupVariants)) {
282
+ lines.push(`- ${name}: \`${classes}\``);
283
+ }
284
+ lines.push("");
285
+ }
286
+ }
287
+ }
288
+ const resolvedColors = data.resolvedColors;
289
+ if (resolvedColors && Object.keys(resolvedColors).length > 0) {
290
+ lines.push("**Resolved Colors** (preferred appearance):");
291
+ for (const [name, value] of Object.entries(resolvedColors)) {
292
+ if (typeof value === "string") {
293
+ lines.push(`- ${name}: ${value}`);
294
+ }
295
+ else if (value && typeof value === "object") {
296
+ const pair = value;
297
+ if (typeof pair.background === "string" ||
298
+ typeof pair.foreground === "string") {
299
+ lines.push(`- ${name}: bg=${pair.background ?? "-"}, fg=${pair.foreground ?? "-"}`);
300
+ }
301
+ else {
302
+ lines.push(`- ${name}: \`${JSON.stringify(value)}\``);
303
+ }
304
+ }
305
+ }
306
+ lines.push("");
307
+ }
308
+ return lines.join("\n");
309
+ }
230
310
  /** テスト用にキャッシュをクリアする */
231
311
  export function clearRegistryCache() {
232
312
  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.0",
13
+ "version": "0.2.0",
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": [