mcp-server-gemini 1.1.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.
Files changed (48) hide show
  1. package/CHANGELOG.md +155 -0
  2. package/LICENSE +21 -0
  3. package/README.md +180 -0
  4. package/dist/config/constants.js +71 -0
  5. package/dist/config/constants.js.map +1 -0
  6. package/dist/config/models.js +121 -0
  7. package/dist/config/models.js.map +1 -0
  8. package/dist/enhanced-stdio-server.js +1164 -0
  9. package/dist/enhanced-stdio-server.js.map +1 -0
  10. package/dist/i18n.js +109 -0
  11. package/dist/i18n.js.map +1 -0
  12. package/dist/server.js +251 -0
  13. package/dist/server.js.map +1 -0
  14. package/dist/tools/analyze-codebase.js +373 -0
  15. package/dist/tools/analyze-codebase.js.map +1 -0
  16. package/dist/tools/analyze-content.js +295 -0
  17. package/dist/tools/analyze-content.js.map +1 -0
  18. package/dist/tools/brainstorm.js +237 -0
  19. package/dist/tools/brainstorm.js.map +1 -0
  20. package/dist/tools/definitions.js +375 -0
  21. package/dist/tools/definitions.js.map +1 -0
  22. package/dist/tools/fix-ui.js +262 -0
  23. package/dist/tools/fix-ui.js.map +1 -0
  24. package/dist/tools/generate-ui.js +311 -0
  25. package/dist/tools/generate-ui.js.map +1 -0
  26. package/dist/tools/index.js +17 -0
  27. package/dist/tools/index.js.map +1 -0
  28. package/dist/tools/list-models.js +30 -0
  29. package/dist/tools/list-models.js.map +1 -0
  30. package/dist/tools/multimodal-query.js +83 -0
  31. package/dist/tools/multimodal-query.js.map +1 -0
  32. package/dist/tools/search.js +94 -0
  33. package/dist/tools/search.js.map +1 -0
  34. package/dist/types.js +2 -0
  35. package/dist/types.js.map +1 -0
  36. package/dist/utils/error-handler.js +69 -0
  37. package/dist/utils/error-handler.js.map +1 -0
  38. package/dist/utils/file-reader.js +470 -0
  39. package/dist/utils/file-reader.js.map +1 -0
  40. package/dist/utils/gemini-client.js +184 -0
  41. package/dist/utils/gemini-client.js.map +1 -0
  42. package/dist/utils/security.js +370 -0
  43. package/dist/utils/security.js.map +1 -0
  44. package/dist/utils/validators.js +150 -0
  45. package/dist/utils/validators.js.map +1 -0
  46. package/dist/windows-utils.js +175 -0
  47. package/dist/windows-utils.js.map +1 -0
  48. package/package.json +69 -0
