gemini-design-mcp 3.3.0 → 3.4.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/build/index.js CHANGED
@@ -4,6 +4,7 @@ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
4
4
  import { createFrontendSchema, createFrontend } from "./tools/create-frontend.js";
5
5
  import { modifyFrontendSchema, modifyFrontend } from "./tools/modify-frontend.js";
6
6
  import { snippetFrontendSchema, snippetFrontend } from "./tools/snippet-frontend.js";
7
+ import { generateVibesSchema, generateVibes } from "./tools/generate-vibes.js";
7
8
  // Create MCP server
8
9
  const server = new McpServer({
9
10
  name: "gemini-design-mcp",
@@ -50,13 +51,8 @@ C) PROJECT EXISTS with existing frontend code:
50
51
 
51
52
  STEP 2: VIBE SELECTION (Required for new designs)
52
53
  ──────────────────────────────────────────────────
53
- Generate 5 vibe options with RICH descriptions (2-3 sentences each):
54
-
55
- 🏛️ "Pristine Museum" - Ultra-clean, white-cube aesthetic...
56
- ⚡ "Technical Precision" - Grid-focused, architectural...
57
- 🌊 "Fluid & Organic" - Soft curves, flowing gradients...
58
- 🔥 "Bold & Unapologetic" - High contrast, oversized typography...
59
- 🌙 "Dark Luxe" - Deep darks, metallic accents...
54
+ Call generate_vibes tool FIRST to get 5 creative vibes from Gemini.
55
+ Present options to user, they select one, then pass it here via designSystem.vibe.
60
56
 
61
57
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
62
58
  📤 OUTPUT
@@ -216,6 +212,44 @@ You (Claude) are responsible for:
216
212
  - Merging new imports
217
213
  - Inserting the snippet at the correct location`, snippetFrontendSchema, snippetFrontend);
218
214
  // =============================================================================
215
+ // TOOL 4: GENERATE_VIBES
216
+ // =============================================================================
217
+ server.tool("generate_vibes", `Generate 5 unique design vibes for a new project using Gemini AI.
218
+
219
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
220
+ 🎯 WHEN TO USE THIS TOOL
221
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
222
+
223
+ Use this tool BEFORE calling create_frontend on a NEW project that has no existing design.
224
+
225
+ This tool generates creative, unique design vibes tailored to the project context.
226
+ The user then selects one, and you pass it to create_frontend.
227
+
228
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
229
+ 📋 FLOW
230
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
231
+
232
+ 1. User asks to create frontend for a NEW project
233
+ 2. Call generate_vibes with project description
234
+ 3. Present the 5 vibes to the user
235
+ 4. User selects their preferred vibe
236
+ 5. Call create_frontend with the selected vibe in designSystem.vibe
237
+
238
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
239
+ 📤 OUTPUT
240
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
241
+
242
+ Returns 5 vibes, each with:
243
+ - emoji: Visual identifier
244
+ - name: Memorable vibe name
245
+ - description: 2-3 evocative sentences
246
+ - keywords: Style keywords for the designer
247
+
248
+ Example vibe:
249
+ 🏛️ "Pristine Museum"
250
+ An ultra-clean, 'white-cube' aesthetic focused on vast negative space.
251
+ Keywords: minimal, whitespace, gallery, clean, sophisticated`, generateVibesSchema, generateVibes);
252
+ // =============================================================================
219
253
  // START SERVER
220
254
  // =============================================================================
221
255
  async function main() {
@@ -1,4 +1,5 @@
1
1
  import { GoogleGenAI } from "@google/genai";
2
+ export type ThinkingMode = "minimal" | "low" | "medium" | "high";
2
3
  export declare const ai: GoogleGenAI | null;
3
4
  export declare const DEFAULT_MODEL = "gemini-3-flash-preview";
4
- export declare function generateWithGemini(systemPrompt: string, userPrompt: string, model?: string): Promise<string>;
5
+ export declare function generateWithGemini(systemPrompt: string, userPrompt: string, model?: string, thinkingMode?: ThinkingMode): Promise<string>;
@@ -1,4 +1,4 @@
1
- import { GoogleGenAI, ThinkingLevel } from "@google/genai";
1
+ import { GoogleGenAI } from "@google/genai";
2
2
  const apiKey = process.env.API_KEY;
3
3
  if (!apiKey) {
4
4
  console.error("ERROR: API_KEY environment variable is required");
@@ -16,7 +16,7 @@ export const DEFAULT_MODEL = "gemini-3-flash-preview";
16
16
  /**
17
17
  * Generate content via the hosted proxy service
18
18
  */
19
- async function generateViaProxy(systemPrompt, userPrompt, model) {
19
+ async function generateViaProxy(systemPrompt, userPrompt, model, thinkingMode = "minimal") {
20
20
  const response = await fetch(PROXY_URL, {
21
21
  method: "POST",
22
22
  headers: {
@@ -37,7 +37,7 @@ async function generateViaProxy(systemPrompt, userPrompt, model) {
37
37
  generationConfig: {
38
38
  temperature: 1,
39
39
  thinkingConfig: {
40
- thinkingBudget: 1024, // LOW thinking level
40
+ thinkingLevel: thinkingMode,
41
41
  },
42
42
  },
43
43
  }),
@@ -57,7 +57,7 @@ async function generateViaProxy(systemPrompt, userPrompt, model) {
57
57
  /**
58
58
  * Generate content directly via Google SDK
59
59
  */
60
- async function generateViaSdk(systemPrompt, userPrompt, model) {
60
+ async function generateViaSdk(systemPrompt, userPrompt, model, thinkingMode = "minimal") {
61
61
  if (!ai) {
62
62
  throw new Error("SDK not initialized");
63
63
  }
@@ -68,19 +68,19 @@ async function generateViaSdk(systemPrompt, userPrompt, model) {
68
68
  systemInstruction: systemPrompt,
69
69
  temperature: 1,
70
70
  thinkingConfig: {
71
- thinkingLevel: ThinkingLevel.LOW,
71
+ thinkingLevel: thinkingMode,
72
72
  },
73
73
  },
74
74
  });
75
75
  return response.text ?? "";
76
76
  }
77
- export async function generateWithGemini(systemPrompt, userPrompt, model = DEFAULT_MODEL) {
77
+ export async function generateWithGemini(systemPrompt, userPrompt, model = DEFAULT_MODEL, thinkingMode = "minimal") {
78
78
  try {
79
79
  if (isHostedKey) {
80
- return await generateViaProxy(systemPrompt, userPrompt, model);
80
+ return await generateViaProxy(systemPrompt, userPrompt, model, thinkingMode);
81
81
  }
82
82
  else {
83
- return await generateViaSdk(systemPrompt, userPrompt, model);
83
+ return await generateViaSdk(systemPrompt, userPrompt, model, thinkingMode);
84
84
  }
85
85
  }
86
86
  catch (error) {
@@ -64,7 +64,7 @@ TECH STACK: ${techStack}
64
64
  FILE PATH: ${filePath}
65
65
 
66
66
  Remember: Return a COMPLETE file ready to save at ${filePath}`.trim();
67
- const result = await generateWithGemini(systemPrompt, request);
67
+ const result = await generateWithGemini(systemPrompt, request, undefined, "high");
68
68
  return {
69
69
  content: [{ type: "text", text: result }],
70
70
  };
@@ -0,0 +1,23 @@
1
+ import { z } from "zod";
2
+ export declare const generateVibesSchema: {
3
+ projectDescription: z.ZodString;
4
+ projectType: z.ZodOptional<z.ZodString>;
5
+ targetAudience: z.ZodOptional<z.ZodString>;
6
+ };
7
+ export declare function generateVibes(params: {
8
+ projectDescription: string;
9
+ projectType?: string;
10
+ targetAudience?: string;
11
+ }): Promise<{
12
+ content: {
13
+ type: "text";
14
+ text: string;
15
+ }[];
16
+ vibes: any;
17
+ } | {
18
+ content: {
19
+ type: "text";
20
+ text: string;
21
+ }[];
22
+ vibes?: undefined;
23
+ }>;
@@ -0,0 +1,85 @@
1
+ import { z } from "zod";
2
+ import { generateWithGemini } from "../lib/gemini.js";
3
+ export const generateVibesSchema = {
4
+ projectDescription: z.string().describe("Brief description of the project. " +
5
+ "Example: 'A SaaS dashboard for managing customer support tickets'"),
6
+ projectType: z.string().optional().describe("Type of project. " +
7
+ "Examples: 'landing page', 'dashboard', 'e-commerce', 'portfolio', 'blog', 'mobile app'"),
8
+ targetAudience: z.string().optional().describe("Who will use this app. " +
9
+ "Examples: 'developers', 'enterprise clients', 'young consumers', 'creative professionals'"),
10
+ };
11
+ const GENERATE_VIBES_PROMPT = `Generate 5 distinct mood/atmosphere options (VIBES) that match different interpretations of the project.
12
+
13
+ Each vibe should represent a unique visual direction and feeling.
14
+ Describe the mood, not specific colors - let the designer interpret creatively.
15
+ Think: "Corporate & Trustworthy" vs "Playful & Vibrant" vs "Dark & Techy"
16
+
17
+ OUTPUT FORMAT (JSON):
18
+ Return ONLY a valid JSON array with exactly 5 vibes. No markdown, no explanation.
19
+
20
+ [
21
+ {
22
+ "emoji": "🏛️",
23
+ "name": "Vibe Name",
24
+ "description": "2-3 sentences describing the mood and atmosphere.",
25
+ "keywords": ["keyword1", "keyword2", "keyword3"]
26
+ }
27
+ ]`;
28
+ export async function generateVibes(params) {
29
+ const { projectDescription, projectType, targetAudience } = params;
30
+ // Build context for Gemini
31
+ let contextParts = [`Project: ${projectDescription}`];
32
+ if (projectType) {
33
+ contextParts.push(`Type: ${projectType}`);
34
+ }
35
+ if (targetAudience) {
36
+ contextParts.push(`Target Audience: ${targetAudience}`);
37
+ }
38
+ const userPrompt = contextParts.join("\n");
39
+ const result = await generateWithGemini(GENERATE_VIBES_PROMPT, userPrompt, undefined, // default model
40
+ "high" // high thinking for creative vibes
41
+ );
42
+ // Parse the JSON response
43
+ try {
44
+ // Clean the response (remove potential markdown code blocks)
45
+ let cleanedResult = result.trim();
46
+ if (cleanedResult.startsWith("```json")) {
47
+ cleanedResult = cleanedResult.slice(7);
48
+ }
49
+ if (cleanedResult.startsWith("```")) {
50
+ cleanedResult = cleanedResult.slice(3);
51
+ }
52
+ if (cleanedResult.endsWith("```")) {
53
+ cleanedResult = cleanedResult.slice(0, -3);
54
+ }
55
+ cleanedResult = cleanedResult.trim();
56
+ const vibes = JSON.parse(cleanedResult);
57
+ // Format vibes for display
58
+ const formattedVibes = vibes.map((vibe, index) => {
59
+ return `${index + 1}. ${vibe.emoji} "${vibe.name}"
60
+ ${vibe.description}
61
+ Keywords: ${vibe.keywords.join(", ")}`;
62
+ }).join("\n\n");
63
+ return {
64
+ content: [
65
+ {
66
+ type: "text",
67
+ text: `Here are 5 design vibes generated for your project:\n\n${formattedVibes}\n\n---\n\nAsk the user to select one vibe. Once selected, pass it to create_frontend via the designSystem.vibe parameter with:\n- name: The vibe name (e.g., "Pristine Museum")\n- description: The full description\n- keywords: The array of keywords`,
68
+ },
69
+ ],
70
+ // Also return structured data for programmatic use
71
+ vibes,
72
+ };
73
+ }
74
+ catch {
75
+ // If parsing fails, return raw result
76
+ return {
77
+ content: [
78
+ {
79
+ type: "text",
80
+ text: `Generated vibes:\n\n${result}\n\n---\n\nNote: Could not parse as JSON. Please extract the vibes manually.`,
81
+ },
82
+ ],
83
+ };
84
+ }
85
+ }
@@ -37,7 +37,7 @@ ${targetCode}
37
37
  MODIFICATION REQUESTED: ${modification}
38
38
 
39
39
  Remember: Return ONLY the find/replace block. ONE modification, surgical precision.`.trim();
40
- const result = await generateWithGemini(systemPrompt, modification);
40
+ const result = await generateWithGemini(systemPrompt, modification, undefined, "minimal");
41
41
  return {
42
42
  content: [{ type: "text", text: result }],
43
43
  };
@@ -39,7 +39,7 @@ INSERTION CONTEXT:
39
39
  ${insertionContext}
40
40
 
41
41
  Generate a snippet that will integrate smoothly at this location.`.trim();
42
- const result = await generateWithGemini(systemPrompt, request);
42
+ const result = await generateWithGemini(systemPrompt, request, undefined, "minimal");
43
43
  return {
44
44
  content: [{ type: "text", text: result }],
45
45
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gemini-design-mcp",
3
- "version": "3.3.0",
3
+ "version": "3.4.0",
4
4
  "description": "MCP server that uses Gemini 3 Pro for frontend/design code generation",
5
5
  "main": "build/index.js",
6
6
  "bin": {