@gemini-designer/mcp-server 0.1.2 → 0.1.29

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 (129) hide show
  1. package/dist/components/catalog.d.ts.map +1 -1
  2. package/dist/components/catalog.js +10 -4
  3. package/dist/components/catalog.js.map +1 -1
  4. package/dist/config/index.d.ts.map +1 -1
  5. package/dist/config/index.js +11 -6
  6. package/dist/config/index.js.map +1 -1
  7. package/dist/context/builder.d.ts.map +1 -1
  8. package/dist/context/builder.js.map +1 -1
  9. package/dist/context/filter.d.ts.map +1 -1
  10. package/dist/context/filter.js +5 -1
  11. package/dist/context/filter.js.map +1 -1
  12. package/dist/context/grounding.d.ts.map +1 -1
  13. package/dist/context/grounding.js +7 -3
  14. package/dist/context/grounding.js.map +1 -1
  15. package/dist/context/guards.d.ts.map +1 -1
  16. package/dist/context/guards.js +53 -0
  17. package/dist/context/guards.js.map +1 -1
  18. package/dist/context/repo-hints.js.map +1 -1
  19. package/dist/context/styling-detector.d.ts +24 -0
  20. package/dist/context/styling-detector.d.ts.map +1 -0
  21. package/dist/context/styling-detector.js +337 -0
  22. package/dist/context/styling-detector.js.map +1 -0
  23. package/dist/design/principles.js.map +1 -1
  24. package/dist/generation/gemini-client.d.ts.map +1 -1
  25. package/dist/generation/gemini-client.js.map +1 -1
  26. package/dist/generation/litellm-client.d.ts.map +1 -1
  27. package/dist/generation/litellm-client.js +14 -7
  28. package/dist/generation/litellm-client.js.map +1 -1
  29. package/dist/generation/remote-client.d.ts +10 -5
  30. package/dist/generation/remote-client.d.ts.map +1 -1
  31. package/dist/generation/remote-client.js +13 -2
  32. package/dist/generation/remote-client.js.map +1 -1
  33. package/dist/index.js.map +1 -1
  34. package/dist/output/file-writer.d.ts.map +1 -1
  35. package/dist/output/file-writer.js +4 -4
  36. package/dist/output/file-writer.js.map +1 -1
  37. package/dist/output/formatter.d.ts.map +1 -1
  38. package/dist/output/formatter.js +5 -2
  39. package/dist/output/formatter.js.map +1 -1
  40. package/dist/server.d.ts.map +1 -1
  41. package/dist/server.js +2 -1
  42. package/dist/server.js.map +1 -1
  43. package/dist/stack/detect.d.ts.map +1 -1
  44. package/dist/stack/detect.js +42 -9
  45. package/dist/stack/detect.js.map +1 -1
  46. package/dist/tokens/sync.d.ts.map +1 -1
  47. package/dist/tokens/sync.js +22 -5
  48. package/dist/tokens/sync.js.map +1 -1
  49. package/dist/tools/analyze-screenshot-ui.d.ts.map +1 -1
  50. package/dist/tools/analyze-screenshot-ui.js +5 -5
  51. package/dist/tools/analyze-screenshot-ui.js.map +1 -1
  52. package/dist/tools/analyze-tokens.d.ts.map +1 -1
  53. package/dist/tools/analyze-tokens.js +3 -1
  54. package/dist/tools/analyze-tokens.js.map +1 -1
  55. package/dist/tools/catalog-components.d.ts.map +1 -1
  56. package/dist/tools/catalog-components.js +1 -4
  57. package/dist/tools/catalog-components.js.map +1 -1
  58. package/dist/tools/create-ui.d.ts +3 -0
  59. package/dist/tools/create-ui.d.ts.map +1 -1
  60. package/dist/tools/create-ui.js +203 -75
  61. package/dist/tools/create-ui.js.map +1 -1
  62. package/dist/tools/detect-ui-stack.js.map +1 -1
  63. package/dist/tools/generate-component-variants.d.ts.map +1 -1
  64. package/dist/tools/generate-component-variants.js +15 -4
  65. package/dist/tools/generate-component-variants.js.map +1 -1
  66. package/dist/tools/generate-vibes.d.ts.map +1 -1
  67. package/dist/tools/generate-vibes.js +7 -3
  68. package/dist/tools/generate-vibes.js.map +1 -1
  69. package/dist/tools/index.js.map +1 -1
  70. package/dist/tools/modify-ui.d.ts.map +1 -1
  71. package/dist/tools/modify-ui.js +7 -2
  72. package/dist/tools/modify-ui.js.map +1 -1
  73. package/dist/tools/scaffold-project.d.ts.map +1 -1
  74. package/dist/tools/scaffold-project.js +3 -1
  75. package/dist/tools/scaffold-project.js.map +1 -1
  76. package/dist/tools/snippet-ui.d.ts +3 -1
  77. package/dist/tools/snippet-ui.d.ts.map +1 -1
  78. package/dist/tools/snippet-ui.js +219 -88
  79. package/dist/tools/snippet-ui.js.map +1 -1
  80. package/dist/tools/sync-design-tokens.d.ts.map +1 -1
  81. package/dist/tools/sync-design-tokens.js +26 -11
  82. package/dist/tools/sync-design-tokens.js.map +1 -1
  83. package/dist/utils/walk.d.ts.map +1 -1
  84. package/dist/utils/walk.js.map +1 -1
  85. package/dist/version.d.ts +2 -0
  86. package/dist/version.d.ts.map +1 -0
  87. package/dist/version.js +5 -0
  88. package/dist/version.js.map +1 -0
  89. package/package.json +55 -55
  90. package/src/__tests__/builder.test.ts +19 -19
  91. package/src/__tests__/config.test.ts +63 -31
  92. package/src/__tests__/filter.test.ts +98 -92
  93. package/src/__tests__/remote-client.test.ts +179 -0
  94. package/src/components/catalog.ts +170 -166
  95. package/src/config/index.ts +185 -177
  96. package/src/context/builder.ts +157 -157
  97. package/src/context/filter.ts +110 -104
  98. package/src/context/grounding.ts +143 -129
  99. package/src/context/guards.ts +97 -38
  100. package/src/context/repo-hints.ts +24 -24
  101. package/src/context/styling-detector.ts +460 -0
  102. package/src/design/principles.ts +14 -14
  103. package/src/generation/gemini-client.ts +53 -56
  104. package/src/generation/litellm-client.ts +102 -86
  105. package/src/generation/remote-client.ts +100 -77
  106. package/src/index.ts +16 -16
  107. package/src/output/file-writer.ts +123 -123
  108. package/src/output/formatter.ts +139 -132
  109. package/src/server.ts +12 -11
  110. package/src/stack/detect.ts +226 -175
  111. package/src/tokens/sync.ts +189 -155
  112. package/src/tools/analyze-screenshot-ui.ts +89 -88
  113. package/src/tools/analyze-tokens.ts +80 -78
  114. package/src/tools/catalog-components.ts +68 -68
  115. package/src/tools/create-ui.ts +295 -142
  116. package/src/tools/detect-ui-stack.ts +36 -36
  117. package/src/tools/generate-component-variants.ts +155 -135
  118. package/src/tools/generate-vibes.ts +121 -117
  119. package/src/tools/index.ts +14 -14
  120. package/src/tools/modify-ui.ts +170 -165
  121. package/src/tools/scaffold-project.ts +68 -66
  122. package/src/tools/snippet-ui.ts +323 -172
  123. package/src/tools/sync-design-tokens.ts +217 -195
  124. package/src/utils/walk.ts +47 -45
  125. package/src/version.ts +6 -0
  126. package/tsconfig.json +23 -33
  127. package/vitest.config.ts +10 -10
  128. package/.prettierrc +0 -9
  129. package/eslint.config.js +0 -37