@@ -0,0 +1,370 @@
1
+ /**
2
+ * Security validation module
3
+ * Provides file path security validation to prevent path traversal attacks and sensitive file access
4
+ */
5
+ import * as path from 'path';
6
+ import * as fs from 'fs/promises';
7
+ import micromatch from 'micromatch';
8
+ // ============== Constant Definitions ==============
9
+ /**
10
+ * Default sensitive file patterns
11
+ * These files may contain sensitive information and are not allowed access by default
12
+ */
13
+ export const DEFAULT_SENSITIVE_PATTERNS = [
14
+ // Environment variable files
15
+ '.env',
16
+ '.env.*',
17
+ '.env.local',
18
+ '.env.development',
19
+ '.env.production',
20
+ '**/.env',
21
+ '**/.env.*',
22
+ // SSH and key files
23
+ '.ssh/**',
24
+ '**/.ssh/**',
25
+ '*.pem',
26
+ '*.key',
27
+ '*.pfx',
28
+ '*.p12',
29
+ '**/id_rsa',
30
+ '**/id_rsa.*',
31
+ '**/id_ed25519',
32
+ '**/id_ed25519.*',
33
+ '**/id_dsa',
34
+ '**/id_dsa.*',
35
+ // Credential and secret files
36
+ '**/credentials*',
37
+ '**/secrets*',
38
+ '**/secret.*',
39
+ '**/*password*',
40
+ '**/*token*',
41
+ // Git sensitive configuration
42
+ '**/.git/config',
43
+ '**/.gitconfig',
44
+ // Database files
45
+ '*.sqlite',
46
+ '*.sqlite3',
47
+ '*.db',
48
+ // History files
49
+ '**/.bash_history',
50
+ '**/.zsh_history',
51
+ '**/.node_repl_history',
52
+ // AWS and cloud service configurations
53
+ '**/.aws/**',
54
+ '**/.azure/**',
55
+ '**/.gcloud/**',
56
+ // Docker secrets
57
+ '**/docker-compose*.yml',
58
+ '**/docker-compose*.yaml',
59
+ ];
60
+ /**
61
+ * Default security configuration
62
+ */
63
+ export const DEFAULT_SECURITY_CONFIG = {
64
+ allowedDirectories: [], // Empty array means no restriction
65
+ sensitivePatterns: DEFAULT_SENSITIVE_PATTERNS,
66
+ maxFileSize: 1024 * 1024, // 1MB
67
+ maxFiles: 500,
68
+ allowSymlinks: false,
69
+ };
70
+ // ============== Error Class Definitions ==============
71
+ /**
72
+ * Security error class
73
+ * Thrown when security validation fails
74
+ */
75
+ export class SecurityError extends Error {
76
+ code;
77
+ path;
78
+ /**
79
+ * Create a security error instance
80
+ * @param message Error message
81
+ * @param code Error code
82
+ * @param path Related file path (optional)
83
+ */
84
+ constructor(message, code, path) {
85
+ super(message);
86
+ this.code = code;
87
+ this.path = path;
88
+ this.name = 'SecurityError';
89
+ // Ensure correct prototype chain (TypeScript compilation compatibility)
90
+ Object.setPrototypeOf(this, SecurityError.prototype);
91
+ }
92
+ }
93
+ // ============== Utility Functions ==============
94
+ /**
95
+ * Normalize path
96
+ * Convert path to unified format, handling Windows and Unix path differences
97
+ *
98
+ * @param inputPath Input path
99
+ * @returns Normalized absolute path
100
+ *
101
+ * @example
102
+ * normalizePath('./src/index.ts') // Returns absolute path
103
+ * normalizePath('C:\\Users\\test') // Returns C:/Users/test
104
+ */
105
+ export function normalizePath(inputPath) {
106
+ // Resolve to absolute path
107
+ const absolutePath = path.resolve(inputPath);
108
+ // Unify to use forward slashes (for cross-platform handling)
109
+ return absolutePath.replace(/\\/g, '/');
110
+ }
111
+ /**
112
+ * Detect if path contains path traversal attack
113
+ *
114
+ * Use path.relative method to safely detect path traversal,
115
+ * avoiding false positives from simple includes('..') checks on legitimate filenames (e.g., vendor..lib.js)
116
+ *
117
+ * @param inputPath Path to detect
118
+ * @param basePath Base path (defaults to current working directory)
119
+ * @returns Returns true if path traversal is detected
120
+ *
121
+ * @example
122
+ * hasPathTraversal('../etc/passwd') // true
123
+ * hasPathTraversal('./src/index.ts') // false
124
+ * hasPathTraversal('./vendor..lib.js') // false (legitimate filename)
125
+ */
126
+ export function hasPathTraversal(inputPath, basePath) {
127
+ // Get base path (defaults to current working directory)
128
+ const base = basePath ? path.resolve(basePath) : process.cwd();
129
+ // Resolve input path to absolute path
130
+ const resolvedPath = path.resolve(base, inputPath);
131
+ // Use path.relative to calculate relative path
132
+ // If result starts with '..', the path is trying to escape the base directory
133
+ const relativePath = path.relative(base, resolvedPath);
134
+ // Check if relative path starts with '..' (indicates path traversal)
135
+ // or is an absolute path (on Windows may start with 'C:')
136
+ if (relativePath.startsWith('..') || path.isAbsolute(relativePath)) {
137
+ return true;
138
+ }
139
+ // Additional check: path segments should not have '..' as a standalone directory name
140
+ // This is to prevent some edge cases
141
+ const segments = inputPath.split(/[/\\]/);
142
+ for (const segment of segments) {
143
+ // Only check segments that exactly equal '..', not filenames containing '..'
144
+ if (segment === '..') {
145
+ return true;
146
+ }
147
+ }
148
+ return false;
149
+ }
150
+ /**
151
+ * Check if file is a sensitive file
152
+ *
153
+ * @param filePath File path
154
+ * @param patterns List of sensitive file patterns (glob patterns)
155
+ * @returns Returns true if it is a sensitive file
156
+ *
157
+ * @example
158
+ * isSensitiveFile('.env') // true
159
+ * isSensitiveFile('./src/index.ts') // false
160
+ * isSensitiveFile('./config/credentials.json') // true
161
+ */
162
+ export function isSensitiveFile(filePath, patterns = DEFAULT_SENSITIVE_PATTERNS) {
163
+ // Get filename and path
164
+ const normalizedPath = filePath.replace(/\\/g, '/');
165
+ const fileName = path.basename(normalizedPath);
166
+ // Use micromatch for glob pattern matching
167
+ const isMatch = micromatch.isMatch(normalizedPath, patterns, {
168
+ dot: true, // Match files starting with .
169
+ nocase: true, // Ignore case
170
+ basename: false // Use full path matching
171
+ });
172
+ // Additional filename check
173
+ const fileNameMatch = micromatch.isMatch(fileName, patterns, {
174
+ dot: true,
175
+ nocase: true
176
+ });
177
+ return isMatch || fileNameMatch;
178
+ }
179
+ /**
180
+ * Check if path is within allowed directory
181
+ *
182
+ * Use path.relative method to safely check if path is within allowed directory,
183
+ * avoiding simple prefix matching bypasses (e.g., /var/www-secret matching /var/www)
184
+ *
185
+ * @param filePath File path to check
186
+ * @param allowedDirs List of allowed directories
187
+ * @returns Returns true if within allowed directory
188
+ *
189
+ * @example
190
+ * isWithinAllowedDirectory('./src/index.ts', ['./src', './lib']) // true
191
+ * isWithinAllowedDirectory('./etc/passwd', ['./src']) // false
192
+ * isWithinAllowedDirectory('/var/www-secret', ['/var/www']) // false (fixed: cannot be bypassed)
193
+ */
194
+ export function isWithinAllowedDirectory(filePath, allowedDirs) {
195
+ // If whitelist is empty, allow all paths
196
+ if (!allowedDirs || allowedDirs.length === 0) {
197
+ return true;
198
+ }
199
+ // Resolve to absolute path
200
+ const absoluteFilePath = path.resolve(filePath);
201
+ for (const dir of allowedDirs) {
202
+ const absoluteDir = path.resolve(dir);
203
+ // Use path.relative to calculate relative path
204
+ const relativePath = path.relative(absoluteDir, absoluteFilePath);
205
+ // If relative path doesn't start with '..' and is not an absolute path,
206
+ // the file is within the allowed directory or is the directory itself
207
+ if (!relativePath.startsWith('..') && !path.isAbsolute(relativePath)) {
208
+ // Additional check: empty string means paths are identical
209
+ // Non-empty string means it's a subpath
210
+ return true;
211
+ }
212
+ }
213
+ return false;
214
+ }
215
+ /**
216
+ * Check if it is a symbolic link
217
+ *
218
+ * @param filePath File path
219
+ * @returns Returns true if it is a symbolic link
220
+ */
221
+ export async function isSymlink(filePath) {
222
+ try {
223
+ const stats = await fs.lstat(filePath);
224
+ return stats.isSymbolicLink();
225
+ }
226
+ catch {
227
+ // File does not exist or cannot be accessed, return false
228
+ return false;
229
+ }
230
+ }
231
+ /**
232
+ * Get file size
233
+ *
234
+ * @param filePath File path
235
+ * @returns File size (bytes)
236
+ */
237
+ export async function getFileSize(filePath) {
238
+ const stats = await fs.stat(filePath);
239
+ return stats.size;
240
+ }
241
+ // ============== Main Validation Functions ==============
242
+ /**
243
+ * Validate the security of a single path
244
+ * Performs complete security checks including path traversal, sensitive files, whitelist, and symbolic link detection
245
+ *
246
+ * @param inputPath Path to validate
247
+ * @param config Security configuration (optional)
248
+ * @throws SecurityError Thrown when security validation fails
249
+ *
250
+ * @example
251
+ * // Normal usage
252
+ * await validatePath('./src/index.ts');
253
+ *
254
+ * // With whitelist
255
+ * await validatePath('./src/index.ts', { allowedDirectories: ['./src'] });
256
+ *
257
+ * // Path traversal attack will throw error
258
+ * await validatePath('../../../etc/passwd'); // Throws SecurityError
259
+ */
260
+ export async function validatePath(inputPath, config) {
261
+ const mergedConfig = { ...DEFAULT_SECURITY_CONFIG, ...config };
262
+ // 1. Check for path traversal attack
263
+ if (hasPathTraversal(inputPath)) {
264
+ throw new SecurityError(`Path traversal attack blocked: "${inputPath}" contains disallowed path traversal pattern`, 'PATH_TRAVERSAL', inputPath);
265
+ }
266
+ // 2. Check if it is a sensitive file
267
+ if (isSensitiveFile(inputPath, mergedConfig.sensitivePatterns)) {
268
+ throw new SecurityError(`Access to sensitive file denied: "${inputPath}" matches sensitive file pattern`, 'SENSITIVE_FILE', inputPath);
269
+ }
270
+ // 3. Check if within whitelist directory
271
+ if (!isWithinAllowedDirectory(inputPath, mergedConfig.allowedDirectories || [])) {
272
+ throw new SecurityError(`Access denied: "${inputPath}" is not in the allowed directory list`, 'ACCESS_DENIED', inputPath);
273
+ }
274
+ // 4. Check for symbolic link (if file exists)
275
+ if (!mergedConfig.allowSymlinks) {
276
+ try {
277
+ if (await isSymlink(inputPath)) {
278
+ throw new SecurityError(`Symlink access denied: "${inputPath}" is a symbolic link`, 'SYMLINK_DETECTED', inputPath);
279
+ }
280
+ }
281
+ catch (error) {
282
+ // If it's a SecurityError, continue throwing
283
+ if (error instanceof SecurityError) {
284
+ throw error;
285
+ }
286
+ // Ignore symlink check when file doesn't exist (let subsequent file reading handle it)
287
+ }
288
+ }
289
+ }
290
+ /**
291
+ * Batch validate the security of multiple paths
292
+ *
293
+ * @param paths Array of paths to validate
294
+ * @param config Security configuration (optional)
295
+ * @throws SecurityError Thrown when any path validation fails
296
+ *
297
+ * @example
298
+ * await validatePaths(['./src/a.ts', './src/b.ts']);
299
+ */
300
+ export async function validatePaths(paths, config) {
301
+ for (const filePath of paths) {
302
+ await validatePath(filePath, config);
303
+ }
304
+ }
305
+ /**
306
+ * Validate if file size is within limits
307
+ *
308
+ * @param filePath File path
309
+ * @param maxSize Maximum file size (bytes)
310
+ * @throws SecurityError Thrown when file size exceeds limit
311
+ */
312
+ export async function validateFileSize(filePath, maxSize = DEFAULT_SECURITY_CONFIG.maxFileSize) {
313
+ try {
314
+ const size = await getFileSize(filePath);
315
+ if (size > maxSize) {
316
+ throw new SecurityError(`File size exceeded: "${filePath}" size is ${formatBytes(size)}, exceeds limit of ${formatBytes(maxSize)}`, 'SIZE_EXCEEDED', filePath);
317
+ }
318
+ }
319
+ catch (error) {
320
+ if (error instanceof SecurityError) {
321
+ throw error;
322
+ }
323
+ // Ignore size check when file doesn't exist (let subsequent file reading handle it)
324
+ }
325
+ }
326
+ /**
327
+ * Validate if file count is within limits
328
+ *
329
+ * @param count File count
330
+ * @param maxFiles Maximum file count
331
+ * @throws SecurityError Thrown when file count exceeds limit
332
+ */
333
+ export function validateFileCount(count, maxFiles = DEFAULT_SECURITY_CONFIG.maxFiles) {
334
+ if (count > maxFiles) {
335
+ throw new SecurityError(`File count exceeded: Found ${count} files, exceeds limit of ${maxFiles}`, 'FILE_LIMIT_EXCEEDED');
336
+ }
337
+ }
338
+ // ============== Helper Functions ==============
339
+ /**
340
+ * Format bytes to human-readable format
341
+ *
342
+ * @param bytes Byte count
343
+ * @returns Formatted string
344
+ */
345
+ function formatBytes(bytes) {
346
+ if (bytes === 0)
347
+ return '0 Bytes';
348
+ const k = 1024;
349
+ const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
350
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
351
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
352
+ }
353
+ /**
354
+ * Merge security configurations
355
+ *
356
+ * @param userConfig User-provided configuration
357
+ * @returns Merged complete configuration
358
+ */
359
+ export function mergeSecurityConfig(userConfig) {
360
+ return {
361
+ ...DEFAULT_SECURITY_CONFIG,
362
+ ...userConfig,
363
+ // Merge sensitive file patterns (rather than overwrite)
364
+ sensitivePatterns: [
365
+ ...DEFAULT_SENSITIVE_PATTERNS,
366
+ ...(userConfig?.sensitivePatterns || [])
367
+ ]
368
+ };
369
+ }
370
+ //# sourceMappingURL=security.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security.js","sourceRoot":"","sources":["../../src/utils/security.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Parameter validation utilities
3
+ */
4
+ import { FRAMEWORKS,
5
+ // ANIMATION_TECHNOLOGIES removed - animation tool has been removed
6
+ UI_STYLES, OUTPUT_FORMATS, CONTENT_TYPES, ANALYSIS_TASKS, CODEBASE_FOCUS, BRAINSTORM_STYLES } from '../config/constants.js';
7
+ import { isModelSupported } from '../config/models.js';
8
+ /**
9
+ * Validate required parameter
10
+ */
11
+ export function validateRequired(value, fieldName) {
12
+ if (value === undefined || value === null || value === '') {
13
+ throw new Error(`${fieldName} is required`);
14
+ }
15
+ }
16
+ /**
17
+ * Validate string
18
+ */
19
+ export function validateString(value, fieldName, minLength = 1) {
20
+ if (typeof value !== 'string') {
21
+ throw new Error(`${fieldName} must be a string`);
22
+ }
23
+ if (value.length < minLength) {
24
+ throw new Error(`${fieldName} must be at least ${minLength} characters long`);
25
+ }
26
+ }
27
+ /**
28
+ * Validate number
29
+ */
30
+ export function validateNumber(value, fieldName, min, max) {
31
+ if (typeof value !== 'number' || isNaN(value)) {
32
+ throw new Error(`${fieldName} must be a number`);
33
+ }
34
+ if (min !== undefined && value < min) {
35
+ throw new Error(`${fieldName} must be at least ${min}`);
36
+ }
37
+ if (max !== undefined && value > max) {
38
+ throw new Error(`${fieldName} must be at most ${max}`);
39
+ }
40
+ }
41
+ /**
42
+ * Validate boolean
43
+ */
44
+ export function validateBoolean(value, fieldName) {
45
+ if (typeof value !== 'boolean') {
46
+ throw new Error(`${fieldName} must be a boolean`);
47
+ }
48
+ }
49
+ /**
50
+ * Validate enum value
51
+ */
52
+ export function validateEnum(value, fieldName, allowedValues) {
53
+ if (!allowedValues.includes(value)) {
54
+ throw new Error(`${fieldName} must be one of: ${allowedValues.join(', ')}. Got: ${value}`);
55
+ }
56
+ }
57
+ /**
58
+ * Validate array
59
+ */
60
+ export function validateArray(value, fieldName, minLength = 1) {
61
+ if (!Array.isArray(value)) {
62
+ throw new Error(`${fieldName} must be an array`);
63
+ }
64
+ if (value.length < minLength) {
65
+ throw new Error(`${fieldName} must have at least ${minLength} item(s)`);
66
+ }
67
+ }
68
+ /**
69
+ * Validate Base64 image
70
+ */
71
+ export function validateBase64Image(value, fieldName) {
72
+ if (!value.startsWith('data:image/')) {
73
+ throw new Error(`${fieldName} must be a Base64 encoded image (data:image/...)`);
74
+ }
75
+ }
76
+ /**
77
+ * Validate URL
78
+ */
79
+ export function validateURL(value, fieldName) {
80
+ try {
81
+ new URL(value);
82
+ }
83
+ catch {
84
+ throw new Error(`${fieldName} must be a valid URL`);
85
+ }
86
+ }
87
+ /**
88
+ * Validate framework
89
+ */
90
+ export function validateFramework(value) {
91
+ validateEnum(value, 'framework', FRAMEWORKS);
92
+ }
93
+ // validateAnimationTechnology removed - animation tool has been removed
94
+ /**
95
+ * Validate UI style
96
+ */
97
+ export function validateUIStyle(value) {
98
+ validateEnum(value, 'style', UI_STYLES);
99
+ }
100
+ /**
101
+ * Validate output format
102
+ */
103
+ export function validateOutputFormat(value) {
104
+ validateEnum(value, 'outputFormat', OUTPUT_FORMATS);
105
+ }
106
+ /**
107
+ * Validate content type
108
+ */
109
+ export function validateContentType(value) {
110
+ validateEnum(value, 'type', CONTENT_TYPES);
111
+ }
112
+ /**
113
+ * Validate analysis task
114
+ */
115
+ export function validateAnalysisTask(value) {
116
+ validateEnum(value, 'task', ANALYSIS_TASKS);
117
+ }
118
+ /**
119
+ * Validate codebase focus
120
+ */
121
+ export function validateCodebaseFocus(value) {
122
+ validateEnum(value, 'focus', CODEBASE_FOCUS);
123
+ }
124
+ /**
125
+ * Validate brainstorm style
126
+ */
127
+ export function validateBrainstormStyle(value) {
128
+ validateEnum(value, 'style', BRAINSTORM_STYLES);
129
+ }
130
+ /**
131
+ * Validate model ID
132
+ */
133
+ export function validateModel(modelId) {
134
+ if (!isModelSupported(modelId)) {
135
+ throw new Error(`Model "${modelId}" is not supported. Use one of: gemini-3-pro-preview, gemini-2.5-pro, gemini-2.5-flash, gemini-2.5-flash-lite`);
136
+ }
137
+ }
138
+ /**
139
+ * Validate temperature parameter
140
+ */
141
+ export function validateTemperature(temperature) {
142
+ validateNumber(temperature, 'temperature', 0, 2);
143
+ }
144
+ /**
145
+ * Validate maxTokens parameter
146
+ */
147
+ export function validateMaxTokens(maxTokens) {
148
+ validateNumber(maxTokens, 'maxTokens', 1, 65536);
149
+ }
150
+ //# sourceMappingURL=validators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validators.js","sourceRoot":"","sources":["../../src/utils/validators.ts"],"names":[],"mappings":"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"}