@@ -7,175 +7,175 @@
7
7
 
8
8
  import * as fs from 'node:fs';
9
9
  import * as path from 'node:path';
10
- import { execSync } from 'node:child_process';
10
+ import { execFileSync } from 'node:child_process';
11
11
  import { formatCode } from './formatter.js';
12
12
 
13
13
  export interface WriteOptions {
14
- backup?: boolean;
15
- format?: boolean;
16
- createDirs?: boolean;
17
- gitAdd?: boolean;
14
+ backup?: boolean;
15
+ format?: boolean;
16
+ createDirs?: boolean;
17
+ gitAdd?: boolean;
18
18
  }
19
19
 
20
20
  export interface WriteResult {
21
- success: boolean;
22
- filePath: string;
23
- backupPath?: string;
24
- error?: string;
21
+ success: boolean;
22
+ filePath: string;
23
+ backupPath?: string;
24
+ error?: string;
25
25
  }
26
26
 
27
27
  /**
28
28
  * Write content to file with safety features
29
29
  */
30
30
  export async function writeFile(
31
- filePath: string,
32
- content: string,
33
- options: WriteOptions = {}
31
+ filePath: string,
32
+ content: string,
33
+ options: WriteOptions = {}
34
34
  ): Promise<WriteResult> {
35
- const { backup = true, format = true, createDirs = true, gitAdd = false } = options;
35
+ const { backup = true, format = true, createDirs = true, gitAdd = false } = options;
36
36
 
37
- const absPath = path.isAbsolute(filePath) ? filePath : path.resolve(process.cwd(), filePath);
37
+ const absPath = path.isAbsolute(filePath) ? filePath : path.resolve(process.cwd(), filePath);
38
38
 
39
- try {
40
- // Create parent directories if needed
41
- if (createDirs) {
42
- const dir = path.dirname(absPath);
43
- if (!fs.existsSync(dir)) {
44
- fs.mkdirSync(dir, { recursive: true });
45
- }
46
- }
47
-
48
- // Create backup if file exists
49
- let backupPath: string | undefined;
50
- if (backup && fs.existsSync(absPath)) {
51
- backupPath = `${absPath}.bak`;
52
- fs.copyFileSync(absPath, backupPath);
53
- }
54
-
55
- // Format content if requested
56
- let finalContent = content;
57
- if (format) {
58
- try {
59
- finalContent = await formatCode(content, { filePath: absPath });
60
- } catch {
61
- // Keep original if formatting fails
62
- }
63
- }
64
-
65
- // Write the file
66
- fs.writeFileSync(absPath, finalContent, 'utf-8');
67
-
68
- // Git add if requested and in a git repo
69
- if (gitAdd && isGitRepo(absPath)) {
70
- try {
71
- execSync(`git add "${absPath}"`, { cwd: path.dirname(absPath), stdio: 'ignore' });
72
- } catch {
73
- // Ignore git errors
74
- }
75
- }
76
-
77
- return {
78
- success: true,
79
- filePath: absPath,
80
- backupPath,
81
- };
82
- } catch (error) {
83
- return {
84
- success: false,
85
- filePath: absPath,
86
- error: error instanceof Error ? error.message : 'Unknown error',
87
- };
39
+ try {
40
+ // Create parent directories if needed
41
+ if (createDirs) {
42
+ const dir = path.dirname(absPath);
43
+ if (!fs.existsSync(dir)) {
44
+ fs.mkdirSync(dir, { recursive: true });
45
+ }
46
+ }
47
+
48
+ // Create backup if file exists
49
+ let backupPath: string | undefined;
50
+ if (backup && fs.existsSync(absPath)) {
51
+ backupPath = `${absPath}.bak`;
52
+ fs.copyFileSync(absPath, backupPath);
53
+ }
54
+
55
+ // Format content if requested
56
+ let finalContent = content;
57
+ if (format) {
58
+ try {
59
+ finalContent = await formatCode(content, { filePath: absPath });
60
+ } catch {
61
+ // Keep original if formatting fails
62
+ }
63
+ }
64
+
65
+ // Write the file
66
+ fs.writeFileSync(absPath, finalContent, 'utf-8');
67
+
68
+ // Git add if requested and in a git repo
69
+ if (gitAdd && isGitRepo(absPath)) {
70
+ try {
71
+ execFileSync('git', ['add', absPath], { cwd: path.dirname(absPath), stdio: 'ignore' });
72
+ } catch {
73
+ // Ignore git errors
74
+ }
88
75
  }
76
+
77
+ return {
78
+ success: true,
79
+ filePath: absPath,
80
+ backupPath,
81
+ };
82
+ } catch (error) {
83
+ return {
84
+ success: false,
85
+ filePath: absPath,
86
+ error: error instanceof Error ? error.message : 'Unknown error',
87
+ };
88
+ }
89
89
  }
90
90
 
91
91
  /**
92
92
  * Restore file from backup
93
93
  */
94
94
  export function restoreFromBackup(filePath: string): boolean {
95
- const absPath = path.isAbsolute(filePath) ? filePath : path.resolve(process.cwd(), filePath);
96
- const backupPath = `${absPath}.bak`;
97
-
98
- if (!fs.existsSync(backupPath)) {
99
- return false;
100
- }
101
-
102
- try {
103
- fs.copyFileSync(backupPath, absPath);
104
- fs.unlinkSync(backupPath);
105
- return true;
106
- } catch {
107
- return false;
108
- }
95
+ const absPath = path.isAbsolute(filePath) ? filePath : path.resolve(process.cwd(), filePath);
96
+ const backupPath = `${absPath}.bak`;
97
+
98
+ if (!fs.existsSync(backupPath)) {
99
+ return false;
100
+ }
101
+
102
+ try {
103
+ fs.copyFileSync(backupPath, absPath);
104
+ fs.unlinkSync(backupPath);
105
+ return true;
106
+ } catch {
107
+ return false;
108
+ }
109
109
  }
110
110
 
111
111
  /**
112
112
  * Check if path is in a git repository
113
113
  */
114
114
  function isGitRepo(filePath: string): boolean {
115
- try {
116
- execSync('git rev-parse --git-dir', {
117
- cwd: path.dirname(filePath),
118
- stdio: 'ignore',
119
- });
120
- return true;
121
- } catch {
122
- return false;
123
- }
115
+ try {
116
+ execFileSync('git', ['rev-parse', '--git-dir'], {
117
+ cwd: path.dirname(filePath),
118
+ stdio: 'ignore',
119
+ });
120
+ return true;
121
+ } catch {
122
+ return false;
123
+ }
124
124
  }
125
125
 
126
126
  /**
127
127
  * Get git status for a file
128
128
  */
129
129
  export function getGitStatus(filePath: string): 'modified' | 'untracked' | 'clean' | 'not-git' {
130
- const absPath = path.isAbsolute(filePath) ? filePath : path.resolve(process.cwd(), filePath);
131
-
132
- if (!isGitRepo(absPath)) {
133
- return 'not-git';
134
- }
135
-
136
- try {
137
- const status = execSync(`git status --porcelain "${absPath}"`, {
138
- cwd: path.dirname(absPath),
139
- encoding: 'utf-8',
140
- }).trim();
141
-
142
- if (!status) return 'clean';
143
- if (status.startsWith('??')) return 'untracked';
144
- return 'modified';
145
- } catch {
146
- return 'not-git';
147
- }
130
+ const absPath = path.isAbsolute(filePath) ? filePath : path.resolve(process.cwd(), filePath);
131
+
132
+ if (!isGitRepo(absPath)) {
133
+ return 'not-git';
134
+ }
135
+
136
+ try {
137
+ const status = execFileSync('git', ['status', '--porcelain', absPath], {
138
+ cwd: path.dirname(absPath),
139
+ encoding: 'utf-8',
140
+ }).trim();
141
+
142
+ if (!status) return 'clean';
143
+ if (status.startsWith('??')) return 'untracked';
144
+ return 'modified';
145
+ } catch {
146
+ return 'not-git';
147
+ }
148
148
  }
149
149
 
150
150
  /**
151
151
  * List all backup files in a directory
152
152
  */
153
153
  export function listBackups(directory: string): string[] {
154
- try {
155
- const entries = fs.readdirSync(directory, { withFileTypes: true });
156
- return entries
157
- .filter((e) => e.isFile() && e.name.endsWith('.bak'))
158
- .map((e) => path.join(directory, e.name));
159
- } catch {
160
- return [];
161
- }
154
+ try {
155
+ const entries = fs.readdirSync(directory, { withFileTypes: true });
156
+ return entries
157
+ .filter((e) => e.isFile() && e.name.endsWith('.bak'))
158
+ .map((e) => path.join(directory, e.name));
159
+ } catch {
160
+ return [];
161
+ }
162
162
  }
163
163
 
164
164
  /**
165
165
  * Clean up old backup files
166
166
  */
167
167
  export function cleanBackups(directory: string): number {
168
- const backups = listBackups(directory);
169
- let cleaned = 0;
170
-
171
- for (const backup of backups) {
172
- try {
173
- fs.unlinkSync(backup);
174
- cleaned++;
175
- } catch {
176
- // Ignore errors
177
- }
168
+ const backups = listBackups(directory);
169
+ let cleaned = 0;
170
+
171
+ for (const backup of backups) {
172
+ try {
173
+ fs.unlinkSync(backup);
174
+ cleaned++;
175
+ } catch {
176
+ // Ignore errors
178
177
  }
178
+ }
179
179
 
180
- return cleaned;
180
+ return cleaned;
181
181
  }
@@ -10,177 +10,184 @@ import * as prettier from 'prettier';
10
10
  export type SupportedLanguage = 'typescript' | 'javascript' | 'css' | 'html' | 'json' | 'markdown';
11
11
 
12
12
  interface FormatOptions {
13
- language?: SupportedLanguage;
14
- filePath?: string;
15
- printWidth?: number;
16
- tabWidth?: number;
17
- useTabs?: boolean;
18
- semi?: boolean;
19
- singleQuote?: boolean;
13
+ language?: SupportedLanguage;
14
+ filePath?: string;
15
+ printWidth?: number;
16
+ tabWidth?: number;
17
+ useTabs?: boolean;
18
+ semi?: boolean;
19
+ singleQuote?: boolean;
20
20
  }
21
21
 
22
22
  /**
23
23
  * Format code using Prettier
24
24
  */
25
25
  export async function formatCode(code: string, options: FormatOptions = {}): Promise<string> {
26
- const language = options.language || detectLanguage(code, options.filePath);
27
- const parser = getParser(language);
28
-
29
- try {
30
- const formatted = await prettier.format(code, {
31
- parser,
32
- printWidth: options.printWidth ?? 100,
33
- tabWidth: options.tabWidth ?? 2,
34
- useTabs: options.useTabs ?? false,
35
- semi: options.semi ?? true,
36
- singleQuote: options.singleQuote ?? true,
37
- trailingComma: 'es5',
38
- bracketSpacing: true,
39
- arrowParens: 'always',
40
- });
41
-
42
- return formatted;
43
- } catch (error) {
44
- // If Prettier fails, return original code
45
- console.error('[formatter] Prettier error, returning unformatted:', error);
46
- return code;
47
- }
26
+ const language = options.language || detectLanguage(code, options.filePath);
27
+ const parser = getParser(language);
28
+
29
+ try {
30
+ const formatted = await prettier.format(code, {
31
+ parser,
32
+ printWidth: options.printWidth ?? 100,
33
+ tabWidth: options.tabWidth ?? 2,
34
+ useTabs: options.useTabs ?? false,
35
+ semi: options.semi ?? true,
36
+ singleQuote: options.singleQuote ?? true,
37
+ trailingComma: 'es5',
38
+ bracketSpacing: true,
39
+ arrowParens: 'always',
40
+ });
41
+
42
+ return formatted;
43
+ } catch (error) {
44
+ // If Prettier fails, return original code
45
+ console.error('[formatter] Prettier error, returning unformatted:', error);
46
+ return code;
47
+ }
48
48
  }
49
49
 
50
50
  /**
51
51
  * Extract code blocks from LLM response and format them
52
52
  */
53
53
  export async function formatLLMResponse(response: string): Promise<string> {
54
- // Match code blocks with language identifier
55
- const codeBlockRegex = /```(\w+)?\n([\s\S]*?)```/g;
56
- let result = response;
57
- let match;
58
-
59
- const replacements: Array<{ original: string; formatted: string }> = [];
60
-
61
- while ((match = codeBlockRegex.exec(response)) !== null) {
62
- const [fullMatch, lang, code] = match;
63
- const language = mapLanguageIdentifier(lang);
64
-
65
- if (language) {
66
- try {
67
- const formatted = await formatCode(code.trim(), { language });
68
- replacements.push({
69
- original: fullMatch,
70
- formatted: `\`\`\`${lang}\n${formatted}\`\`\``,
71
- });
72
- } catch {
73
- // Keep original if formatting fails
74
- }
75
- }
54
+ // Match code blocks with language identifier
55
+ const codeBlockRegex = /```(\w+)?\n([\s\S]*?)```/g;
56
+ let result = response;
57
+ let match;
58
+
59
+ const replacements: Array<{ original: string; formatted: string }> = [];
60
+
61
+ while ((match = codeBlockRegex.exec(response)) !== null) {
62
+ const [fullMatch, lang, code] = match;
63
+ const language = mapLanguageIdentifier(lang);
64
+
65
+ if (language) {
66
+ try {
67
+ const formatted = await formatCode(code.trim(), { language });
68
+ replacements.push({
69
+ original: fullMatch,
70
+ formatted: `\`\`\`${lang}\n${formatted}\`\`\``,
71
+ });
72
+ } catch {
73
+ // Keep original if formatting fails
74
+ }
76
75
  }
76
+ }
77
77
 
78
- // Apply replacements
79
- for (const { original, formatted } of replacements) {
80
- result = result.replace(original, formatted);
81
- }
78
+ // Apply replacements
79
+ for (const { original, formatted } of replacements) {
80
+ result = result.replace(original, formatted);
81
+ }
82
82
 
83
- return result;
83
+ return result;
84
84
  }
85
85
 
86
86
  /**
87
87
  * Detect language from code content or file path
88
88
  */
89
89
  function detectLanguage(code: string, filePath?: string): SupportedLanguage {
90
- if (filePath) {
91
- const ext = filePath.split('.').pop()?.toLowerCase();
92
- switch (ext) {
93
- case 'ts':
94
- case 'tsx':
95
- return 'typescript';
96
- case 'js':
97
- case 'jsx':
98
- return 'javascript';
99
- case 'css':
100
- case 'scss':
101
- case 'less':
102
- return 'css';
103
- case 'html':
104
- return 'html';
105
- case 'json':
106
- return 'json';
107
- case 'md':
108
- return 'markdown';
109
- }
110
- }
111
-
112
- // Detect from content
113
- if (code.includes('import React') || code.includes('from "react"') || code.includes("from 'react'")) {
114
- return code.includes(': React.') || code.includes('<') ? 'typescript' : 'javascript';
115
- }
116
-
117
- if (code.includes('interface ') || code.includes(': string') || code.includes(': number')) {
90
+ if (filePath) {
91
+ const ext = filePath.split('.').pop()?.toLowerCase();
92
+ switch (ext) {
93
+ case 'ts':
94
+ case 'tsx':
118
95
  return 'typescript';
119
- }
120
-
121
- if (code.includes('function ') || code.includes('const ') || code.includes('let ')) {
96
+ case 'js':
97
+ case 'jsx':
122
98
  return 'javascript';
123
- }
124
-
125
- if (code.includes('{') && (code.includes('color:') || code.includes('margin:') || code.includes('display:'))) {
99
+ case 'css':
100
+ case 'scss':
101
+ case 'less':
126
102
  return 'css';
103
+ case 'html':
104
+ return 'html';
105
+ case 'json':
106
+ return 'json';
107
+ case 'md':
108
+ return 'markdown';
127
109
  }
110
+ }
111
+
112
+ // Detect from content
113
+ if (
114
+ code.includes('import React') ||
115
+ code.includes('from "react"') ||
116
+ code.includes("from 'react'")
117
+ ) {
118
+ return code.includes(': React.') || code.includes('<') ? 'typescript' : 'javascript';
119
+ }
120
+
121
+ if (code.includes('interface ') || code.includes(': string') || code.includes(': number')) {
122
+ return 'typescript';
123
+ }
128
124
 
129
- if (code.startsWith('{') || code.startsWith('[')) {
130
- try {
131
- JSON.parse(code);
132
- return 'json';
133
- } catch {
134
- // Not JSON
135
- }
136
- }
125
+ if (code.includes('function ') || code.includes('const ') || code.includes('let ')) {
126
+ return 'javascript';
127
+ }
137
128
 
138
- if (code.includes('<html') || code.includes('<!DOCTYPE')) {
139
- return 'html';
129
+ if (
130
+ code.includes('{') &&
131
+ (code.includes('color:') || code.includes('margin:') || code.includes('display:'))
132
+ ) {
133
+ return 'css';
134
+ }
135
+
136
+ if (code.startsWith('{') || code.startsWith('[')) {
137
+ try {
138
+ JSON.parse(code);
139
+ return 'json';
140
+ } catch {
141
+ // Not JSON
140
142
  }
143
+ }
141
144
 
142
- // Default to TypeScript for better JSX support
143
- return 'typescript';
145
+ if (code.includes('<html') || code.includes('<!DOCTYPE')) {
146
+ return 'html';
147
+ }
148
+
149
+ // Default to TypeScript for better JSX support
150
+ return 'typescript';
144
151
  }
145
152
 
146
153
  /**
147
154
  * Get Prettier parser for language
148
155
  */
149
156
  function getParser(language: SupportedLanguage): string {
150
- const parsers: Record<SupportedLanguage, string> = {
151
- typescript: 'typescript',
152
- javascript: 'babel',
153
- css: 'css',
154
- html: 'html',
155
- json: 'json',
156
- markdown: 'markdown',
157
- };
158
-
159
- return parsers[language];
157
+ const parsers: Record<SupportedLanguage, string> = {
158
+ typescript: 'typescript',
159
+ javascript: 'babel',
160
+ css: 'css',
161
+ html: 'html',
162
+ json: 'json',
163
+ markdown: 'markdown',
164
+ };
165
+
166
+ return parsers[language];
160
167
  }
161
168
 
162
169
  /**
163
170
  * Map common language identifiers to supported types
164
171
  */
165
172
  function mapLanguageIdentifier(identifier?: string): SupportedLanguage | null {
166
- if (!identifier) return null;
167
-
168
- const lower = identifier.toLowerCase();
169
- const mapping: Record<string, SupportedLanguage> = {
170
- ts: 'typescript',
171
- tsx: 'typescript',
172
- typescript: 'typescript',
173
- js: 'javascript',
174
- jsx: 'javascript',
175
- javascript: 'javascript',
176
- css: 'css',
177
- scss: 'css',
178
- less: 'css',
179
- html: 'html',
180
- json: 'json',
181
- md: 'markdown',
182
- markdown: 'markdown',
183
- };
184
-
185
- return mapping[lower] || null;
173
+ if (!identifier) return null;
174
+
175
+ const lower = identifier.toLowerCase();
176
+ const mapping: Record<string, SupportedLanguage> = {
177
+ ts: 'typescript',
178
+ tsx: 'typescript',
179
+ typescript: 'typescript',
180
+ js: 'javascript',
181
+ jsx: 'javascript',
182
+ javascript: 'javascript',
183
+ css: 'css',
184
+ scss: 'css',
185
+ less: 'css',
186
+ html: 'html',
187
+ json: 'json',
188
+ md: 'markdown',
189
+ markdown: 'markdown',
190
+ };
191
+
192
+ return mapping[lower] || null;
186
193
  }
package/src/server.ts CHANGED
@@ -8,21 +8,22 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
8
8
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
9
9
  import { Config } from './config/index.js';
10
10
  import { registerTools } from './tools/index.js';
11
+ import { VERSION } from './version.js';
11
12
 
12
13
  export async function createServer(config: Config) {
13
- const server = new McpServer({
14
- name: 'gemini-designer-mcp',
15
- version: '0.1.0',
16
- });
14
+ const server = new McpServer({
15
+ name: 'gemini-designer-mcp',
16
+ version: VERSION,
17
+ });
17
18
 
18
- // Register all MCP tools
19
- registerTools(server, config);
19
+ // Register all MCP tools
20
+ registerTools(server, config);
20
21
 
21
- // Use stdio transport (standard for MCP)
22
- const transport = new StdioServerTransport();
23
- await server.connect(transport);
22
+ // Use stdio transport (standard for MCP)
23
+ const transport = new StdioServerTransport();
24
+ await server.connect(transport);
24
25
 
25
- console.error('[gemini-designer-mcp] Server connected via stdio');
26
+ console.error('[gemini-designer-mcp] Server connected via stdio');
26
27
 
27
- return server;
28
+ return server;
28
29
  }