├── .env.example ├── dist ├── types.js ├── types.js.map ├── tools │ ├── index.js.map │ ├── index.js │ ├── list-models.js.map │ ├── list-models.js │ ├── multimodal-query.js.map │ ├── create-animation.js.map │ ├── multimodal-query.js │ ├── fix-ui.js.map │ ├── brainstorm.js.map │ ├── create-animation.js │ ├── definitions.js.map │ ├── analyze-content.js.map │ ├── generate-ui.js.map │ ├── fix-ui.js │ └── analyze-codebase.js.map ├── config │ ├── constants.js.map │ ├── constants.js │ ├── models.js.map │ └── models.js ├── utils │ ├── error-handler.js.map │ ├── error-handler.js │ ├── validators.js.map │ ├── gemini-client.js.map │ ├── validators.js │ ├── security.js.map │ └── gemini-client.js ├── i18n.js.map ├── windows-utils.js.map ├── i18n.js ├── windows-utils.js ├── server.js.map └── server.js ├── .gitignore ├── tsconfig.json ├── .npmignore ├── jest.config.js ├── jest.config.ts ├── CLAUDE.md ├── src ├── tools │ ├── index.ts │ ├── list-models.ts │ ├── multimodal-query.ts │ ├── create-animation.ts │ └── fix-ui.ts ├── config │ ├── constants.ts │ └── models.ts ├── utils │ ├── error-handler.ts │ ├── validators.ts │ └── gemini-client.ts ├── types.ts └── server.ts ├── smithery.yaml ├── Dockerfile ├── LICENSE ├── tests ├── server.test.ts └── handlers.test.ts ├── package.json ├── CONTRIBUTING.md ├── CHANGELOG.md └── README.md /.env.example: -------------------------------------------------------------------------------- 1 | GEMINI_API_KEY=your_gemini_api_key_here -------------------------------------------------------------------------------- /dist/types.js: -------------------------------------------------------------------------------- 1 | export {}; 2 | //# sourceMappingURL=types.js.map -------------------------------------------------------------------------------- /dist/types.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | node_modules/ 3 | 4 | # Environment variables 5 | .env 6 | 7 | # Logs 8 | *.log 9 | npm-debug.log* 10 | 11 | # IDE files 12 | .vscode/ 13 | .idea/ 14 | *.swp 15 | *.swo 16 | 17 | # OS files 18 | .DS_Store 19 | Thumbs.db 20 | 21 | # Claude configuration 22 | .claude/ 23 | MCP-PRD.md 24 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2022", 4 | "module": "NodeNext", 5 | "moduleResolution": "NodeNext", 6 | "outDir": "./dist", 7 | "rootDir": "./src", 8 | "strict": true, 9 | "esModuleInterop": true, 10 | "skipLibCheck": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "sourceMap": true 13 | }, 14 | "include": ["src/**/*"], 15 | "exclude": ["node_modules"] 16 | } -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # Source files 2 | src/ 3 | *.ts 4 | !dist/**/*.d.ts 5 | 6 | # Development files 7 | .gitignore 8 | .eslintrc* 9 | .prettierrc* 10 | tsconfig.json 11 | jest.config.* 12 | 13 | # Documentation (keep essential ones) 14 | docs/ 15 | *.md 16 | !README.md 17 | !LICENSE 18 | !CHANGELOG.md 19 | 20 | # Test files 21 | __tests__/ 22 | *.test.* 23 | *.spec.* 24 | 25 | # CI/CD 26 | .github/ 27 | 28 | # IDE 29 | .vscode/ 30 | .idea/ 31 | 32 | # Misc 33 | .env 34 | .env.* 35 | *.log 36 | .DS_Store -------------------------------------------------------------------------------- /dist/tools/index.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,UAAU;AACV,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD,SAAS;AACT,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC"} -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | testEnvironment: 'node', 4 | roots: ['/src'], 5 | testMatch: ['**/__tests__/**/*.ts', '**/?(*.)+(spec|test).ts'], 6 | transform: { 7 | '^.+\\.ts$': 'ts-jest' 8 | }, 9 | moduleFileExtensions: ['ts', 'js', 'json', 'node'], 10 | collectCoverage: true, 11 | coverageDirectory: 'coverage', 12 | coverageReporters: ['text', 'lcov'], 13 | coveragePathIgnorePatterns: ['/node_modules/', '/__tests__/'], 14 | setupFilesAfterEnv: ['/src/__tests__/setup.ts'] 15 | }; -------------------------------------------------------------------------------- /jest.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from '@jest/types'; 2 | 3 | const config: Config.InitialOptions = { 4 | preset: 'ts-jest', 5 | testEnvironment: 'node', 6 | roots: ['/src'], 7 | testMatch: ['**/__tests__/**/*.ts', '**/?(*.)+(spec|test).ts'], 8 | transform: { 9 | '^.+\\.ts$': 'ts-jest' 10 | }, 11 | moduleFileExtensions: ['ts', 'js', 'json', 'node'], 12 | collectCoverage: true, 13 | coverageDirectory: 'coverage', 14 | coverageReporters: ['text', 'lcov'], 15 | coveragePathIgnorePatterns: ['/node_modules/', '/__tests__/'], 16 | setupFilesAfterEnv: ['/src/__tests__/setup.ts'] 17 | }; -------------------------------------------------------------------------------- /CLAUDE.md: -------------------------------------------------------------------------------- 1 | ## Development Environment 2 | - OS: Windows 10.0.19045 3 | - Shell: Git Bash 4 | - Path format: Windows (use forward slashes in Git Bash) 5 | - File system: Case-insensitive 6 | - Line endings: CRLF (configure Git autocrlf) 7 | 8 | ## Playwright MCP Guide 9 | 10 | File paths: 11 | - Screenshots: `./CCimages/screenshots/` 12 | - PDFs: `./CCimages/pdfs/` 13 | 14 | Browser version fix: 15 | - Error: "Executable doesn't exist at chromium-1179" → Version mismatch 16 | - Quick fix: `cd ~/AppData/Local/ms-playwright && cmd //c "mklink /J chromium-1179 chromium-1181"` 17 | - Or install: `npx playwright@1.40.0 install chromium` 18 | -------------------------------------------------------------------------------- /src/tools/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 工具导出 3 | * 所有 MCP 工具的统一入口 4 | */ 5 | 6 | // 导出工具处理器 7 | export { handleGenerateUI } from './generate-ui.js'; 8 | export { handleMultimodalQuery } from './multimodal-query.js'; 9 | export { handleFixUI } from './fix-ui.js'; 10 | export { handleCreateAnimation } from './create-animation.js'; 11 | export { handleAnalyzeContent } from './analyze-content.js'; 12 | export { handleAnalyzeCodebase } from './analyze-codebase.js'; 13 | export { handleBrainstorm } from './brainstorm.js'; 14 | export { handleListModels } from './list-models.js'; 15 | 16 | // 导出工具定义 17 | export { TOOL_DEFINITIONS } from './definitions.js'; 18 | -------------------------------------------------------------------------------- /dist/tools/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 工具导出 3 | * 所有 MCP 工具的统一入口 4 | */ 5 | // 导出工具处理器 6 | export { handleGenerateUI } from './generate-ui.js'; 7 | export { handleMultimodalQuery } from './multimodal-query.js'; 8 | export { handleFixUI } from './fix-ui.js'; 9 | export { handleCreateAnimation } from './create-animation.js'; 10 | export { handleAnalyzeContent } from './analyze-content.js'; 11 | export { handleAnalyzeCodebase } from './analyze-codebase.js'; 12 | export { handleBrainstorm } from './brainstorm.js'; 13 | export { handleListModels } from './list-models.js'; 14 | // 导出工具定义 15 | export { TOOL_DEFINITIONS } from './definitions.js'; 16 | //# sourceMappingURL=index.js.map -------------------------------------------------------------------------------- /smithery.yaml: -------------------------------------------------------------------------------- 1 | # Smithery configuration file: https://smithery.ai/docs/config#smitheryyaml 2 | 3 | startCommand: 4 | type: stdio 5 | configSchema: 6 | # JSON Schema defining the configuration options for the MCP. 7 | type: object 8 | required: 9 | - geminiApiKey 10 | properties: 11 | geminiApiKey: 12 | type: string 13 | description: The API key for the Gemini AI server. 14 | port: 15 | type: number 16 | default: 3005 17 | description: The port on which the server will run. 18 | commandFunction: 19 | # A function that produces the CLI command to start the MCP on stdio. 20 | |- 21 | config => ({command: 'node', args: ['dist/index.js'], env: {GEMINI_API_KEY: config.geminiApiKey, PORT: config.port.toString()}}) -------------------------------------------------------------------------------- /dist/tools/list-models.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"list-models.js","sourceRoot":"","sources":["../../src/tools/list-models.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,YAAY,EACZ,eAAe,EACf,qBAAqB,EAGtB,MAAM,qBAAqB,CAAC;AAqC7B;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,YAAY,GAAG,eAAe,EAAE,CAAC;IAEvC,OAAO;QACL,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAC7B,EAAE,EAAE,KAAK,CAAC,EAAE;YACZ,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,YAAY,EAAE,KAAK,CAAC,YAAY;YAChC,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,QAAQ,EAAE,KAAK,CAAC,QAAQ;YACxB,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,UAAU,EAAE,KAAK,CAAC,UAAU;SAC7B,CAAC,CAAC;QACH,YAAY,EAAE,YAAY,CAAC,EAAE;QAC7B,UAAU,EAAE,MAAM,CAAC,MAAM;QACzB,eAAe,EAAE,qBAAqB;KACvC,CAAC;AACJ,CAAC"} -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Generated by https://smithery.ai. See: https://smithery.ai/docs/config#dockerfile 2 | # Use a Node.js image 3 | FROM node:18-alpine AS builder 4 | 5 | # Set the working directory 6 | WORKDIR /app 7 | 8 | # Copy package.json and package-lock.json 9 | COPY package.json package-lock.json ./ 10 | 11 | # Install dependencies 12 | RUN npm install 13 | 14 | # Copy the rest of the application code 15 | COPY . . 16 | 17 | # Build the application 18 | RUN npm run build 19 | 20 | # Use a smaller Node.js image for the release 21 | FROM node:18-slim AS release 22 | 23 | # Set the working directory 24 | WORKDIR /app 25 | 26 | # Copy the build from the builder stage 27 | COPY --from=builder /app/dist /app/dist 28 | COPY --from=builder /app/package.json /app/package-lock.json /app/ 29 | 30 | # Install production dependencies only 31 | RUN npm ci --production 32 | 33 | # Expose the necessary port 34 | EXPOSE 3005 35 | 36 | # Command to run the application 37 | CMD ["node", "dist/index.js"] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Ali Argün 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /dist/tools/list-models.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Tool 8: list_models 3 | * List all available Gemini models 4 | */ 5 | import { getAllModels, getDefaultModel, MODEL_RECOMMENDATIONS } from '../config/models.js'; 6 | /** 7 | * Handle list_models request 8 | * Returns detailed information about all available models, including structured capability information 9 | */ 10 | export async function handleListModels() { 11 | const models = getAllModels(); 12 | const defaultModel = getDefaultModel(); 13 | return { 14 | models: models.map((model) => ({ 15 | id: model.id, 16 | name: model.name, 17 | description: model.description, 18 | capabilities: model.capabilities, 19 | useCases: model.useCases, 20 | isDefault: model.isDefault, 21 | features: model.features, 22 | bestFor: model.bestFor, 23 | lastUpdate: model.lastUpdate 24 | })), 25 | defaultModel: defaultModel.id, 26 | totalCount: models.length, 27 | recommendations: MODEL_RECOMMENDATIONS 28 | }; 29 | } 30 | //# sourceMappingURL=list-models.js.map -------------------------------------------------------------------------------- /tests/server.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect, jest } from '@jest/globals'; 2 | import { MCPServer } from '../src/server'; 3 | import { WebSocket } from 'ws'; 4 | 5 | describe('MCP Server', () => { 6 | const TEST_API_KEY = 'test-key'; 7 | const TEST_PORT = 3006; 8 | 9 | it('should initialize correctly', () => { 10 | const server = new MCPServer(TEST_API_KEY, TEST_PORT); 11 | expect(server).toBeDefined(); 12 | }); 13 | 14 | it('should handle initialize request', async () => { 15 | const server = new MCPServer(TEST_API_KEY, TEST_PORT); 16 | const client = new WebSocket(`ws://localhost:${TEST_PORT}`); 17 | 18 | const response = await new Promise((resolve) => { 19 | client.on('open', () => { 20 | client.send(JSON.stringify({ 21 | jsonrpc: '2.0', 22 | id: 1, 23 | method: 'initialize' 24 | })); 25 | }); 26 | 27 | client.on('message', (data) => { 28 | resolve(JSON.parse(data.toString())); 29 | }); 30 | }); 31 | 32 | expect(response).toMatchObject({ 33 | jsonrpc: '2.0', 34 | id: 1, 35 | result: { 36 | protocolVersion: '2024-11-05', 37 | serverInfo: { 38 | name: 'gemini-mcp', 39 | version: expect.any(String) 40 | }, 41 | capabilities: expect.any(Object) 42 | } 43 | }); 44 | }); 45 | }); -------------------------------------------------------------------------------- /dist/tools/multimodal-query.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"multimodal-query.js","sourceRoot":"","sources":["../../src/tools/multimodal-query.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,oBAAoB,EACrB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AAErE,qCAAqC;AACrC,MAAM,8BAA8B,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;+BA2BR,CAAC;AAkBhC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,MAA6B,EAC7B,MAAoB;IAEpB,IAAI,CAAC;QACH,+BAA+B;QAC/B,gBAAgB,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC1C,cAAc,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;QAC3C,gBAAgB,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC1C,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC;QAE1C,+BAA+B;QAC/B,MAAM,YAAY,GAAG,MAAM,CAAC,YAAY,IAAI,MAAM,CAAC;QACnD,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;YACxB,oBAAoB,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QAC5C,CAAC;QAED,mBAAmB;QACnB,IAAI,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC;QAE/B,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,UAAU,GAAG,YAAY,MAAM,CAAC,OAAO,iBAAiB,MAAM,CAAC,MAAM,EAAE,CAAC;QAC1E,CAAC;QAED,IAAI,YAAY,KAAK,MAAM,EAAE,CAAC;YAC5B,UAAU,IAAI,wDAAwD,CAAC;QACzE,CAAC;aAAM,IAAI,YAAY,KAAK,MAAM,EAAE,CAAC;YACnC,UAAU,IAAI,iEAAiE,CAAC;QAClF,CAAC;QAED,wCAAwC;QACxC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAC9C,UAAU,EACV,MAAM,CAAC,MAAM,EACb;YACE,iBAAiB,EAAE,8BAA8B;YACjD,WAAW,EAAE,GAAG;YAChB,SAAS,EAAE,IAAI;SAChB,CACF,CAAC;QAEF,OAAO;YACL,QAAQ;YACR,MAAM,EAAE,YAAY;YACpB,QAAQ,EAAE;gBACR,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM;gBAChC,SAAS,EAAE,MAAM,CAAC,QAAQ,EAAE;aAC7B;SACF,CAAC;IAEJ,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,QAAQ,CAAC,iBAAiB,EAAE,KAAK,CAAC,CAAC;QACnC,MAAM,cAAc,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;AACH,CAAC"} -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mcp-server-gemini", 3 | "version": "1.1.0", 4 | "description": "Specialized MCP server for Gemini 3.0 Pro focused on UI generation and frontend development", 5 | "main": "dist/server.js", 6 | "bin": { 7 | "mcp-server-gemini": "./dist/server.js" 8 | }, 9 | "scripts": { 10 | "build": "tsc", 11 | "prepare": "npm run build", 12 | "start": "node dist/server.js", 13 | "dev": "ts-node src/server.ts", 14 | "test": "jest", 15 | "test:watch": "jest --watch", 16 | "lint": "eslint src/**/*.ts", 17 | "format": "prettier --write src/**/*.ts" 18 | }, 19 | "type": "module", 20 | "dependencies": { 21 | "@google/genai": "^1.8.0", 22 | "fast-glob": "^3.3.3", 23 | "micromatch": "^4.0.8", 24 | "undici": "^7.16.0" 25 | }, 26 | "devDependencies": { 27 | "@types/jest": "^29.5.0", 28 | "@types/micromatch": "^4.0.10", 29 | "@types/node": "^20.10.5", 30 | "@typescript-eslint/eslint-plugin": "^6.0.0", 31 | "@typescript-eslint/parser": "^6.0.0", 32 | "eslint": "^8.0.0", 33 | "jest": "^29.5.0", 34 | "prettier": "^3.0.0", 35 | "ts-jest": "^29.1.0", 36 | "typescript": "^5.3.3" 37 | }, 38 | "keywords": [ 39 | "mcp", 40 | "model-context-protocol", 41 | "gemini", 42 | "google-gemini", 43 | "ai", 44 | "llm", 45 | "claude-desktop", 46 | "cursor", 47 | "windsurf", 48 | "typescript" 49 | ], 50 | "author": "LKbaba (based on aliargun/mcp-server-gemini)", 51 | "license": "MIT", 52 | "repository": { 53 | "type": "git", 54 | "url": "git+https://github.com/LKbaba/Gemini-mcp.git" 55 | }, 56 | "bugs": { 57 | "url": "https://github.com/LKbaba/Gemini-mcp/issues" 58 | }, 59 | "homepage": "https://github.com/LKbaba/Gemini-mcp#readme", 60 | "engines": { 61 | "node": ">=16.0.0" 62 | }, 63 | "files": [ 64 | "dist", 65 | "README.md", 66 | "LICENSE", 67 | "CHANGELOG.md" 68 | ] 69 | } 70 | -------------------------------------------------------------------------------- /dist/config/constants.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/config/constants.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /src/tools/list-models.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Tool 8: list_models 3 | * List all available Gemini models 4 | */ 5 | 6 | import { 7 | getAllModels, 8 | getDefaultModel, 9 | MODEL_RECOMMENDATIONS, 10 | ModelConfig, 11 | ModelCapabilities 12 | } from '../config/models.js'; 13 | 14 | /** 15 | * Model information output interface (more structured) 16 | */ 17 | export interface ModelInfo { 18 | id: string; 19 | name: string; 20 | description: string; 21 | /** Structured capability information */ 22 | capabilities: ModelCapabilities; 23 | /** Recommended use cases */ 24 | useCases: string[]; 25 | /** Whether this is the default model */ 26 | isDefault: boolean; 27 | /** List of supported features */ 28 | features: string[]; 29 | /** Best suited scenarios */ 30 | bestFor: string[]; 31 | /** Last update time */ 32 | lastUpdate: string; 33 | } 34 | 35 | /** 36 | * list_models return result interface 37 | */ 38 | export interface ListModelsResult { 39 | /** All available models */ 40 | models: ModelInfo[]; 41 | /** Default model ID */ 42 | defaultModel: string; 43 | /** Total number of models */ 44 | totalCount: number; 45 | /** Model recommendations by scenario */ 46 | recommendations: typeof MODEL_RECOMMENDATIONS; 47 | } 48 | 49 | /** 50 | * Handle list_models request 51 | * Returns detailed information about all available models, including structured capability information 52 | */ 53 | export async function handleListModels(): Promise { 54 | const models = getAllModels(); 55 | const defaultModel = getDefaultModel(); 56 | 57 | return { 58 | models: models.map((model) => ({ 59 | id: model.id, 60 | name: model.name, 61 | description: model.description, 62 | capabilities: model.capabilities, 63 | useCases: model.useCases, 64 | isDefault: model.isDefault, 65 | features: model.features, 66 | bestFor: model.bestFor, 67 | lastUpdate: model.lastUpdate 68 | })), 69 | defaultModel: defaultModel.id, 70 | totalCount: models.length, 71 | recommendations: MODEL_RECOMMENDATIONS 72 | }; 73 | } 74 | -------------------------------------------------------------------------------- /tests/handlers.test.ts: -------------------------------------------------------------------------------- 1 | import { describe, it, expect, jest } from '@jest/globals'; 2 | import { MCPHandlers } from '../src/handlers'; 3 | import { ERROR_CODES } from '../src/protocol'; 4 | 5 | describe('MCP Handlers', () => { 6 | const mockModel = { 7 | generateContent: jest.fn() 8 | }; 9 | 10 | beforeEach(() => { 11 | jest.clearAllMocks(); 12 | }); 13 | 14 | const handlers = new MCPHandlers(mockModel as any); 15 | 16 | describe('handleInitialize', () => { 17 | it('should return correct initialize response', async () => { 18 | const request = { 19 | jsonrpc: '2.0', 20 | id: 1, 21 | method: 'initialize' 22 | }; 23 | 24 | const response = await handlers.handleInitialize(request); 25 | 26 | expect(response).toMatchObject({ 27 | jsonrpc: '2.0', 28 | id: 1, 29 | result: { 30 | protocolVersion: '2024-11-05', 31 | serverInfo: expect.any(Object), 32 | capabilities: expect.any(Object) 33 | } 34 | }); 35 | }); 36 | }); 37 | 38 | describe('handleGenerate', () => { 39 | it('should handle missing prompt parameter', async () => { 40 | const request = { 41 | jsonrpc: '2.0', 42 | id: 1, 43 | method: 'generate', 44 | params: {} 45 | }; 46 | 47 | await expect(handlers.handleGenerate(request)).rejects.toThrow(); 48 | }); 49 | 50 | it('should handle successful generation', async () => { 51 | const mockResponse = { 52 | response: { 53 | text: () => 'Generated text' 54 | } 55 | }; 56 | 57 | mockModel.generateContent.mockResolvedValue(mockResponse); 58 | 59 | const request = { 60 | jsonrpc: '2.0', 61 | id: 1, 62 | method: 'generate', 63 | params: { 64 | prompt: 'Test prompt' 65 | } 66 | }; 67 | 68 | const response = await handlers.handleGenerate(request); 69 | 70 | expect(response).toMatchObject({ 71 | jsonrpc: '2.0', 72 | id: 1, 73 | result: { 74 | type: 'completion', 75 | content: 'Generated text', 76 | metadata: expect.any(Object) 77 | } 78 | }); 79 | }); 80 | }); 81 | }); -------------------------------------------------------------------------------- /dist/utils/error-handler.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"error-handler.js","sourceRoot":"","sources":["../../src/utils/error-handler.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/i18n.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"i18n.js","sourceRoot":"","sources":["../src/i18n.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/config/constants.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Global constant definitions 3 | */ 4 | // MCP protocol version 5 | export const MCP_VERSION = '2024-11-05'; 6 | // Server information 7 | export const SERVER_INFO = { 8 | name: 'mcp-server-gemini', 9 | version: '1.0.1', 10 | description: 'Specialized MCP server for Gemini 3.0 Pro focused on UI generation and frontend development', 11 | author: 'LKbaba', 12 | basedOn: 'aliargun/mcp-server-gemini v4.2.2' 13 | }; 14 | // API configuration 15 | export const API_CONFIG = { 16 | timeout: 60000, // 60 seconds 17 | maxRetries: 3, 18 | retryDelay: 1000, // 1 second 19 | maxImageSize: 10 * 1024 * 1024, // 10MB 20 | }; 21 | // Tool names 22 | export const TOOL_NAMES = { 23 | GENERATE_UI: 'gemini_generate_ui', 24 | MULTIMODAL_QUERY: 'gemini_multimodal_query', 25 | FIX_UI: 'gemini_fix_ui_from_screenshot', 26 | CREATE_ANIMATION: 'gemini_create_animation', 27 | ANALYZE_CONTENT: 'gemini_analyze_content', 28 | ANALYZE_CODEBASE: 'gemini_analyze_codebase', 29 | BRAINSTORM: 'gemini_brainstorm', 30 | LIST_MODELS: 'list_models' 31 | }; 32 | // Error codes 33 | export const ERROR_CODES = { 34 | INVALID_REQUEST: -32600, 35 | METHOD_NOT_FOUND: -32601, 36 | INVALID_PARAMS: -32602, 37 | INTERNAL_ERROR: -32603, 38 | PARSE_ERROR: -32700, 39 | API_ERROR: -32000, 40 | TIMEOUT: -32001, 41 | RATE_LIMIT: -32002, 42 | MODEL_NOT_SUPPORTED: -32003 43 | }; 44 | // Default parameters 45 | export const DEFAULT_PARAMS = { 46 | temperature: 0.7, 47 | maxTokens: 8192, 48 | topP: 0.95, 49 | topK: 40 50 | }; 51 | // Supported frameworks 52 | export const FRAMEWORKS = ['vanilla', 'react', 'vue', 'svelte']; 53 | // Supported technologies (animation) 54 | export const ANIMATION_TECHNOLOGIES = ['css', 'canvas', 'webgl', 'threejs']; 55 | // Supported styles 56 | export const UI_STYLES = ['modern', 'minimal', 'glassmorphism', 'neumorphism']; 57 | // Output formats 58 | export const OUTPUT_FORMATS = ['text', 'code', 'json', 'markdown']; 59 | // Content types 60 | export const CONTENT_TYPES = ['code', 'document', 'data', 'auto']; 61 | // Analysis task types 62 | export const ANALYSIS_TASKS = ['summarize', 'review', 'explain', 'optimize', 'debug']; 63 | // Codebase analysis focus areas 64 | export const CODEBASE_FOCUS = ['architecture', 'security', 'performance', 'dependencies', 'patterns']; 65 | // Brainstorm styles 66 | export const BRAINSTORM_STYLES = ['innovative', 'practical', 'radical']; 67 | // Feasibility levels 68 | export const FEASIBILITY_LEVELS = ['low', 'medium', 'high']; 69 | // Severity levels 70 | export const SEVERITY_LEVELS = ['high', 'medium', 'low']; 71 | //# sourceMappingURL=constants.js.map -------------------------------------------------------------------------------- /src/config/constants.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Global constant definitions 3 | */ 4 | 5 | // MCP protocol version 6 | export const MCP_VERSION = '2024-11-05'; 7 | 8 | // Server information 9 | export const SERVER_INFO = { 10 | name: 'mcp-server-gemini', 11 | version: '1.0.1', 12 | description: 'Specialized MCP server for Gemini 3.0 Pro focused on UI generation and frontend development', 13 | author: 'LKbaba', 14 | basedOn: 'aliargun/mcp-server-gemini v4.2.2' 15 | }; 16 | 17 | // API configuration 18 | export const API_CONFIG = { 19 | timeout: 60000, // 60 seconds 20 | maxRetries: 3, 21 | retryDelay: 1000, // 1 second 22 | maxImageSize: 10 * 1024 * 1024, // 10MB 23 | }; 24 | 25 | // Tool names 26 | export const TOOL_NAMES = { 27 | GENERATE_UI: 'gemini_generate_ui', 28 | MULTIMODAL_QUERY: 'gemini_multimodal_query', 29 | FIX_UI: 'gemini_fix_ui_from_screenshot', 30 | CREATE_ANIMATION: 'gemini_create_animation', 31 | ANALYZE_CONTENT: 'gemini_analyze_content', 32 | ANALYZE_CODEBASE: 'gemini_analyze_codebase', 33 | BRAINSTORM: 'gemini_brainstorm', 34 | LIST_MODELS: 'list_models' 35 | } as const; 36 | 37 | // Error codes 38 | export const ERROR_CODES = { 39 | INVALID_REQUEST: -32600, 40 | METHOD_NOT_FOUND: -32601, 41 | INVALID_PARAMS: -32602, 42 | INTERNAL_ERROR: -32603, 43 | PARSE_ERROR: -32700, 44 | API_ERROR: -32000, 45 | TIMEOUT: -32001, 46 | RATE_LIMIT: -32002, 47 | MODEL_NOT_SUPPORTED: -32003 48 | } as const; 49 | 50 | // Default parameters 51 | export const DEFAULT_PARAMS = { 52 | temperature: 0.7, 53 | maxTokens: 8192, 54 | topP: 0.95, 55 | topK: 40 56 | }; 57 | 58 | // Supported frameworks 59 | export const FRAMEWORKS = ['vanilla', 'react', 'vue', 'svelte'] as const; 60 | 61 | // Supported technologies (animation) 62 | export const ANIMATION_TECHNOLOGIES = ['css', 'canvas', 'webgl', 'threejs'] as const; 63 | 64 | // Supported styles 65 | export const UI_STYLES = ['modern', 'minimal', 'glassmorphism', 'neumorphism'] as const; 66 | 67 | // Output formats 68 | export const OUTPUT_FORMATS = ['text', 'code', 'json', 'markdown'] as const; 69 | 70 | // Content types 71 | export const CONTENT_TYPES = ['code', 'document', 'data', 'auto'] as const; 72 | 73 | // Analysis task types 74 | export const ANALYSIS_TASKS = ['summarize', 'review', 'explain', 'optimize', 'debug'] as const; 75 | 76 | // Codebase analysis focus areas 77 | export const CODEBASE_FOCUS = ['architecture', 'security', 'performance', 'dependencies', 'patterns'] as const; 78 | 79 | // Brainstorm styles 80 | export const BRAINSTORM_STYLES = ['innovative', 'practical', 'radical'] as const; 81 | 82 | // Feasibility levels 83 | export const FEASIBILITY_LEVELS = ['low', 'medium', 'high'] as const; 84 | 85 | // Severity levels 86 | export const SEVERITY_LEVELS = ['high', 'medium', 'low'] as const; 87 | -------------------------------------------------------------------------------- /dist/utils/error-handler.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Error handling utilities 3 | */ 4 | import { ERROR_CODES } from '../config/constants.js'; 5 | /** 6 | * Create MCP error object 7 | */ 8 | export function createMCPError(code, message, data) { 9 | return { code, message, data }; 10 | } 11 | /** 12 | * Handle API errors 13 | */ 14 | export function handleAPIError(error) { 15 | // API Key error 16 | if (error.message?.includes('API key') || error.message?.includes('Invalid key')) { 17 | return createMCPError(ERROR_CODES.API_ERROR, 'Invalid API key. Please check your GEMINI_API_KEY environment variable.', { originalError: error.message }); 18 | } 19 | // Quota error 20 | if (error.message?.includes('quota') || error.message?.includes('rate limit')) { 21 | return createMCPError(ERROR_CODES.RATE_LIMIT, 'API quota exceeded or rate limit reached. Please try again later.', { originalError: error.message }); 22 | } 23 | // Timeout error 24 | if (error.message?.includes('timeout')) { 25 | return createMCPError(ERROR_CODES.TIMEOUT, 'Request timeout. The operation took too long to complete.', { originalError: error.message }); 26 | } 27 | // Model not supported 28 | if (error.message?.includes('model') || error.message?.includes('not found')) { 29 | return createMCPError(ERROR_CODES.MODEL_NOT_SUPPORTED, 'The specified model is not supported or not available.', { originalError: error.message }); 30 | } 31 | // Generic API error 32 | return createMCPError(ERROR_CODES.API_ERROR, error.message || 'An error occurred while calling the Gemini API.', { originalError: error.message }); 33 | } 34 | /** 35 | * Handle parameter validation errors 36 | */ 37 | export function handleValidationError(message, details) { 38 | return createMCPError(ERROR_CODES.INVALID_PARAMS, message, details); 39 | } 40 | /** 41 | * Handle internal errors 42 | */ 43 | export function handleInternalError(error) { 44 | return createMCPError(ERROR_CODES.INTERNAL_ERROR, 'Internal server error', { originalError: error.message }); 45 | } 46 | /** 47 | * Sanitize error message (prevent sensitive information leakage) 48 | */ 49 | export function sanitizeErrorMessage(error) { 50 | if (typeof error === 'string') { 51 | return error.replace(/apiKey\s*=\s*[^\s]+/gi, 'apiKey=***'); 52 | } 53 | if (error.message) { 54 | return error.message.replace(/apiKey\s*=\s*[^\s]+/gi, 'apiKey=***'); 55 | } 56 | return 'Unknown error'; 57 | } 58 | /** 59 | * Log error (for debugging) 60 | */ 61 | export function logError(context, error) { 62 | const timestamp = new Date().toISOString(); 63 | const sanitized = sanitizeErrorMessage(error); 64 | console.error(`[${timestamp}] [${context}] Error:`, sanitized); 65 | if (error.stack) { 66 | console.error('Stack trace:', error.stack); 67 | } 68 | } 69 | //# sourceMappingURL=error-handler.js.map -------------------------------------------------------------------------------- /dist/tools/create-animation.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"create-animation.js","sourceRoot":"","sources":["../../src/tools/create-animation.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/config/models.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"models.js","sourceRoot":"","sources":["../../src/config/models.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Gemini MCP Server 2 | 3 | Thank you for your interest in contributing to the Gemini MCP Server! This document provides guidelines for contributing to the project. 4 | 5 | ## Code of Conduct 6 | 7 | This project follows a standard code of conduct. Please be respectful and constructive in all interactions. 8 | 9 | ## How to Contribute 10 | 11 | ### Reporting Issues 12 | 13 | 1. Check if the issue already exists in the [issue tracker](https://github.com/aliargun/mcp-server-gemini/issues) 14 | 2. If not, create a new issue with: 15 | - Clear description of the problem 16 | - Steps to reproduce 17 | - Expected behavior 18 | - Actual behavior 19 | - Your environment (OS, MCP client, Node.js version) 20 | - Relevant logs or error messages 21 | 22 | ### Suggesting Enhancements 23 | 24 | 1. Check if the enhancement has already been suggested 25 | 2. Create a new issue with the `enhancement` label 26 | 3. Describe the feature and why it would be useful 27 | 4. Provide examples of how it would work 28 | 29 | ### Pull Requests 30 | 31 | 1. Fork the repository 32 | 2. Create a new branch: `git checkout -b feature/your-feature-name` 33 | 3. Make your changes 34 | 4. Write or update tests if applicable 35 | 5. Update documentation if needed 36 | 6. Commit your changes with clear commit messages 37 | 7. Push to your fork 38 | 8. Create a pull request 39 | 40 | #### Pull Request Guidelines 41 | 42 | - Keep PRs focused - one feature or fix per PR 43 | - Follow the existing code style 44 | - Update the README.md if you're adding new features 45 | - Add tests for new functionality 46 | - Make sure all tests pass: `npm test` 47 | - Update type definitions if changing APIs 48 | 49 | ## Development Setup 50 | 51 | ```bash 52 | # Clone your fork 53 | git clone https://github.com/YOUR_USERNAME/mcp-server-gemini.git 54 | cd mcp-server-gemini 55 | 56 | # Install dependencies 57 | npm install 58 | 59 | # Run in development mode 60 | npm run dev 61 | 62 | # Run tests 63 | npm test 64 | 65 | # Build the project 66 | npm run build 67 | 68 | # Lint the code 69 | npm run lint 70 | ``` 71 | 72 | ## Code Style 73 | 74 | - TypeScript with strict mode 75 | - ESM modules 76 | - Use async/await over callbacks 77 | - Add JSDoc comments for public APIs 78 | - Follow the existing patterns in the codebase 79 | 80 | ## Testing 81 | 82 | - Write tests for new features 83 | - Ensure existing tests pass 84 | - Test with multiple MCP clients if possible 85 | - Test error cases and edge conditions 86 | 87 | ## Documentation 88 | 89 | - Update README.md for new features 90 | - Add JSDoc comments for new functions 91 | - Update USAGE_GUIDE.md if adding new tools 92 | - Update PARAMETERS_REFERENCE.md for new parameters 93 | 94 | ## Release Process 95 | 96 | Maintainers will: 97 | 1. Review and merge PRs 98 | 2. Update version in package.json 99 | 3. Update CHANGELOG.md 100 | 4. Create a new release on GitHub 101 | 5. Publish to npm if applicable 102 | 103 | ## Questions? 104 | 105 | Feel free to open an issue for any questions about contributing! -------------------------------------------------------------------------------- /src/utils/error-handler.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Error handling utilities 3 | */ 4 | 5 | import { ERROR_CODES } from '../config/constants.js'; 6 | import { MCPError } from '../types.js'; 7 | 8 | /** 9 | * Create MCP error object 10 | */ 11 | export function createMCPError(code: number, message: string, data?: any): MCPError { 12 | return { code, message, data }; 13 | } 14 | 15 | /** 16 | * Handle API errors 17 | */ 18 | export function handleAPIError(error: any): MCPError { 19 | // API Key error 20 | if (error.message?.includes('API key') || error.message?.includes('Invalid key')) { 21 | return createMCPError( 22 | ERROR_CODES.API_ERROR, 23 | 'Invalid API key. Please check your GEMINI_API_KEY environment variable.', 24 | { originalError: error.message } 25 | ); 26 | } 27 | 28 | // Quota error 29 | if (error.message?.includes('quota') || error.message?.includes('rate limit')) { 30 | return createMCPError( 31 | ERROR_CODES.RATE_LIMIT, 32 | 'API quota exceeded or rate limit reached. Please try again later.', 33 | { originalError: error.message } 34 | ); 35 | } 36 | 37 | // Timeout error 38 | if (error.message?.includes('timeout')) { 39 | return createMCPError( 40 | ERROR_CODES.TIMEOUT, 41 | 'Request timeout. The operation took too long to complete.', 42 | { originalError: error.message } 43 | ); 44 | } 45 | 46 | // Model not supported 47 | if (error.message?.includes('model') || error.message?.includes('not found')) { 48 | return createMCPError( 49 | ERROR_CODES.MODEL_NOT_SUPPORTED, 50 | 'The specified model is not supported or not available.', 51 | { originalError: error.message } 52 | ); 53 | } 54 | 55 | // Generic API error 56 | return createMCPError( 57 | ERROR_CODES.API_ERROR, 58 | error.message || 'An error occurred while calling the Gemini API.', 59 | { originalError: error.message } 60 | ); 61 | } 62 | 63 | /** 64 | * Handle parameter validation errors 65 | */ 66 | export function handleValidationError(message: string, details?: any): MCPError { 67 | return createMCPError(ERROR_CODES.INVALID_PARAMS, message, details); 68 | } 69 | 70 | /** 71 | * Handle internal errors 72 | */ 73 | export function handleInternalError(error: any): MCPError { 74 | return createMCPError( 75 | ERROR_CODES.INTERNAL_ERROR, 76 | 'Internal server error', 77 | { originalError: error.message } 78 | ); 79 | } 80 | 81 | /** 82 | * Sanitize error message (prevent sensitive information leakage) 83 | */ 84 | export function sanitizeErrorMessage(error: any): string { 85 | if (typeof error === 'string') { 86 | return error.replace(/apiKey\s*=\s*[^\s]+/gi, 'apiKey=***'); 87 | } 88 | if (error.message) { 89 | return error.message.replace(/apiKey\s*=\s*[^\s]+/gi, 'apiKey=***'); 90 | } 91 | return 'Unknown error'; 92 | } 93 | 94 | /** 95 | * Log error (for debugging) 96 | */ 97 | export function logError(context: string, error: any): void { 98 | const timestamp = new Date().toISOString(); 99 | const sanitized = sanitizeErrorMessage(error); 100 | console.error(`[${timestamp}] [${context}] Error:`, sanitized); 101 | 102 | if (error.stack) { 103 | console.error('Stack trace:', error.stack); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /dist/tools/multimodal-query.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Tool 2: gemini_multimodal_query 3 | * Query using images + text for multimodal understanding 4 | * Priority: P0 - Core functionality 5 | */ 6 | import { validateRequired, validateString, validateArray, validateOutputFormat } from '../utils/validators.js'; 7 | import { handleAPIError, logError } from '../utils/error-handler.js'; 8 | // System prompt for multimodal query 9 | const MULTIMODAL_QUERY_SYSTEM_PROMPT = `You are a visual understanding expert with deep knowledge of: 10 | - UI/UX design patterns and principles 11 | - Frontend development (HTML/CSS/JavaScript) 12 | - Architecture diagrams and technical documentation 13 | - Design systems and component libraries 14 | 15 | When analyzing images: 16 | 1. Identify all key elements and their purposes 17 | 2. Understand spatial relationships and layouts 18 | 3. Recognize design patterns and conventions 19 | 4. Detect colors, typography, spacing with precision 20 | 5. Infer interactive states (hover, active, disabled) 21 | 22 | When asked to convert designs to code: 23 | - Provide complete, production-ready implementation 24 | - Match the design pixel-perfectly 25 | - Include all visible and implied interactions 26 | 27 | When asked questions about designs: 28 | - Be specific and detailed 29 | - Reference exact colors (hex codes) 30 | - Mention spacing values when relevant 31 | - Suggest improvements if asked 32 | 33 | Output format: 34 | - Adapt to the requested format (text/code/json) 35 | - Be concise but comprehensive 36 | - Use professional terminology`; 37 | /** 38 | * Handle gemini_multimodal_query tool call 39 | */ 40 | export async function handleMultimodalQuery(params, client) { 41 | try { 42 | // Validate required parameters 43 | validateRequired(params.prompt, 'prompt'); 44 | validateString(params.prompt, 'prompt', 5); 45 | validateRequired(params.images, 'images'); 46 | validateArray(params.images, 'images', 1); 47 | // Validate optional parameters 48 | const outputFormat = params.outputFormat || 'text'; 49 | if (params.outputFormat) { 50 | validateOutputFormat(params.outputFormat); 51 | } 52 | // Build the prompt 53 | let fullPrompt = params.prompt; 54 | if (params.context) { 55 | fullPrompt = `Context: ${params.context}\n\nQuestion: ${params.prompt}`; 56 | } 57 | if (outputFormat === 'json') { 58 | fullPrompt += `\n\nPlease provide your response in valid JSON format.`; 59 | } 60 | else if (outputFormat === 'code') { 61 | fullPrompt += `\n\nPlease provide your response as code only, no explanations.`; 62 | } 63 | // Call Gemini API with multimodal input 64 | const response = await client.generateMultimodal(fullPrompt, params.images, { 65 | systemInstruction: MULTIMODAL_QUERY_SYSTEM_PROMPT, 66 | temperature: 0.7, 67 | maxTokens: 4096 68 | }); 69 | return { 70 | response, 71 | format: outputFormat, 72 | metadata: { 73 | imageCount: params.images.length, 74 | modelUsed: client.getModel() 75 | } 76 | }; 77 | } 78 | catch (error) { 79 | logError('multimodalQuery', error); 80 | throw handleAPIError(error); 81 | } 82 | } 83 | //# sourceMappingURL=multimodal-query.js.map -------------------------------------------------------------------------------- /dist/utils/validators.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"validators.js","sourceRoot":"","sources":["../../src/utils/validators.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,UAAU,EACV,sBAAsB,EACtB,SAAS,EACT,cAAc,EACd,aAAa,EACb,cAAc,EACd,cAAc,EACd,iBAAiB,EAClB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAEvD;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAU,EAAE,SAAiB;IAC5D,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,GAAG,SAAS,cAAc,CAAC,CAAC;IAC9C,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,KAAU,EAAE,SAAiB,EAAE,SAAS,GAAG,CAAC;IACzE,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,GAAG,SAAS,mBAAmB,CAAC,CAAC;IACnD,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,GAAG,SAAS,qBAAqB,SAAS,kBAAkB,CAAC,CAAC;IAChF,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,KAAU,EAAE,SAAiB,EAAE,GAAY,EAAE,GAAY;IACtF,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,GAAG,SAAS,mBAAmB,CAAC,CAAC;IACnD,CAAC;IACD,IAAI,GAAG,KAAK,SAAS,IAAI,KAAK,GAAG,GAAG,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CAAC,GAAG,SAAS,qBAAqB,GAAG,EAAE,CAAC,CAAC;IAC1D,CAAC;IACD,IAAI,GAAG,KAAK,SAAS,IAAI,KAAK,GAAG,GAAG,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CAAC,GAAG,SAAS,oBAAoB,GAAG,EAAE,CAAC,CAAC;IACzD,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,KAAU,EAAE,SAAiB;IAC3D,IAAI,OAAO,KAAK,KAAK,SAAS,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,GAAG,SAAS,oBAAoB,CAAC,CAAC;IACpD,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAC1B,KAAU,EACV,SAAiB,EACjB,aAAgB;IAEhB,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CACb,GAAG,SAAS,oBAAoB,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,KAAK,EAAE,CAC1E,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,KAAU,EAAE,SAAiB,EAAE,SAAS,GAAG,CAAC;IACxE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,GAAG,SAAS,mBAAmB,CAAC,CAAC;IACnD,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CAAC,GAAG,SAAS,uBAAuB,SAAS,UAAU,CAAC,CAAC;IAC1E,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAa,EAAE,SAAiB;IAClE,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,KAAK,CAAC,GAAG,SAAS,kDAAkD,CAAC,CAAC;IAClF,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa,EAAE,SAAiB;IAC1D,IAAI,CAAC;QACH,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC;IACjB,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,GAAG,SAAS,sBAAsB,CAAC,CAAC;IACtD,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,YAAY,CAAC,KAAK,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC;AAC/C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,2BAA2B,CAAC,KAAa;IACvD,YAAY,CAAC,KAAK,EAAE,YAAY,EAAE,sBAAsB,CAAC,CAAC;AAC5D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;AAC1C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAChD,YAAY,CAAC,KAAK,EAAE,cAAc,EAAE,cAAc,CAAC,CAAC;AACtD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC;AAC7C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAa;IAChD,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,cAAc,CAAC,CAAC;AAC9C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAa;IACjD,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC;AAC/C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB,CAAC,KAAa;IACnD,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,iBAAiB,CAAC,CAAC;AAClD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CACb,UAAU,OAAO,+GAA+G,CACjI,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,WAAmB;IACrD,cAAc,CAAC,WAAW,EAAE,aAAa,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACnD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,SAAiB;IACjD,cAAc,CAAC,SAAS,EAAE,WAAW,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;AACnD,CAAC"} -------------------------------------------------------------------------------- /dist/windows-utils.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"windows-utils.js","sourceRoot":"","sources":["../src/windows-utils.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /src/tools/multimodal-query.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Tool 2: gemini_multimodal_query 3 | * Query using images + text for multimodal understanding 4 | * Priority: P0 - Core functionality 5 | */ 6 | 7 | import { GeminiClient } from '../utils/gemini-client.js'; 8 | import { 9 | validateRequired, 10 | validateString, 11 | validateArray, 12 | validateOutputFormat 13 | } from '../utils/validators.js'; 14 | import { handleAPIError, logError } from '../utils/error-handler.js'; 15 | 16 | // System prompt for multimodal query 17 | const MULTIMODAL_QUERY_SYSTEM_PROMPT = `You are a visual understanding expert with deep knowledge of: 18 | - UI/UX design patterns and principles 19 | - Frontend development (HTML/CSS/JavaScript) 20 | - Architecture diagrams and technical documentation 21 | - Design systems and component libraries 22 | 23 | When analyzing images: 24 | 1. Identify all key elements and their purposes 25 | 2. Understand spatial relationships and layouts 26 | 3. Recognize design patterns and conventions 27 | 4. Detect colors, typography, spacing with precision 28 | 5. Infer interactive states (hover, active, disabled) 29 | 30 | When asked to convert designs to code: 31 | - Provide complete, production-ready implementation 32 | - Match the design pixel-perfectly 33 | - Include all visible and implied interactions 34 | 35 | When asked questions about designs: 36 | - Be specific and detailed 37 | - Reference exact colors (hex codes) 38 | - Mention spacing values when relevant 39 | - Suggest improvements if asked 40 | 41 | Output format: 42 | - Adapt to the requested format (text/code/json) 43 | - Be concise but comprehensive 44 | - Use professional terminology`; 45 | 46 | export interface MultimodalQueryParams { 47 | prompt: string; 48 | images: string[]; 49 | outputFormat?: 'text' | 'code' | 'json'; 50 | context?: string; 51 | } 52 | 53 | export interface MultimodalQueryResult { 54 | response: string; 55 | format: string; 56 | metadata?: { 57 | imageCount: number; 58 | modelUsed: string; 59 | }; 60 | } 61 | 62 | /** 63 | * Handle gemini_multimodal_query tool call 64 | */ 65 | export async function handleMultimodalQuery( 66 | params: MultimodalQueryParams, 67 | client: GeminiClient 68 | ): Promise { 69 | try { 70 | // Validate required parameters 71 | validateRequired(params.prompt, 'prompt'); 72 | validateString(params.prompt, 'prompt', 5); 73 | validateRequired(params.images, 'images'); 74 | validateArray(params.images, 'images', 1); 75 | 76 | // Validate optional parameters 77 | const outputFormat = params.outputFormat || 'text'; 78 | if (params.outputFormat) { 79 | validateOutputFormat(params.outputFormat); 80 | } 81 | 82 | // Build the prompt 83 | let fullPrompt = params.prompt; 84 | 85 | if (params.context) { 86 | fullPrompt = `Context: ${params.context}\n\nQuestion: ${params.prompt}`; 87 | } 88 | 89 | if (outputFormat === 'json') { 90 | fullPrompt += `\n\nPlease provide your response in valid JSON format.`; 91 | } else if (outputFormat === 'code') { 92 | fullPrompt += `\n\nPlease provide your response as code only, no explanations.`; 93 | } 94 | 95 | // Call Gemini API with multimodal input 96 | const response = await client.generateMultimodal( 97 | fullPrompt, 98 | params.images, 99 | { 100 | systemInstruction: MULTIMODAL_QUERY_SYSTEM_PROMPT, 101 | temperature: 0.7, 102 | maxTokens: 4096 103 | } 104 | ); 105 | 106 | return { 107 | response, 108 | format: outputFormat, 109 | metadata: { 110 | imageCount: params.images.length, 111 | modelUsed: client.getModel() 112 | } 113 | }; 114 | 115 | } catch (error: any) { 116 | logError('multimodalQuery', error); 117 | throw handleAPIError(error); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /dist/tools/fix-ui.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"fix-ui.js","sourceRoot":"","sources":["../../src/tools/fix-ui.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EACL,gBAAgB,EAChB,cAAc,EACf,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAe,MAAM,yBAAyB,CAAC;AAE3E,iCAAiC;AACjC,MAAM,oBAAoB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gCAgCG,CAAC;AAgCjC;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,MAAmB,EACnB,MAAoB;IAEpB,IAAI,CAAC;QACH,+BAA+B;QAC/B,+FAA+F;QAC/F,gBAAgB,CAAC,MAAM,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;QAClD,cAAc,CAAC,MAAM,CAAC,UAAU,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC;QAEnD,+BAA+B;QAC/B,IAAI,WAAW,GAAG,EAAE,CAAC;QACrB,MAAM,aAAa,GAAa,EAAE,CAAC;QAEnC,6BAA6B;QAC7B,IAAI,MAAM,CAAC,cAAc,EAAE,CAAC;YAC1B,IAAI,CAAC;gBACH,MAAM,WAAW,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;gBAC1D,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;gBACrC,WAAW,IAAI,6BAA6B,WAAW,CAAC,IAAI,IAAI,CAAC;gBACjE,WAAW,IAAI,SAAS,WAAW,CAAC,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,CAAC;gBACtE,WAAW,IAAI,WAAW,CAAC,OAAO,CAAC;gBACnC,WAAW,IAAI,WAAW,CAAC;YAC7B,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,QAAQ,CAAC,0BAA0B,EAAE,KAAK,CAAC,CAAC;gBAC5C,uCAAuC;YACzC,CAAC;QACH,CAAC;QAED,qBAAqB;QACrB,IAAI,MAAM,CAAC,YAAY,IAAI,MAAM,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC1D,IAAI,CAAC;gBACH,MAAM,eAAe,GAAG,MAAM,SAAS,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;gBAC7D,KAAK,MAAM,IAAI,IAAI,eAAe,EAAE,CAAC;oBACnC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBAC9B,WAAW,IAAI,oBAAoB,IAAI,CAAC,IAAI,IAAI,CAAC;oBACjD,WAAW,IAAI,SAAS,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,CAAC;oBAC/D,WAAW,IAAI,IAAI,CAAC,OAAO,CAAC;oBAC5B,WAAW,IAAI,WAAW,CAAC;gBAC7B,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,QAAQ,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAC;gBAC1C,uCAAuC;YACzC,CAAC;QACH,CAAC;QAED,0EAA0E;QAC1E,IAAI,MAAM,CAAC,WAAW,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;YACjD,WAAW,IAAI,4BAA4B,MAAM,CAAC,WAAW,cAAc,CAAC;QAC9E,CAAC;QAED,eAAe;QACf,IAAI,MAAM,GAAG,2DAA2D,CAAC;QAEzE,IAAI,MAAM,CAAC,gBAAgB,EAAE,CAAC;YAC5B,MAAM,IAAI,gBAAgB,MAAM,CAAC,gBAAgB,MAAM,CAAC;QAC1D,CAAC;QAED,mBAAmB;QACnB,IAAI,WAAW,EAAE,CAAC;YAChB,MAAM,IAAI,0BAA0B,WAAW,IAAI,CAAC;QACtD,CAAC;QAED,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;YACvB,mCAAmC;YACnC,MAAM,aAAa,GAAG,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;YAClE,MAAM,UAAU,GAAG,yCAAyC,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;YACtF,IAAI,CAAC,aAAa,IAAI,CAAC,UAAU,EAAE,CAAC;gBAClC,MAAM,IAAI,mBAAmB,MAAM,CAAC,WAAW,MAAM,CAAC;YACxD,CAAC;QACH,CAAC;QAED,sEAAsE;QACtE,MAAM,cAAc,GAAG,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC;QAChD,MAAM,IAAI;;8CAEgC,cAAc,CAAC,CAAC,CAAC,mCAAmC,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;2CAU5D,cAAc,CAAC,CAAC,CAAC,yCAAyC,CAAC,CAAC,CAAC,EAAE;;;;EAIxG,CAAC;QAEC,kBAAkB;QAClB,MAAM,MAAM,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QACnC,wEAAwE;QACxE,sDAAsD;QACtD,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;YACvB,MAAM,aAAa,GAAG,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;YAClE,MAAM,UAAU,GAAG,yCAAyC,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;YACtF,IAAI,aAAa,IAAI,UAAU,EAAE,CAAC;gBAChC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;YAClC,CAAC;QACH,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAC9C,MAAM,EACN,MAAM,EACN;YACE,iBAAiB,EAAE,oBAAoB;YACvC,WAAW,EAAE,GAAG;YAChB,SAAS,EAAE,IAAI;SAChB,CACF,CAAC;QAEF,uBAAuB;QACvB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YACpC,0BAA0B;YAC1B,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC7B,MAAM,CAAC,aAAa,GAAG,aAAa,CAAC;YACvC,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,MAAM,CAAC;YACP,0CAA0C;YAC1C,OAAO;gBACL,SAAS,EAAE,QAAQ;gBACnB,KAAK,EAAE,CAAC;wBACN,WAAW,EAAE,aAAa;wBAC1B,IAAI,EAAE,uBAAuB,CAAC,QAAQ,CAAC;wBACvC,OAAO,EAAE,CAAC,2BAA2B,CAAC;qBACvC,CAAC;gBACF,aAAa,EAAE,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS;aACpE,CAAC;QACJ,CAAC;IAEH,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,QAAQ,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACzB,MAAM,cAAc,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,uBAAuB,CAAC,QAAgB;IAC/C,6BAA6B;IAC7B,MAAM,UAAU,GAAG,QAAQ,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACrD,IAAI,UAAU,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxC,OAAO,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAC5B,KAAK,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAC7D,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACjB,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC"} -------------------------------------------------------------------------------- /dist/i18n.js: -------------------------------------------------------------------------------- 1 | /** 2 | * 国际化支持 - 中文错误信息和系统提示 3 | * i18n Support - Chinese error messages and system prompts 4 | */ 5 | export const ERROR_MESSAGES = { 6 | API_KEY_MISSING: '缺少 GEMINI_API_KEY 环境变量。请设置您的 Google Gemini API 密钥。', 7 | API_KEY_INVALID: 'Gemini API 密钥无效或已过期。请检查您的 API 密钥。', 8 | MODEL_NOT_FOUND: '找不到指定的模型。请使用 list_models 工具查看可用模型列表。', 9 | NETWORK_ERROR: '网络连接失败。请检查您的网络连接和代理设置。', 10 | RATE_LIMIT: 'API 调用频率超限。请稍后重试。', 11 | CONTEXT_TOO_LONG: '上下文长度超出模型限制。请减少输入内容或清除对话历史。', 12 | SAFETY_BLOCKED: '内容因安全策略被拦截。请修改您的输入内容。', 13 | INVALID_REQUEST: '无效的请求格式。请检查您的输入参数。', 14 | SERVER_ERROR: 'Gemini API 服务器错误。请稍后重试。', 15 | THINKING_NOT_SUPPORTED: '所选模型不支持思考模式。请使用 gemini-2.5-pro 或 gemini-2.5-flash。', 16 | FILE_NOT_FOUND: '找不到指定的文件。请检查文件路径是否正确。', 17 | FILE_READ_ERROR: '读取文件失败。请检查文件权限和路径格式。' 18 | }; 19 | export const SYSTEM_PROMPTS = { 20 | CHINESE_OPTIMIZATION: ` 21 | 你是一个专为中文用户优化的 AI 助手,运行在 Windows 平台上。 22 | 23 | ## 重要提示 24 | 1. **路径格式**: Windows 使用反斜杠 \\ 作为路径分隔符(如 C:\\Users\\...) 25 | 2. **中文路径**: 支持中文文件名和文件夹名,但建议使用英文路径以避免编码问题 26 | 3. **换行符**: Windows 使用 CRLF (\\r\\n) 而非 LF (\\n) 27 | 4. **大小写**: Windows 文件系统不区分大小写 28 | 29 | ## 交互规则 30 | - 优先使用中文进行交流 31 | - 代码注释使用中文 32 | - 错误信息提供中文说明 33 | - 提供 Windows 平台特定的建议 34 | `, 35 | WINDOWS_PATH_TIPS: ` 36 | ## Windows 路径处理建议 37 | 1. 使用 path.normalize() 标准化路径 38 | 2. 使用 path.join() 拼接路径,自动处理分隔符 39 | 3. 使用 path.resolve() 获取绝对路径 40 | 4. 避免硬编码路径分隔符 41 | 5. 处理中文路径时使用 UTF-8 编码 42 | ` 43 | }; 44 | /** 45 | * 将英文错误信息翻译为中文 46 | * @param error 原始错误对象 47 | * @returns 中文错误信息 48 | */ 49 | export function translateError(error) { 50 | const message = error.message || error.toString(); 51 | // API Key 相关 52 | if (message.includes('API key') || message.includes('GEMINI_API_KEY')) { 53 | return ERROR_MESSAGES.API_KEY_MISSING; 54 | } 55 | if (message.includes('invalid') && message.includes('key')) { 56 | return ERROR_MESSAGES.API_KEY_INVALID; 57 | } 58 | // 网络相关 59 | if (message.includes('network') || message.includes('ECONNREFUSED') || message.includes('ETIMEDOUT')) { 60 | return ERROR_MESSAGES.NETWORK_ERROR; 61 | } 62 | if (message.includes('rate limit') || message.includes('quota')) { 63 | return ERROR_MESSAGES.RATE_LIMIT; 64 | } 65 | // 模型和内容相关 66 | if (message.includes('model not found') || message.includes('invalid model')) { 67 | return ERROR_MESSAGES.MODEL_NOT_FOUND; 68 | } 69 | if (message.includes('context length') || message.includes('too long')) { 70 | return ERROR_MESSAGES.CONTEXT_TOO_LONG; 71 | } 72 | if (message.includes('safety') || message.includes('blocked')) { 73 | return ERROR_MESSAGES.SAFETY_BLOCKED; 74 | } 75 | if (message.includes('thinking') && message.includes('not supported')) { 76 | return ERROR_MESSAGES.THINKING_NOT_SUPPORTED; 77 | } 78 | // 文件相关 79 | if (message.includes('ENOENT') || message.includes('not found')) { 80 | return ERROR_MESSAGES.FILE_NOT_FOUND; 81 | } 82 | if (message.includes('EACCES') || message.includes('permission')) { 83 | return ERROR_MESSAGES.FILE_READ_ERROR; 84 | } 85 | // 服务器错误 86 | if (message.includes('500') || message.includes('server error')) { 87 | return ERROR_MESSAGES.SERVER_ERROR; 88 | } 89 | // 默认返回原始错误和中文说明 90 | return `操作失败: ${message}`; 91 | } 92 | /** 93 | * 格式化成功消息 94 | * @param key 消息类型 95 | * @param details 详细信息 96 | * @returns 格式化的中文消息 97 | */ 98 | export function formatSuccessMessage(key, details) { 99 | const messages = { 100 | chat_complete: '对话完成', 101 | models_listed: `已列出 ${details?.count || 0} 个可用模型`, 102 | conversation_cleared: '对话历史已清除', 103 | file_read: `成功读取文件: ${details?.path || ''}`, 104 | thinking_enabled: '已启用思考模式', 105 | thinking_disabled: '已禁用思考模式' 106 | }; 107 | return messages[key] || '操作成功'; 108 | } 109 | //# sourceMappingURL=i18n.js.map -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | // Base MCP Protocol Types 2 | export interface MCPRequest { 3 | jsonrpc: '2.0'; 4 | id: string | number; 5 | method: string; 6 | params?: any; 7 | } 8 | 9 | export interface MCPResponse { 10 | jsonrpc: '2.0'; 11 | id: string | number; 12 | result?: any; 13 | error?: { 14 | code: number; 15 | message: string; 16 | data?: any; 17 | }; 18 | } 19 | 20 | export interface MCPError { 21 | code: number; 22 | message: string; 23 | data?: any; 24 | } 25 | 26 | // Connection Management 27 | export interface ConnectionState { 28 | connectedAt: Date; 29 | lastMessageAt: Date; 30 | initialized: boolean; 31 | activeRequests: Set; 32 | ip: string; 33 | } 34 | 35 | // Notification Types 36 | export interface NotificationMessage { 37 | jsonrpc: '2.0'; 38 | method: string; 39 | params?: any; 40 | } 41 | 42 | export interface ErrorNotification extends NotificationMessage { 43 | method: 'notifications/error'; 44 | params: { 45 | code: number; 46 | message: string; 47 | data?: any; 48 | }; 49 | } 50 | 51 | export interface ProgressParams { 52 | progressToken: string | number; 53 | progress: number; 54 | total?: number; 55 | } 56 | 57 | export interface ProgressNotification extends NotificationMessage { 58 | method: 'notifications/progress'; 59 | params: ProgressParams; 60 | } 61 | 62 | // Request Types 63 | export interface GenerateRequest extends MCPRequest { 64 | method: 'generate'; 65 | params: { 66 | prompt: string; 67 | temperature?: number; 68 | maxTokens?: number; 69 | stopSequences?: string[]; 70 | }; 71 | } 72 | 73 | export interface GenerateResponse extends MCPResponse { 74 | result: { 75 | type: 'completion'; 76 | content: string; 77 | metadata: { 78 | model: string; 79 | provider: string; 80 | temperature?: number; 81 | maxTokens?: number; 82 | stopSequences?: string[]; 83 | }; 84 | }; 85 | } 86 | 87 | export interface StreamRequest extends MCPRequest { 88 | method: 'stream'; 89 | params: { 90 | prompt: string; 91 | temperature?: number; 92 | maxTokens?: number; 93 | stopSequences?: string[]; 94 | }; 95 | } 96 | 97 | export interface StreamResponse extends MCPResponse { 98 | result: { 99 | type: 'stream'; 100 | content: string; 101 | done: boolean; 102 | }; 103 | } 104 | 105 | export interface CancelRequest extends MCPRequest { 106 | method: 'cancel'; 107 | params: { 108 | requestId: string | number; 109 | }; 110 | } 111 | 112 | export interface ConfigureRequest extends MCPRequest { 113 | method: 'configure'; 114 | params: { 115 | configuration: { 116 | model?: string; 117 | temperature?: number; 118 | maxTokens?: number; 119 | stopSequences?: string[]; 120 | timeout?: number; 121 | }; 122 | }; 123 | } 124 | 125 | // Server Configuration 126 | export interface ServerInfo { 127 | name: string; 128 | version: string; 129 | } 130 | 131 | export interface ServerCapabilities { 132 | experimental?: Record; 133 | prompts?: { 134 | listChanged?: boolean; 135 | }; 136 | resources?: { 137 | subscribe?: boolean; 138 | listChanged?: boolean; 139 | }; 140 | tools?: { 141 | listChanged?: boolean; 142 | }; 143 | logging?: Record; 144 | } 145 | 146 | export interface InitializeResult { 147 | protocolVersion: string; 148 | serverInfo: ServerInfo; 149 | capabilities: ServerCapabilities; 150 | } 151 | 152 | // Lifecycle Types 153 | export interface ShutdownRequest extends MCPRequest { 154 | method: 'shutdown'; 155 | } 156 | 157 | export interface ExitNotification extends NotificationMessage { 158 | method: 'exit'; 159 | } 160 | 161 | // Resource and Prompt References (for interfaces) 162 | export interface ResourceReference { 163 | type: 'resource'; 164 | uri: string; 165 | } 166 | 167 | export interface PromptReference { 168 | type: 'prompt'; 169 | name: string; 170 | } 171 | 172 | export interface CompletionArgument { 173 | name: string; 174 | value: string; 175 | } 176 | 177 | export interface Completion { 178 | values: Array<{ 179 | value: string; 180 | description?: string; 181 | }>; 182 | total?: number; 183 | hasMore?: boolean; 184 | } -------------------------------------------------------------------------------- /dist/utils/gemini-client.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"gemini-client.js","sourceRoot":"","sources":["../../src/utils/gemini-client.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/utils/validators.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Parameter validation utilities 3 | */ 4 | import { FRAMEWORKS, ANIMATION_TECHNOLOGIES, UI_STYLES, OUTPUT_FORMATS, CONTENT_TYPES, ANALYSIS_TASKS, CODEBASE_FOCUS, BRAINSTORM_STYLES } from '../config/constants.js'; 5 | import { isModelSupported } from '../config/models.js'; 6 | /** 7 | * Validate required parameter 8 | */ 9 | export function validateRequired(value, fieldName) { 10 | if (value === undefined || value === null || value === '') { 11 | throw new Error(`${fieldName} is required`); 12 | } 13 | } 14 | /** 15 | * Validate string 16 | */ 17 | export function validateString(value, fieldName, minLength = 1) { 18 | if (typeof value !== 'string') { 19 | throw new Error(`${fieldName} must be a string`); 20 | } 21 | if (value.length < minLength) { 22 | throw new Error(`${fieldName} must be at least ${minLength} characters long`); 23 | } 24 | } 25 | /** 26 | * Validate number 27 | */ 28 | export function validateNumber(value, fieldName, min, max) { 29 | if (typeof value !== 'number' || isNaN(value)) { 30 | throw new Error(`${fieldName} must be a number`); 31 | } 32 | if (min !== undefined && value < min) { 33 | throw new Error(`${fieldName} must be at least ${min}`); 34 | } 35 | if (max !== undefined && value > max) { 36 | throw new Error(`${fieldName} must be at most ${max}`); 37 | } 38 | } 39 | /** 40 | * Validate boolean 41 | */ 42 | export function validateBoolean(value, fieldName) { 43 | if (typeof value !== 'boolean') { 44 | throw new Error(`${fieldName} must be a boolean`); 45 | } 46 | } 47 | /** 48 | * Validate enum value 49 | */ 50 | export function validateEnum(value, fieldName, allowedValues) { 51 | if (!allowedValues.includes(value)) { 52 | throw new Error(`${fieldName} must be one of: ${allowedValues.join(', ')}. Got: ${value}`); 53 | } 54 | } 55 | /** 56 | * Validate array 57 | */ 58 | export function validateArray(value, fieldName, minLength = 1) { 59 | if (!Array.isArray(value)) { 60 | throw new Error(`${fieldName} must be an array`); 61 | } 62 | if (value.length < minLength) { 63 | throw new Error(`${fieldName} must have at least ${minLength} item(s)`); 64 | } 65 | } 66 | /** 67 | * Validate Base64 image 68 | */ 69 | export function validateBase64Image(value, fieldName) { 70 | if (!value.startsWith('data:image/')) { 71 | throw new Error(`${fieldName} must be a Base64 encoded image (data:image/...)`); 72 | } 73 | } 74 | /** 75 | * Validate URL 76 | */ 77 | export function validateURL(value, fieldName) { 78 | try { 79 | new URL(value); 80 | } 81 | catch { 82 | throw new Error(`${fieldName} must be a valid URL`); 83 | } 84 | } 85 | /** 86 | * Validate framework 87 | */ 88 | export function validateFramework(value) { 89 | validateEnum(value, 'framework', FRAMEWORKS); 90 | } 91 | /** 92 | * Validate animation technology 93 | */ 94 | export function validateAnimationTechnology(value) { 95 | validateEnum(value, 'technology', ANIMATION_TECHNOLOGIES); 96 | } 97 | /** 98 | * Validate UI style 99 | */ 100 | export function validateUIStyle(value) { 101 | validateEnum(value, 'style', UI_STYLES); 102 | } 103 | /** 104 | * Validate output format 105 | */ 106 | export function validateOutputFormat(value) { 107 | validateEnum(value, 'outputFormat', OUTPUT_FORMATS); 108 | } 109 | /** 110 | * Validate content type 111 | */ 112 | export function validateContentType(value) { 113 | validateEnum(value, 'type', CONTENT_TYPES); 114 | } 115 | /** 116 | * Validate analysis task 117 | */ 118 | export function validateAnalysisTask(value) { 119 | validateEnum(value, 'task', ANALYSIS_TASKS); 120 | } 121 | /** 122 | * Validate codebase focus 123 | */ 124 | export function validateCodebaseFocus(value) { 125 | validateEnum(value, 'focus', CODEBASE_FOCUS); 126 | } 127 | /** 128 | * Validate brainstorm style 129 | */ 130 | export function validateBrainstormStyle(value) { 131 | validateEnum(value, 'style', BRAINSTORM_STYLES); 132 | } 133 | /** 134 | * Validate model ID 135 | */ 136 | export function validateModel(modelId) { 137 | if (!isModelSupported(modelId)) { 138 | 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`); 139 | } 140 | } 141 | /** 142 | * Validate temperature parameter 143 | */ 144 | export function validateTemperature(temperature) { 145 | validateNumber(temperature, 'temperature', 0, 2); 146 | } 147 | /** 148 | * Validate maxTokens parameter 149 | */ 150 | export function validateMaxTokens(maxTokens) { 151 | validateNumber(maxTokens, 'maxTokens', 1, 65536); 152 | } 153 | //# sourceMappingURL=validators.js.map -------------------------------------------------------------------------------- /src/utils/validators.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Parameter validation utilities 3 | */ 4 | 5 | import { 6 | FRAMEWORKS, 7 | ANIMATION_TECHNOLOGIES, 8 | UI_STYLES, 9 | OUTPUT_FORMATS, 10 | CONTENT_TYPES, 11 | ANALYSIS_TASKS, 12 | CODEBASE_FOCUS, 13 | BRAINSTORM_STYLES 14 | } from '../config/constants.js'; 15 | import { isModelSupported } from '../config/models.js'; 16 | 17 | /** 18 | * Validate required parameter 19 | */ 20 | export function validateRequired(value: any, fieldName: string): void { 21 | if (value === undefined || value === null || value === '') { 22 | throw new Error(`${fieldName} is required`); 23 | } 24 | } 25 | 26 | /** 27 | * Validate string 28 | */ 29 | export function validateString(value: any, fieldName: string, minLength = 1): void { 30 | if (typeof value !== 'string') { 31 | throw new Error(`${fieldName} must be a string`); 32 | } 33 | if (value.length < minLength) { 34 | throw new Error(`${fieldName} must be at least ${minLength} characters long`); 35 | } 36 | } 37 | 38 | /** 39 | * Validate number 40 | */ 41 | export function validateNumber(value: any, fieldName: string, min?: number, max?: number): void { 42 | if (typeof value !== 'number' || isNaN(value)) { 43 | throw new Error(`${fieldName} must be a number`); 44 | } 45 | if (min !== undefined && value < min) { 46 | throw new Error(`${fieldName} must be at least ${min}`); 47 | } 48 | if (max !== undefined && value > max) { 49 | throw new Error(`${fieldName} must be at most ${max}`); 50 | } 51 | } 52 | 53 | /** 54 | * Validate boolean 55 | */ 56 | export function validateBoolean(value: any, fieldName: string): void { 57 | if (typeof value !== 'boolean') { 58 | throw new Error(`${fieldName} must be a boolean`); 59 | } 60 | } 61 | 62 | /** 63 | * Validate enum value 64 | */ 65 | export function validateEnum( 66 | value: any, 67 | fieldName: string, 68 | allowedValues: T 69 | ): void { 70 | if (!allowedValues.includes(value)) { 71 | throw new Error( 72 | `${fieldName} must be one of: ${allowedValues.join(', ')}. Got: ${value}` 73 | ); 74 | } 75 | } 76 | 77 | /** 78 | * Validate array 79 | */ 80 | export function validateArray(value: any, fieldName: string, minLength = 1): void { 81 | if (!Array.isArray(value)) { 82 | throw new Error(`${fieldName} must be an array`); 83 | } 84 | if (value.length < minLength) { 85 | throw new Error(`${fieldName} must have at least ${minLength} item(s)`); 86 | } 87 | } 88 | 89 | /** 90 | * Validate Base64 image 91 | */ 92 | export function validateBase64Image(value: string, fieldName: string): void { 93 | if (!value.startsWith('data:image/')) { 94 | throw new Error(`${fieldName} must be a Base64 encoded image (data:image/...)`); 95 | } 96 | } 97 | 98 | /** 99 | * Validate URL 100 | */ 101 | export function validateURL(value: string, fieldName: string): void { 102 | try { 103 | new URL(value); 104 | } catch { 105 | throw new Error(`${fieldName} must be a valid URL`); 106 | } 107 | } 108 | 109 | /** 110 | * Validate framework 111 | */ 112 | export function validateFramework(value: string): void { 113 | validateEnum(value, 'framework', FRAMEWORKS); 114 | } 115 | 116 | /** 117 | * Validate animation technology 118 | */ 119 | export function validateAnimationTechnology(value: string): void { 120 | validateEnum(value, 'technology', ANIMATION_TECHNOLOGIES); 121 | } 122 | 123 | /** 124 | * Validate UI style 125 | */ 126 | export function validateUIStyle(value: string): void { 127 | validateEnum(value, 'style', UI_STYLES); 128 | } 129 | 130 | /** 131 | * Validate output format 132 | */ 133 | export function validateOutputFormat(value: string): void { 134 | validateEnum(value, 'outputFormat', OUTPUT_FORMATS); 135 | } 136 | 137 | /** 138 | * Validate content type 139 | */ 140 | export function validateContentType(value: string): void { 141 | validateEnum(value, 'type', CONTENT_TYPES); 142 | } 143 | 144 | /** 145 | * Validate analysis task 146 | */ 147 | export function validateAnalysisTask(value: string): void { 148 | validateEnum(value, 'task', ANALYSIS_TASKS); 149 | } 150 | 151 | /** 152 | * Validate codebase focus 153 | */ 154 | export function validateCodebaseFocus(value: string): void { 155 | validateEnum(value, 'focus', CODEBASE_FOCUS); 156 | } 157 | 158 | /** 159 | * Validate brainstorm style 160 | */ 161 | export function validateBrainstormStyle(value: string): void { 162 | validateEnum(value, 'style', BRAINSTORM_STYLES); 163 | } 164 | 165 | /** 166 | * Validate model ID 167 | */ 168 | export function validateModel(modelId: string): void { 169 | if (!isModelSupported(modelId)) { 170 | throw new Error( 171 | `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` 172 | ); 173 | } 174 | } 175 | 176 | /** 177 | * Validate temperature parameter 178 | */ 179 | export function validateTemperature(temperature: number): void { 180 | validateNumber(temperature, 'temperature', 0, 2); 181 | } 182 | 183 | /** 184 | * Validate maxTokens parameter 185 | */ 186 | export function validateMaxTokens(maxTokens: number): void { 187 | validateNumber(maxTokens, 'maxTokens', 1, 65536); 188 | } 189 | -------------------------------------------------------------------------------- /dist/windows-utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Windows 平台特定工具函数 3 | * Windows-specific utility functions 4 | */ 5 | import * as path from 'path'; 6 | import * as fs from 'fs'; 7 | /** 8 | * 标准化 Windows 路径 9 | * - 将正斜杠转换为反斜杠 10 | * - 处理 UNC 路径 11 | * - 移除多余的分隔符 12 | * @param filePath 原始路径 13 | * @returns 标准化的 Windows 路径 14 | */ 15 | export function normalizeWindowsPath(filePath) { 16 | if (!filePath) 17 | return filePath; 18 | // 使用 Node.js 内置方法标准化路径 19 | let normalized = path.normalize(filePath); 20 | // 确保盘符大写 (C: 而不是 c:) 21 | if (normalized.length >= 2 && normalized[1] === ':') { 22 | normalized = normalized[0].toUpperCase() + normalized.slice(1); 23 | } 24 | return normalized; 25 | } 26 | /** 27 | * 安全地拼接路径 28 | * 使用 path.join() 确保跨平台兼容 29 | * @param paths 路径片段 30 | * @returns 拼接后的路径 31 | */ 32 | export function joinPath(...paths) { 33 | return path.join(...paths); 34 | } 35 | /** 36 | * 获取绝对路径 37 | * @param relativePath 相对路径 38 | * @param basePath 基础路径(可选) 39 | * @returns 绝对路径 40 | */ 41 | export function getAbsolutePath(relativePath, basePath) { 42 | if (path.isAbsolute(relativePath)) { 43 | return normalizeWindowsPath(relativePath); 44 | } 45 | const base = basePath || process.cwd(); 46 | return normalizeWindowsPath(path.resolve(base, relativePath)); 47 | } 48 | /** 49 | * 检查文件是否存在(支持中文路径) 50 | * @param filePath 文件路径 51 | * @returns 文件是否存在 52 | */ 53 | export function fileExists(filePath) { 54 | try { 55 | const normalized = normalizeWindowsPath(filePath); 56 | return fs.existsSync(normalized); 57 | } 58 | catch (error) { 59 | return false; 60 | } 61 | } 62 | /** 63 | * 安全地读取文件(支持中文路径和自动编码检测) 64 | * @param filePath 文件路径 65 | * @param encoding 编码格式,默认 utf-8 66 | * @returns 文件内容 67 | */ 68 | export function readFileSafe(filePath, encoding = 'utf-8') { 69 | const normalized = normalizeWindowsPath(filePath); 70 | if (!fileExists(normalized)) { 71 | throw new Error(`文件不存在: ${normalized}`); 72 | } 73 | try { 74 | return fs.readFileSync(normalized, encoding); 75 | } 76 | catch (error) { 77 | if (error.code === 'EACCES') { 78 | throw new Error(`没有权限读取文件: ${normalized}`); 79 | } 80 | throw new Error(`读取文件失败: ${error.message}`); 81 | } 82 | } 83 | /** 84 | * 安全地写入文件(支持中文路径) 85 | * @param filePath 文件路径 86 | * @param content 文件内容 87 | * @param encoding 编码格式,默认 utf-8 88 | */ 89 | export function writeFileSafe(filePath, content, encoding = 'utf-8') { 90 | const normalized = normalizeWindowsPath(filePath); 91 | // 确保目录存在 92 | const dir = path.dirname(normalized); 93 | if (!fs.existsSync(dir)) { 94 | fs.mkdirSync(dir, { recursive: true }); 95 | } 96 | try { 97 | // Windows 下使用 CRLF 换行符 98 | const contentWithCRLF = content.replace(/\n/g, '\r\n'); 99 | fs.writeFileSync(normalized, contentWithCRLF, encoding); 100 | } 101 | catch (error) { 102 | if (error.code === 'EACCES') { 103 | throw new Error(`没有权限写入文件: ${normalized}`); 104 | } 105 | throw new Error(`写入文件失败: ${error.message}`); 106 | } 107 | } 108 | /** 109 | * 检测路径是否包含中文字符 110 | * @param filePath 文件路径 111 | * @returns 是否包含中文 112 | */ 113 | export function hasChineseChars(filePath) { 114 | return /[\u4e00-\u9fa5]/.test(filePath); 115 | } 116 | /** 117 | * 将 WSL/Git Bash 路径转换为 Windows 路径 118 | * 例如: /c/Users/... -> C:\Users\... 119 | * @param posixPath POSIX 风格路径 120 | * @returns Windows 路径 121 | */ 122 | export function convertPosixToWindows(posixPath) { 123 | if (!posixPath.startsWith('/')) { 124 | return normalizeWindowsPath(posixPath); 125 | } 126 | // 处理 /c/Users/... 格式 127 | const match = posixPath.match(/^\/([a-z])\/(.*)/i); 128 | if (match) { 129 | const drive = match[1].toUpperCase(); 130 | const rest = match[2].replace(/\//g, '\\'); 131 | return `${drive}:\\${rest}`; 132 | } 133 | // 其他情况直接标准化 134 | return normalizeWindowsPath(posixPath); 135 | } 136 | /** 137 | * 将 Windows 路径转换为 POSIX 路径(用于某些命令行工具) 138 | * 例如: C:\Users\... -> /c/Users/... 139 | * @param windowsPath Windows 路径 140 | * @returns POSIX 风格路径 141 | */ 142 | export function convertWindowsToPosix(windowsPath) { 143 | const normalized = normalizeWindowsPath(windowsPath); 144 | // 处理盘符 145 | if (normalized.length >= 2 && normalized[1] === ':') { 146 | const drive = normalized[0].toLowerCase(); 147 | const rest = normalized.slice(2).replace(/\\/g, '/'); 148 | return `/${drive}${rest}`; 149 | } 150 | return normalized.replace(/\\/g, '/'); 151 | } 152 | /** 153 | * 获取用户主目录 154 | * @returns 用户主目录路径 155 | */ 156 | export function getHomeDir() { 157 | const homeDir = process.env.USERPROFILE || process.env.HOME || ''; 158 | return normalizeWindowsPath(homeDir); 159 | } 160 | /** 161 | * 检查是否在 Windows 平台 162 | * @returns 是否为 Windows 163 | */ 164 | export function isWindows() { 165 | return process.platform === 'win32'; 166 | } 167 | /** 168 | * 获取临时目录 169 | * @returns 临时目录路径 170 | */ 171 | export function getTempDir() { 172 | const tmpDir = process.env.TEMP || process.env.TMP || path.join(getHomeDir(), 'AppData', 'Local', 'Temp'); 173 | return normalizeWindowsPath(tmpDir); 174 | } 175 | //# sourceMappingURL=windows-utils.js.map -------------------------------------------------------------------------------- /dist/tools/brainstorm.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"brainstorm.js","sourceRoot":"","sources":["../../src/tools/brainstorm.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/tools/create-animation.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Tool 4: gemini_create_animation 3 | * Create interactive animations using CSS, Canvas, WebGL, or Three.js 4 | * Priority: P0 - Core functionality 5 | */ 6 | import { validateRequired, validateString, validateAnimationTechnology, validateNumber } from '../utils/validators.js'; 7 | import { handleAPIError, logError } from '../utils/error-handler.js'; 8 | // System prompt for animation creation 9 | const ANIMATION_SYSTEM_PROMPT = `You are a creative coding expert specializing in interactive animations. 10 | 11 | Your expertise: 12 | - CSS animations and transitions (keyframes, timing functions) 13 | - Canvas 2D API (particles, effects, games) 14 | - WebGL and shaders (3D graphics, visual effects) 15 | - Three.js (3D scenes, materials, lighting) 16 | - Animation principles (easing, timing, motion design) 17 | 18 | Creation guidelines: 19 | 1. Performance: 20 | - Use requestAnimationFrame for smooth 60fps 21 | - Optimize rendering (only draw what changes) 22 | - Use hardware acceleration when possible 23 | - Implement proper cleanup (event listeners, timers) 24 | 25 | 2. Interactivity: 26 | - Respond to mouse/touch events 27 | - Add keyboard controls when relevant 28 | - Provide smooth, natural interactions 29 | - Handle edge cases (window resize, visibility) 30 | 31 | 3. Code quality: 32 | - Well-structured and modular 33 | - Configurable parameters 34 | - Clear comments explaining logic 35 | - Self-contained (minimal dependencies) 36 | 37 | 4. Visual quality: 38 | - Smooth, polished animations 39 | - Appropriate easing functions 40 | - Consistent style and feel 41 | - Attention to detail 42 | 43 | Output format: 44 | - Complete, working code 45 | - Embedded in HTML with inline scripts 46 | - Includes all necessary setup and initialization 47 | - Ready to copy-paste and run`; 48 | /** 49 | * Handle gemini_create_animation tool call 50 | */ 51 | export async function handleCreateAnimation(params, client) { 52 | try { 53 | // Validate required parameters 54 | validateRequired(params.description, 'description'); 55 | validateString(params.description, 'description', 10); 56 | // Validate optional parameters 57 | const technology = params.technology || 'canvas'; 58 | const interactive = params.interactive !== false; // default true 59 | const fps = params.fps || 60; 60 | if (params.technology) { 61 | validateAnimationTechnology(params.technology); 62 | } 63 | if (params.fps) { 64 | validateNumber(params.fps, 'fps', 1, 120); 65 | } 66 | // Build the prompt 67 | let prompt = `Create an interactive animation using ${technology} based on this description:\n\n`; 68 | prompt += `${params.description}\n\n`; 69 | prompt += `Requirements:\n`; 70 | prompt += `- Technology: ${technology}\n`; 71 | prompt += `- Interactive: ${interactive ? 'Yes (respond to mouse/touch)' : 'No'}\n`; 72 | prompt += `- Target FPS: ${fps}\n`; 73 | if (params.dimensions) { 74 | prompt += `- Canvas Size: ${params.dimensions.width}x${params.dimensions.height}px\n`; 75 | } 76 | prompt += `\n`; 77 | if (technology === 'css') { 78 | prompt += `Provide a complete HTML file with CSS animations using keyframes.\n`; 79 | } 80 | else if (technology === 'canvas') { 81 | prompt += `Provide a complete HTML file with Canvas 2D animation.\n`; 82 | } 83 | else if (technology === 'webgl') { 84 | prompt += `Provide a complete HTML file with WebGL shader animation.\n`; 85 | } 86 | else if (technology === 'threejs') { 87 | prompt += `Provide a complete HTML file with Three.js 3D animation.\n`; 88 | prompt += `Include Three.js from CDN: https://cdn.jsdelivr.net/npm/three@latest/build/three.module.js\n`; 89 | } 90 | prompt += `\nReturn ONLY the complete HTML code, no explanations.`; 91 | // Call Gemini API 92 | const code = await client.generate(prompt, { 93 | systemInstruction: ANIMATION_SYSTEM_PROMPT, 94 | temperature: 0.8, // Higher temperature for more creative animations 95 | maxTokens: 8192 96 | }); 97 | // Clean up code 98 | const cleanedCode = cleanCodeOutput(code); 99 | // Extract dependencies 100 | const dependencies = extractDependencies(cleanedCode, technology); 101 | return { 102 | code: cleanedCode, 103 | technology, 104 | preview: cleanedCode, 105 | dependencies, 106 | usage: `Open this HTML file in a modern web browser to see the animation. ${interactive ? 'Use mouse/touch to interact.' : ''}` 107 | }; 108 | } 109 | catch (error) { 110 | logError('createAnimation', error); 111 | throw handleAPIError(error); 112 | } 113 | } 114 | /** 115 | * Clean code output (remove markdown code blocks) 116 | */ 117 | function cleanCodeOutput(code) { 118 | code = code.replace(/```[a-z]*\n/g, ''); 119 | code = code.replace(/```\n?/g, ''); 120 | return code.trim(); 121 | } 122 | /** 123 | * Extract dependencies from code 124 | */ 125 | function extractDependencies(code, technology) { 126 | const deps = []; 127 | if (technology === 'threejs') { 128 | deps.push('three.js (from CDN)'); 129 | } 130 | // Check for other common libraries 131 | if (code.includes('gsap')) { 132 | deps.push('GSAP'); 133 | } 134 | if (code.includes('anime.js') || code.includes('anime(')) { 135 | deps.push('anime.js'); 136 | } 137 | return deps; 138 | } 139 | //# sourceMappingURL=create-animation.js.map -------------------------------------------------------------------------------- /dist/config/models.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Gemini model configuration 3 | * Based on official documentation: https://ai.google.dev/gemini-api/docs/models 4 | * Last updated: November 2025 5 | */ 6 | /** 7 | * Supported Gemini model list 8 | * Curated 4 models focused on UI generation and frontend development 9 | */ 10 | export const SUPPORTED_MODELS = { 11 | 'gemini-3-pro-preview': { 12 | id: 'gemini-3-pro-preview', 13 | name: 'Gemini 3.0 Pro Preview', 14 | description: 'Latest and most powerful model, #1 on WebDev Arena for UI generation', 15 | contextWindow: 1_048_576, // 1M tokens 16 | outputLimit: 65_536, 17 | capabilities: { 18 | maxInputTokens: 1_048_576, 19 | maxOutputTokens: 65_536, 20 | supportsVision: true, 21 | supportsFunctionCalling: true, 22 | supportsStreaming: true, 23 | supportsThinking: true, 24 | supportsSystemInstructions: true 25 | }, 26 | features: ['thinking', 'multimodal', 'function_calling', 'grounding', 'system_instructions'], 27 | bestFor: ['UI generation', 'Frontend development', 'Design to code', 'Interactive animations', 'Complex reasoning'], 28 | useCases: ['UI generation', 'Frontend development', 'Design to code', 'Interactive animations', 'Complex reasoning'], 29 | thinking: true, 30 | lastUpdate: 'November 2025', 31 | isDefault: true 32 | }, 33 | 'gemini-2.5-pro': { 34 | id: 'gemini-2.5-pro', 35 | name: 'Gemini 2.5 Pro', 36 | description: 'Stable production model with excellent coding capabilities', 37 | contextWindow: 1_048_576, // 1M tokens 38 | outputLimit: 65_536, 39 | capabilities: { 40 | maxInputTokens: 1_048_576, 41 | maxOutputTokens: 65_536, 42 | supportsVision: true, 43 | supportsFunctionCalling: true, 44 | supportsStreaming: true, 45 | supportsThinking: true, 46 | supportsSystemInstructions: true 47 | }, 48 | features: ['thinking', 'multimodal', 'function_calling', 'grounding', 'system_instructions'], 49 | bestFor: ['General coding', 'Large codebase analysis', 'Fallback option'], 50 | useCases: ['General coding', 'Large codebase analysis', 'Code review', 'Documentation generation'], 51 | thinking: true, 52 | lastUpdate: 'June 2025', 53 | isDefault: false 54 | }, 55 | 'gemini-2.5-flash': { 56 | id: 'gemini-2.5-flash', 57 | name: 'Gemini 2.5 Flash', 58 | description: 'Fast and cost-effective model with best price/performance ratio', 59 | contextWindow: 1_048_576, // 1M tokens 60 | outputLimit: 65_536, 61 | capabilities: { 62 | maxInputTokens: 1_048_576, 63 | maxOutputTokens: 65_536, 64 | supportsVision: true, 65 | supportsFunctionCalling: true, 66 | supportsStreaming: true, 67 | supportsThinking: true, 68 | supportsSystemInstructions: true 69 | }, 70 | features: ['thinking', 'multimodal', 'function_calling', 'grounding', 'system_instructions'], 71 | bestFor: ['High-frequency tasks', 'Batch processing', 'Cost optimization'], 72 | useCases: ['Quick Q&A', 'Real-time analysis', 'Batch processing', 'Cost optimization'], 73 | thinking: true, 74 | lastUpdate: 'June 2025', 75 | isDefault: false 76 | }, 77 | 'gemini-2.5-flash-lite': { 78 | id: 'gemini-2.5-flash-lite', 79 | name: 'Gemini 2.5 Flash Lite', 80 | description: 'Ultra-fast and most cost-efficient model for simple tasks', 81 | contextWindow: 1_048_576, // 1M tokens 82 | outputLimit: 65_536, 83 | capabilities: { 84 | maxInputTokens: 1_048_576, 85 | maxOutputTokens: 65_536, 86 | supportsVision: true, 87 | supportsFunctionCalling: true, 88 | supportsStreaming: true, 89 | supportsThinking: true, 90 | supportsSystemInstructions: true 91 | }, 92 | features: ['thinking', 'multimodal', 'function_calling', 'system_instructions'], 93 | bestFor: ['Simple queries', 'Quick prototypes', 'Maximum cost savings'], 94 | useCases: ['Simple queries', 'Quick validation', 'Low latency scenarios', 'Maximum cost savings'], 95 | thinking: true, 96 | lastUpdate: 'July 2025', 97 | isDefault: false 98 | } 99 | }; 100 | /** 101 | * Get default model 102 | */ 103 | export function getDefaultModel() { 104 | return SUPPORTED_MODELS['gemini-3-pro-preview']; 105 | } 106 | /** 107 | * Get model configuration 108 | * @param modelId - Model ID 109 | * @returns Model configuration, returns default model if not found 110 | */ 111 | export function getModelConfig(modelId) { 112 | if (!modelId) { 113 | return getDefaultModel(); 114 | } 115 | return SUPPORTED_MODELS[modelId] || getDefaultModel(); 116 | } 117 | /** 118 | * Validate if model is supported 119 | * @param modelId - Model ID 120 | * @returns Whether the model is supported 121 | */ 122 | export function isModelSupported(modelId) { 123 | return modelId in SUPPORTED_MODELS; 124 | } 125 | /** 126 | * Get all supported models list 127 | */ 128 | export function getAllModels() { 129 | return Object.values(SUPPORTED_MODELS); 130 | } 131 | /** 132 | * Model selection recommendations 133 | */ 134 | export const MODEL_RECOMMENDATIONS = { 135 | ui_generation: 'gemini-3-pro-preview', 136 | animation: 'gemini-3-pro-preview', 137 | multimodal: 'gemini-3-pro-preview', 138 | codebase_analysis: 'gemini-2.5-pro', 139 | batch_processing: 'gemini-2.5-flash', 140 | simple_tasks: 'gemini-2.5-flash-lite', 141 | fallback: 'gemini-2.5-pro' 142 | }; 143 | //# sourceMappingURL=models.js.map -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 | 8 | ## [1.1.0] - 2025-11-26 9 | 10 | ### 🚀 File System Access & Tool Enhancement 11 | 12 | This version adds direct file system access to tools, eliminating the need to pass file contents as parameters. 13 | 14 | ### Added 15 | 16 | - **File System Access Module** (`src/utils/file-reader.ts`): 17 | - `readFile()` - Read single file with language detection 18 | - `readFiles()` - Batch read multiple files 19 | - `readDirectory()` - Read entire directory with glob filtering 20 | - Automatic binary file detection and exclusion 21 | 22 | - **Security Module** (`src/utils/security.ts`): 23 | - Path traversal attack prevention using `path.relative` 24 | - Sensitive file protection (`.env`, `.ssh`, credentials, etc.) 25 | - Directory whitelist validation 26 | - Symlink detection 27 | - File size and count limits 28 | 29 | - **New Tool Parameters**: 30 | - `analyze_codebase`: `directory`, `filePaths`, `include`, `exclude` 31 | - `analyze_content`: `filePath` with auto language detection 32 | - `generate_ui`: `techContext`, `configPath` for tech stack context 33 | - `fix_ui_from_screenshot`: `sourceCodePath`, `relatedFiles` 34 | - `brainstorm`: `contextFilePath`, `contextFiles` for project context 35 | 36 | - **Structured Model Information** in `list_models`: 37 | - `capabilities`: Detailed capability flags (vision, function calling, etc.) 38 | - `useCases`: Recommended use cases in Chinese 39 | - `recommendations`: Model recommendations by scenario 40 | 41 | ### Changed 42 | 43 | - **Security Improvements**: 44 | - Fixed directory whitelist bypass vulnerability (prefix matching issue) 45 | - Fixed path traversal detection to allow legitimate filenames like `vendor..lib.js` 46 | - Using `path.relative` for safer path validation 47 | 48 | - All tools maintain **backward compatibility** with existing parameters 49 | 50 | ### Dependencies 51 | 52 | - Added `micromatch` for glob pattern matching 53 | - Added `fast-glob` for directory traversal 54 | 55 | --- 56 | 57 | ## [1.0.1] - 2025-11-26 58 | 59 | ### 🎉 Major Rewrite - LKbaba Specialized Version 60 | 61 | This version is a complete rewrite focused on **UI generation and frontend development**, designed to complement Claude Code. 62 | 63 | ### Added 64 | 65 | - **8 Specialized Tools**: 66 | - `gemini_generate_ui` - Generate UI components from description or design images 67 | - `gemini_multimodal_query` - Analyze images with natural language queries 68 | - `gemini_fix_ui_from_screenshot` - Diagnose and fix UI issues from screenshots 69 | - `gemini_create_animation` - Create interactive animations (CSS/Canvas/WebGL/Three.js) 70 | - `gemini_analyze_content` - Analyze code, documents, or data 71 | - `gemini_analyze_codebase` - Analyze entire codebase using 1M token context 72 | - `gemini_brainstorm` - Generate creative ideas with feasibility assessment 73 | - `list_models` - List available Gemini models 74 | 75 | - **4 Supported Models**: 76 | - `gemini-3-pro-preview` (default) - Latest and most powerful for UI generation 77 | - `gemini-2.5-pro` - Stable fallback option 78 | - `gemini-2.5-flash` - Cost-effective for high-frequency tasks 79 | - `gemini-2.5-flash-lite` - Maximum cost savings 80 | 81 | - **Proxy Support** - Automatic proxy configuration for users behind VPN/proxy 82 | - **File Path Support** - Image tools now accept file paths, automatically converted to Base64 83 | - **Modular Architecture** - Clean separation of concerns with tools, utils, and config directories 84 | 85 | ### Changed 86 | 87 | - Complete project restructure for better maintainability 88 | - Updated to Gemini 3.0 Pro as default model 89 | - Simplified from 6 generic tools to 8 specialized tools 90 | - Improved error handling and validation 91 | - Enhanced system prompts for better output quality 92 | 93 | ### Removed 94 | 95 | - Legacy WebSocket implementation 96 | - Generic text generation tool (replaced with specialized tools) 97 | - Token counting tool (not needed for this use case) 98 | - Embedding tool (not relevant for UI generation) 99 | - Help system (simplified documentation) 100 | 101 | --- 102 | 103 | ## Previous Versions (Original Project) 104 | 105 | The following versions are from the original [aliargun/mcp-server-gemini](https://github.com/aliargun/mcp-server-gemini) project. 106 | 107 | ## [4.2.2] - 2025-07-08 108 | 109 | ### Fixed 110 | - Fixed image truncation issue by adding crlfDelay: Infinity to readline interface 111 | - Added proper UTF-8 encoding for stdin to handle large Base64 data 112 | 113 | ## [4.2.1] - 2025-07-08 114 | 115 | ### Fixed 116 | - Fixed conversation context role validation error 117 | 118 | ## [4.2.0] - 2025-07-08 119 | 120 | ### Changed 121 | - Cleaned up repository by removing legacy WebSocket implementation files 122 | 123 | ### Security 124 | - Performed comprehensive security audit 125 | 126 | ## [4.1.0] - 2025-07-07 127 | 128 | ### Added 129 | - Self-documenting `get_help` tool 130 | - MCP resources for documentation access 131 | 132 | ## [4.0.0] - 2025-07-07 133 | 134 | ### Added 135 | - Support for Gemini 2.5 series with thinking capabilities 136 | - 5 powerful tools: generate_text, analyze_image, count_tokens, list_models, embed_text 137 | - JSON mode, Google Search grounding, system instructions 138 | 139 | ### Changed 140 | - Complete rewrite to use stdio-based MCP protocol 141 | 142 | ## [3.0.0] - 2025-07-07 143 | 144 | ### Changed 145 | - Migrated from WebSocket to stdio-based communication 146 | 147 | ## [2.0.0] - 2025-07-07 148 | 149 | ### Changed 150 | - Updated from deprecated @google/generative-ai to @google/genai SDK 151 | 152 | ## [1.0.0] - 2024-12-15 153 | 154 | ### Added 155 | - Initial release with WebSocket-based MCP server 156 | -------------------------------------------------------------------------------- /dist/utils/security.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"security.js","sourceRoot":"","sources":["../../src/utils/security.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /src/tools/create-animation.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Tool 4: gemini_create_animation 3 | * Create interactive animations using CSS, Canvas, WebGL, or Three.js 4 | * Priority: P0 - Core functionality 5 | */ 6 | 7 | import { GeminiClient } from '../utils/gemini-client.js'; 8 | import { 9 | validateRequired, 10 | validateString, 11 | validateAnimationTechnology, 12 | validateNumber 13 | } from '../utils/validators.js'; 14 | import { handleAPIError, logError } from '../utils/error-handler.js'; 15 | 16 | // System prompt for animation creation 17 | const ANIMATION_SYSTEM_PROMPT = `You are a creative coding expert specializing in interactive animations. 18 | 19 | Your expertise: 20 | - CSS animations and transitions (keyframes, timing functions) 21 | - Canvas 2D API (particles, effects, games) 22 | - WebGL and shaders (3D graphics, visual effects) 23 | - Three.js (3D scenes, materials, lighting) 24 | - Animation principles (easing, timing, motion design) 25 | 26 | Creation guidelines: 27 | 1. Performance: 28 | - Use requestAnimationFrame for smooth 60fps 29 | - Optimize rendering (only draw what changes) 30 | - Use hardware acceleration when possible 31 | - Implement proper cleanup (event listeners, timers) 32 | 33 | 2. Interactivity: 34 | - Respond to mouse/touch events 35 | - Add keyboard controls when relevant 36 | - Provide smooth, natural interactions 37 | - Handle edge cases (window resize, visibility) 38 | 39 | 3. Code quality: 40 | - Well-structured and modular 41 | - Configurable parameters 42 | - Clear comments explaining logic 43 | - Self-contained (minimal dependencies) 44 | 45 | 4. Visual quality: 46 | - Smooth, polished animations 47 | - Appropriate easing functions 48 | - Consistent style and feel 49 | - Attention to detail 50 | 51 | Output format: 52 | - Complete, working code 53 | - Embedded in HTML with inline scripts 54 | - Includes all necessary setup and initialization 55 | - Ready to copy-paste and run`; 56 | 57 | export interface CreateAnimationParams { 58 | description: string; 59 | technology?: 'css' | 'canvas' | 'webgl' | 'threejs'; 60 | interactive?: boolean; 61 | fps?: number; 62 | dimensions?: { 63 | width: number; 64 | height: number; 65 | }; 66 | } 67 | 68 | export interface CreateAnimationResult { 69 | code: string; 70 | technology: string; 71 | preview?: string; 72 | dependencies?: string[]; 73 | usage: string; 74 | } 75 | 76 | /** 77 | * Handle gemini_create_animation tool call 78 | */ 79 | export async function handleCreateAnimation( 80 | params: CreateAnimationParams, 81 | client: GeminiClient 82 | ): Promise { 83 | try { 84 | // Validate required parameters 85 | validateRequired(params.description, 'description'); 86 | validateString(params.description, 'description', 10); 87 | 88 | // Validate optional parameters 89 | const technology = params.technology || 'canvas'; 90 | const interactive = params.interactive !== false; // default true 91 | const fps = params.fps || 60; 92 | 93 | if (params.technology) { 94 | validateAnimationTechnology(params.technology); 95 | } 96 | if (params.fps) { 97 | validateNumber(params.fps, 'fps', 1, 120); 98 | } 99 | 100 | // Build the prompt 101 | let prompt = `Create an interactive animation using ${technology} based on this description:\n\n`; 102 | prompt += `${params.description}\n\n`; 103 | 104 | prompt += `Requirements:\n`; 105 | prompt += `- Technology: ${technology}\n`; 106 | prompt += `- Interactive: ${interactive ? 'Yes (respond to mouse/touch)' : 'No'}\n`; 107 | prompt += `- Target FPS: ${fps}\n`; 108 | 109 | if (params.dimensions) { 110 | prompt += `- Canvas Size: ${params.dimensions.width}x${params.dimensions.height}px\n`; 111 | } 112 | 113 | prompt += `\n`; 114 | 115 | if (technology === 'css') { 116 | prompt += `Provide a complete HTML file with CSS animations using keyframes.\n`; 117 | } else if (technology === 'canvas') { 118 | prompt += `Provide a complete HTML file with Canvas 2D animation.\n`; 119 | } else if (technology === 'webgl') { 120 | prompt += `Provide a complete HTML file with WebGL shader animation.\n`; 121 | } else if (technology === 'threejs') { 122 | prompt += `Provide a complete HTML file with Three.js 3D animation.\n`; 123 | prompt += `Include Three.js from CDN: https://cdn.jsdelivr.net/npm/three@latest/build/three.module.js\n`; 124 | } 125 | 126 | prompt += `\nReturn ONLY the complete HTML code, no explanations.`; 127 | 128 | // Call Gemini API 129 | const code = await client.generate( 130 | prompt, 131 | { 132 | systemInstruction: ANIMATION_SYSTEM_PROMPT, 133 | temperature: 0.8, // Higher temperature for more creative animations 134 | maxTokens: 8192 135 | } 136 | ); 137 | 138 | // Clean up code 139 | const cleanedCode = cleanCodeOutput(code); 140 | 141 | // Extract dependencies 142 | const dependencies = extractDependencies(cleanedCode, technology); 143 | 144 | return { 145 | code: cleanedCode, 146 | technology, 147 | preview: cleanedCode, 148 | dependencies, 149 | usage: `Open this HTML file in a modern web browser to see the animation. ${interactive ? 'Use mouse/touch to interact.' : ''}` 150 | }; 151 | 152 | } catch (error: any) { 153 | logError('createAnimation', error); 154 | throw handleAPIError(error); 155 | } 156 | } 157 | 158 | /** 159 | * Clean code output (remove markdown code blocks) 160 | */ 161 | function cleanCodeOutput(code: string): string { 162 | code = code.replace(/```[a-z]*\n/g, ''); 163 | code = code.replace(/```\n?/g, ''); 164 | return code.trim(); 165 | } 166 | 167 | /** 168 | * Extract dependencies from code 169 | */ 170 | function extractDependencies(code: string, technology: string): string[] { 171 | const deps: string[] = []; 172 | 173 | if (technology === 'threejs') { 174 | deps.push('three.js (from CDN)'); 175 | } 176 | 177 | // Check for other common libraries 178 | if (code.includes('gsap')) { 179 | deps.push('GSAP'); 180 | } 181 | if (code.includes('anime.js') || code.includes('anime(')) { 182 | deps.push('anime.js'); 183 | } 184 | 185 | return deps; 186 | } 187 | -------------------------------------------------------------------------------- /dist/tools/definitions.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/tools/definitions.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAEpD;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,gCAAgC;IAChC;QACE,IAAI,EAAE,UAAU,CAAC,WAAW;QAC5B,WAAW,EAAE,wPAAwP;QACrQ,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,WAAW,EAAE;oBACX,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,6CAA6C;iBAC3D;gBACD,WAAW,EAAE;oBACX,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,2IAA2I;iBACzJ;gBACD,SAAS,EAAE;oBACT,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,CAAC,SAAS,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC;oBAC3C,WAAW,EAAE,qCAAqC;oBAClD,OAAO,EAAE,SAAS;iBACnB;gBACD,2BAA2B;gBAC3B,WAAW,EAAE;oBACX,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,YAAY,EAAE;4BACZ,IAAI,EAAE,QAAQ;4BACd,IAAI,EAAE,CAAC,UAAU,EAAE,WAAW,EAAE,mBAAmB,EAAE,aAAa,EAAE,SAAS,CAAC;4BAC9E,WAAW,EAAE,kCAAkC;yBAChD;wBACD,SAAS,EAAE;4BACT,IAAI,EAAE,QAAQ;4BACd,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC;4BAClD,WAAW,EAAE,6BAA6B;yBAC3C;wBACD,UAAU,EAAE;4BACV,IAAI,EAAE,SAAS;4BACf,WAAW,EAAE,2CAA2C;yBACzD;wBACD,eAAe,EAAE;4BACf,IAAI,EAAE,QAAQ;4BACd,IAAI,EAAE,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC;4BAC7C,WAAW,EAAE,oCAAoC;yBAClD;qBACF;oBACD,WAAW,EAAE,wEAAwE;iBACtF;gBACD,gCAAgC;gBAChC,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,uJAAuJ;iBACrK;gBACD,gBAAgB,EAAE;oBAChB,IAAI,EAAE,SAAS;oBACf,WAAW,EAAE,oDAAoD;oBACjE,OAAO,EAAE,IAAI;iBACd;gBACD,UAAU,EAAE;oBACV,IAAI,EAAE,SAAS;oBACf,WAAW,EAAE,wCAAwC;oBACrD,OAAO,EAAE,IAAI;iBACd;gBACD,KAAK,EAAE;oBACL,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,eAAe,EAAE,aAAa,CAAC;oBAC3D,WAAW,EAAE,mCAAmC;iBACjD;aACF;YACD,QAAQ,EAAE,CAAC,aAAa,CAAC;SAC1B;KACF;IAED,sCAAsC;IACtC;QACE,IAAI,EAAE,UAAU,CAAC,gBAAgB;QACjC,WAAW,EAAE,wJAAwJ;QACrK,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,MAAM,EAAE;oBACN,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,0CAA0C;iBACxD;gBACD,MAAM,EAAE;oBACN,IAAI,EAAE,OAAO;oBACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;oBACzB,WAAW,EAAE,iIAAiI;iBAC/I;gBACD,YAAY,EAAE;oBACZ,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;oBAC9B,WAAW,EAAE,uCAAuC;oBACpD,OAAO,EAAE,MAAM;iBAChB;gBACD,OAAO,EAAE;oBACP,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,uDAAuD;iBACrE;aACF;YACD,QAAQ,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC;SAC/B;KACF;IAED,2CAA2C;IAC3C;QACE,IAAI,EAAE,UAAU,CAAC,MAAM;QACvB,WAAW,EAAE,0MAA0M;QACvN,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,mJAAmJ;iBACjK;gBACD,8BAA8B;gBAC9B,cAAc,EAAE;oBACd,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,yIAAyI;iBACvJ;gBACD,mCAAmC;gBACnC,YAAY,EAAE;oBACZ,IAAI,EAAE,OAAO;oBACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;oBACzB,WAAW,EAAE,oIAAoI;iBAClJ;gBACD,4DAA4D;gBAC5D,WAAW,EAAE;oBACX,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,oGAAoG;iBAClH;gBACD,gBAAgB,EAAE;oBAChB,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,sCAAsC;iBACpD;gBACD,WAAW,EAAE;oBACX,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,yDAAyD;iBACvE;aACF;YACD,QAAQ,EAAE,CAAC,YAAY,CAAC;SACzB;KACF;IAED,oCAAoC;IACpC;QACE,IAAI,EAAE,UAAU,CAAC,gBAAgB;QACjC,WAAW,EAAE,+IAA+I;QAC5J,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,WAAW,EAAE;oBACX,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,sCAAsC;iBACpD;gBACD,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,CAAC;oBAC3C,WAAW,EAAE,wCAAwC;oBACrD,OAAO,EAAE,QAAQ;iBAClB;gBACD,WAAW,EAAE;oBACX,IAAI,EAAE,SAAS;oBACf,WAAW,EAAE,mDAAmD;oBAChE,OAAO,EAAE,IAAI;iBACd;gBACD,GAAG,EAAE;oBACH,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,wCAAwC;oBACrD,OAAO,EAAE,EAAE;iBACZ;gBACD,UAAU,EAAE;oBACV,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;wBACzB,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;qBAC3B;oBACD,WAAW,EAAE,6BAA6B;iBAC3C;aACF;YACD,QAAQ,EAAE,CAAC,aAAa,CAAC;SAC1B;KACF;IAED,oCAAoC;IACpC;QACE,IAAI,EAAE,UAAU,CAAC,eAAe;QAChC,WAAW,EAAE,kNAAkN;QAC/N,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,mEAAmE;gBACnE,OAAO,EAAE;oBACP,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,0DAA0D;iBACxE;gBACD,kCAAkC;gBAClC,QAAQ,EAAE;oBACR,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,wJAAwJ;iBACtK;gBACD,IAAI,EAAE;oBACJ,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,CAAC;oBAC1C,WAAW,EAAE,8BAA8B;oBAC3C,OAAO,EAAE,MAAM;iBAChB;gBACD,IAAI,EAAE;oBACJ,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,CAAC,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,CAAC;oBAC7D,WAAW,EAAE,oCAAoC;oBACjD,OAAO,EAAE,WAAW;iBACrB;gBACD,QAAQ,EAAE;oBACR,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,8EAA8E;iBAC5F;gBACD,KAAK,EAAE;oBACL,IAAI,EAAE,OAAO;oBACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;oBACzB,WAAW,EAAE,0EAA0E;iBACxF;gBACD,YAAY,EAAE;oBACZ,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC;oBAClC,WAAW,EAAE,mCAAmC;oBAChD,OAAO,EAAE,UAAU;iBACpB;aACF;YACD,QAAQ,EAAE,EAAE,CAAE,oEAAoE;SACnF;KACF;IAED,qCAAqC;IACrC;QACE,IAAI,EAAE,UAAU,CAAC,gBAAgB;QACjC,WAAW,EAAE,gOAAgO;QAC7O,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,iCAAiC;gBACjC,SAAS,EAAE;oBACT,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,4HAA4H;iBAC1I;gBACD,OAAO,EAAE;oBACP,IAAI,EAAE,OAAO;oBACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;oBACzB,WAAW,EAAE,qGAAqG;iBACnH;gBACD,OAAO,EAAE;oBACP,IAAI,EAAE,OAAO;oBACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;oBACzB,WAAW,EAAE,iHAAiH;iBAC/H;gBACD,qCAAqC;gBACrC,SAAS,EAAE;oBACT,IAAI,EAAE,OAAO;oBACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;oBACzB,WAAW,EAAE,kIAAkI;iBAChJ;gBACD,qEAAqE;gBACrE,KAAK,EAAE;oBACL,IAAI,EAAE,OAAO;oBACb,KAAK,EAAE;wBACL,IAAI,EAAE,QAAQ;wBACd,UAAU,EAAE;4BACV,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;4BACxB,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;yBAC5B;wBACD,QAAQ,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC;qBAC9B;oBACD,WAAW,EAAE,6GAA6G;iBAC3H;gBACD,KAAK,EAAE;oBACL,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,CAAC,cAAc,EAAE,UAAU,EAAE,aAAa,EAAE,cAAc,EAAE,UAAU,CAAC;oBAC7E,WAAW,EAAE,+BAA+B;iBAC7C;gBACD,SAAS,EAAE;oBACT,IAAI,EAAE,SAAS;oBACf,WAAW,EAAE,8DAA8D;oBAC3E,OAAO,EAAE,KAAK;iBACf;gBACD,YAAY,EAAE;oBACZ,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,CAAC,UAAU,EAAE,MAAM,CAAC;oBAC1B,WAAW,EAAE,mCAAmC;oBAChD,OAAO,EAAE,UAAU;iBACpB;aACF;YACD,QAAQ,EAAE,EAAE,CAAE,4EAA4E;SAC3F;KACF;IAED,+BAA+B;IAC/B;QACE,IAAI,EAAE,UAAU,CAAC,UAAU;QAC3B,WAAW,EAAE,2LAA2L;QACxM,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE;gBACV,KAAK,EAAE;oBACL,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,yBAAyB;iBACvC;gBACD,OAAO,EAAE;oBACP,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,8BAA8B;iBAC5C;gBACD,kCAAkC;gBAClC,eAAe,EAAE;oBACf,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,oGAAoG;iBAClH;gBACD,+BAA+B;gBAC/B,YAAY,EAAE;oBACZ,IAAI,EAAE,OAAO;oBACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;oBACzB,WAAW,EAAE,mFAAmF;iBACjG;gBACD,KAAK,EAAE;oBACL,IAAI,EAAE,QAAQ;oBACd,WAAW,EAAE,0CAA0C;oBACvD,OAAO,EAAE,CAAC;iBACX;gBACD,KAAK,EAAE;oBACL,IAAI,EAAE,QAAQ;oBACd,IAAI,EAAE,CAAC,YAAY,EAAE,WAAW,EAAE,SAAS,CAAC;oBAC5C,WAAW,EAAE,+BAA+B;iBAC7C;aACF;YACD,QAAQ,EAAE,CAAC,OAAO,CAAC;SACpB;KACF;IAED,yBAAyB;IACzB;QACE,IAAI,EAAE,UAAU,CAAC,WAAW;QAC5B,WAAW,EAAE,2FAA2F;QACxG,WAAW,EAAE;YACX,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE,EAAE;YACd,QAAQ,EAAE,EAAE;SACb;KACF;CACF,CAAC"} -------------------------------------------------------------------------------- /dist/server.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/tools/analyze-content.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"analyze-content.js","sourceRoot":"","sources":["../../src/tools/analyze-content.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /dist/utils/gemini-client.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Gemini API client wrapper 3 | * Provides unified API interface with error handling and retry logic 4 | */ 5 | import { GoogleGenAI } from '@google/genai'; 6 | import { API_CONFIG } from '../config/constants.js'; 7 | import * as fs from 'fs'; 8 | import * as path from 'path'; 9 | /** 10 | * Get MIME type based on file extension 11 | */ 12 | function getMimeType(ext) { 13 | const mimeTypes = { 14 | '.png': 'image/png', 15 | '.jpg': 'image/jpeg', 16 | '.jpeg': 'image/jpeg', 17 | '.gif': 'image/gif', 18 | '.webp': 'image/webp', 19 | '.bmp': 'image/bmp', 20 | '.svg': 'image/svg+xml', 21 | '.ico': 'image/x-icon' 22 | }; 23 | return mimeTypes[ext.toLowerCase()] || 'image/png'; 24 | } 25 | /** 26 | * Convert image to Base64 inline data format 27 | * Supports: file path, Base64 data URI 28 | */ 29 | function convertImageToInlineData(image) { 30 | // 1. Already in Base64 data URI format 31 | if (image.startsWith('data:')) { 32 | const [metadata, data] = image.split(','); 33 | const mimeType = metadata.match(/:(.*?);/)?.[1] || 'image/png'; 34 | return { mimeType, data }; 35 | } 36 | // 2. URL format - not supported 37 | if (image.startsWith('http://') || image.startsWith('https://')) { 38 | throw new Error(`URL images are not supported. Please provide a file path or Base64 data URI instead.`); 39 | } 40 | // 3. File path format - read file and convert to Base64 41 | try { 42 | // Check if file exists 43 | if (!fs.existsSync(image)) { 44 | throw new Error(`Image file not found: ${image}`); 45 | } 46 | // Read file and convert to Base64 47 | const fileBuffer = fs.readFileSync(image); 48 | const base64Data = fileBuffer.toString('base64'); 49 | // Get MIME type 50 | const ext = path.extname(image); 51 | const mimeType = getMimeType(ext); 52 | return { mimeType, data: base64Data }; 53 | } 54 | catch (error) { 55 | if (error.message.includes('Image file not found')) { 56 | throw error; 57 | } 58 | throw new Error(`Failed to read image file "${image}": ${error.message}`); 59 | } 60 | } 61 | export class GeminiClient { 62 | client; 63 | modelId; 64 | config; 65 | constructor(config) { 66 | this.client = new GoogleGenAI({ apiKey: config.apiKey }); 67 | this.modelId = config.model || 'gemini-3-pro-preview'; 68 | this.config = { 69 | apiKey: config.apiKey, 70 | model: this.modelId, 71 | timeout: config.timeout || API_CONFIG.timeout, 72 | maxRetries: config.maxRetries || API_CONFIG.maxRetries 73 | }; 74 | } 75 | /** 76 | * Generate content (text only) 77 | */ 78 | async generate(prompt, options = {}) { 79 | try { 80 | const requestBody = { 81 | model: this.modelId, 82 | contents: [{ 83 | role: 'user', 84 | parts: [{ text: prompt }] 85 | }], 86 | generationConfig: { 87 | temperature: options.temperature, 88 | maxOutputTokens: options.maxTokens, 89 | topP: options.topP, 90 | topK: options.topK 91 | } 92 | }; 93 | // Add system instruction (if provided) 94 | if (options.systemInstruction) { 95 | requestBody.systemInstruction = { 96 | parts: [{ text: options.systemInstruction }] 97 | }; 98 | } 99 | const result = await this.client.models.generateContent(requestBody); 100 | return result.text || ''; 101 | } 102 | catch (error) { 103 | throw this.handleError(error); 104 | } 105 | } 106 | /** 107 | * Generate content (multimodal: text + images) 108 | * Supported image formats: 109 | * - File path: e.g., "./images/screenshot.png" 110 | * - Base64 data URI: e.g., "data:image/png;base64,iVBORw0KGgo..." 111 | */ 112 | async generateMultimodal(prompt, images, options = {}) { 113 | try { 114 | // Build content: text + images 115 | const parts = [{ text: prompt }]; 116 | // Process each image (supports file path and Base64) 117 | for (const image of images) { 118 | const { mimeType, data } = convertImageToInlineData(image); 119 | parts.push({ 120 | inlineData: { 121 | mimeType, 122 | data 123 | } 124 | }); 125 | } 126 | const requestBody = { 127 | model: this.modelId, 128 | contents: [{ role: 'user', parts }], 129 | generationConfig: { 130 | temperature: options.temperature, 131 | maxOutputTokens: options.maxTokens, 132 | topP: options.topP, 133 | topK: options.topK 134 | } 135 | }; 136 | // Add system instruction (if provided) 137 | if (options.systemInstruction) { 138 | requestBody.systemInstruction = { 139 | parts: [{ text: options.systemInstruction }] 140 | }; 141 | } 142 | const result = await this.client.models.generateContent(requestBody); 143 | return result.text || ''; 144 | } 145 | catch (error) { 146 | throw this.handleError(error); 147 | } 148 | } 149 | /** 150 | * Switch model 151 | */ 152 | setModel(modelId) { 153 | this.modelId = modelId; 154 | this.config.model = modelId; 155 | } 156 | /** 157 | * Get current model 158 | */ 159 | getModel() { 160 | return this.modelId; 161 | } 162 | /** 163 | * Error handling 164 | */ 165 | handleError(error) { 166 | if (error.message?.includes('API key')) { 167 | return new Error('Invalid API key'); 168 | } 169 | if (error.message?.includes('quota')) { 170 | return new Error('API quota exceeded'); 171 | } 172 | if (error.message?.includes('timeout')) { 173 | return new Error('Request timeout'); 174 | } 175 | return new Error(error.message || 'Unknown error'); 176 | } 177 | } 178 | /** 179 | * Create Gemini client instance 180 | */ 181 | export function createGeminiClient(apiKey, model) { 182 | return new GeminiClient({ apiKey, model }); 183 | } 184 | //# sourceMappingURL=gemini-client.js.map -------------------------------------------------------------------------------- /dist/tools/generate-ui.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"generate-ui.js","sourceRoot":"","sources":["../../src/tools/generate-ui.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /src/utils/gemini-client.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Gemini API client wrapper 3 | * Provides unified API interface with error handling and retry logic 4 | */ 5 | 6 | import { GoogleGenAI } from '@google/genai'; 7 | import { getModelConfig } from '../config/models.js'; 8 | import { API_CONFIG, ERROR_CODES } from '../config/constants.js'; 9 | import * as fs from 'fs'; 10 | import * as path from 'path'; 11 | 12 | export interface GeminiClientConfig { 13 | apiKey: string; 14 | model?: string; 15 | timeout?: number; 16 | maxRetries?: number; 17 | } 18 | 19 | export interface GenerateOptions { 20 | temperature?: number; 21 | maxTokens?: number; 22 | topP?: number; 23 | topK?: number; 24 | systemInstruction?: string; 25 | } 26 | 27 | /** 28 | * Get MIME type based on file extension 29 | */ 30 | function getMimeType(ext: string): string { 31 | const mimeTypes: Record = { 32 | '.png': 'image/png', 33 | '.jpg': 'image/jpeg', 34 | '.jpeg': 'image/jpeg', 35 | '.gif': 'image/gif', 36 | '.webp': 'image/webp', 37 | '.bmp': 'image/bmp', 38 | '.svg': 'image/svg+xml', 39 | '.ico': 'image/x-icon' 40 | }; 41 | return mimeTypes[ext.toLowerCase()] || 'image/png'; 42 | } 43 | 44 | /** 45 | * Convert image to Base64 inline data format 46 | * Supports: file path, Base64 data URI 47 | */ 48 | function convertImageToInlineData(image: string): { mimeType: string; data: string } { 49 | // 1. Already in Base64 data URI format 50 | if (image.startsWith('data:')) { 51 | const [metadata, data] = image.split(','); 52 | const mimeType = metadata.match(/:(.*?);/)?.[1] || 'image/png'; 53 | return { mimeType, data }; 54 | } 55 | 56 | // 2. URL format - not supported 57 | if (image.startsWith('http://') || image.startsWith('https://')) { 58 | throw new Error( 59 | `URL images are not supported. Please provide a file path or Base64 data URI instead.` 60 | ); 61 | } 62 | 63 | // 3. File path format - read file and convert to Base64 64 | try { 65 | // Check if file exists 66 | if (!fs.existsSync(image)) { 67 | throw new Error(`Image file not found: ${image}`); 68 | } 69 | 70 | // Read file and convert to Base64 71 | const fileBuffer = fs.readFileSync(image); 72 | const base64Data = fileBuffer.toString('base64'); 73 | 74 | // Get MIME type 75 | const ext = path.extname(image); 76 | const mimeType = getMimeType(ext); 77 | 78 | return { mimeType, data: base64Data }; 79 | } catch (error: any) { 80 | if (error.message.includes('Image file not found')) { 81 | throw error; 82 | } 83 | throw new Error(`Failed to read image file "${image}": ${error.message}`); 84 | } 85 | } 86 | 87 | export class GeminiClient { 88 | private client: GoogleGenAI; 89 | private modelId: string; 90 | private config: Required; 91 | 92 | constructor(config: GeminiClientConfig) { 93 | this.client = new GoogleGenAI({ apiKey: config.apiKey }); 94 | this.modelId = config.model || 'gemini-3-pro-preview'; 95 | this.config = { 96 | apiKey: config.apiKey, 97 | model: this.modelId, 98 | timeout: config.timeout || API_CONFIG.timeout, 99 | maxRetries: config.maxRetries || API_CONFIG.maxRetries 100 | }; 101 | } 102 | 103 | /** 104 | * Generate content (text only) 105 | */ 106 | async generate(prompt: string, options: GenerateOptions = {}): Promise { 107 | try { 108 | const requestBody: any = { 109 | model: this.modelId, 110 | contents: [{ 111 | role: 'user', 112 | parts: [{ text: prompt }] 113 | }], 114 | generationConfig: { 115 | temperature: options.temperature, 116 | maxOutputTokens: options.maxTokens, 117 | topP: options.topP, 118 | topK: options.topK 119 | } 120 | }; 121 | 122 | // Add system instruction (if provided) 123 | if (options.systemInstruction) { 124 | requestBody.systemInstruction = { 125 | parts: [{ text: options.systemInstruction }] 126 | }; 127 | } 128 | 129 | const result = await this.client.models.generateContent(requestBody); 130 | return result.text || ''; 131 | } catch (error) { 132 | throw this.handleError(error); 133 | } 134 | } 135 | 136 | /** 137 | * Generate content (multimodal: text + images) 138 | * Supported image formats: 139 | * - File path: e.g., "./images/screenshot.png" 140 | * - Base64 data URI: e.g., "data:image/png;base64,iVBORw0KGgo..." 141 | */ 142 | async generateMultimodal( 143 | prompt: string, 144 | images: string[], 145 | options: GenerateOptions = {} 146 | ): Promise { 147 | try { 148 | // Build content: text + images 149 | const parts: any[] = [{ text: prompt }]; 150 | 151 | // Process each image (supports file path and Base64) 152 | for (const image of images) { 153 | const { mimeType, data } = convertImageToInlineData(image); 154 | parts.push({ 155 | inlineData: { 156 | mimeType, 157 | data 158 | } 159 | }); 160 | } 161 | 162 | const requestBody: any = { 163 | model: this.modelId, 164 | contents: [{ role: 'user', parts }], 165 | generationConfig: { 166 | temperature: options.temperature, 167 | maxOutputTokens: options.maxTokens, 168 | topP: options.topP, 169 | topK: options.topK 170 | } 171 | }; 172 | 173 | // Add system instruction (if provided) 174 | if (options.systemInstruction) { 175 | requestBody.systemInstruction = { 176 | parts: [{ text: options.systemInstruction }] 177 | }; 178 | } 179 | 180 | const result = await this.client.models.generateContent(requestBody); 181 | return result.text || ''; 182 | } catch (error) { 183 | throw this.handleError(error); 184 | } 185 | } 186 | 187 | /** 188 | * Switch model 189 | */ 190 | setModel(modelId: string): void { 191 | this.modelId = modelId; 192 | this.config.model = modelId; 193 | } 194 | 195 | /** 196 | * Get current model 197 | */ 198 | getModel(): string { 199 | return this.modelId; 200 | } 201 | 202 | /** 203 | * Error handling 204 | */ 205 | private handleError(error: any): Error { 206 | if (error.message?.includes('API key')) { 207 | return new Error('Invalid API key'); 208 | } 209 | if (error.message?.includes('quota')) { 210 | return new Error('API quota exceeded'); 211 | } 212 | if (error.message?.includes('timeout')) { 213 | return new Error('Request timeout'); 214 | } 215 | return new Error(error.message || 'Unknown error'); 216 | } 217 | } 218 | 219 | /** 220 | * Create Gemini client instance 221 | */ 222 | export function createGeminiClient(apiKey: string, model?: string): GeminiClient { 223 | return new GeminiClient({ apiKey, model }); 224 | } 225 | -------------------------------------------------------------------------------- /src/config/models.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Gemini model configuration 3 | * Based on official documentation: https://ai.google.dev/gemini-api/docs/models 4 | * Last updated: November 2025 5 | */ 6 | 7 | /** 8 | * Model capabilities details interface 9 | */ 10 | export interface ModelCapabilities { 11 | /** Maximum input tokens */ 12 | maxInputTokens: number; 13 | /** Maximum output tokens */ 14 | maxOutputTokens: number; 15 | /** Whether vision/video input is supported */ 16 | supportsVision: boolean; 17 | /** Whether function calling is supported */ 18 | supportsFunctionCalling: boolean; 19 | /** Whether streaming output is supported */ 20 | supportsStreaming: boolean; 21 | /** Whether thinking/reasoning is supported */ 22 | supportsThinking: boolean; 23 | /** Whether system instructions are supported */ 24 | supportsSystemInstructions: boolean; 25 | } 26 | 27 | /** 28 | * Model pricing information (optional) 29 | */ 30 | export interface ModelPricing { 31 | /** Price per million input tokens */ 32 | inputPerMillion: string; 33 | /** Price per million output tokens */ 34 | outputPerMillion: string; 35 | } 36 | 37 | export interface ModelConfig { 38 | id: string; 39 | name: string; 40 | description: string; 41 | contextWindow: number; 42 | outputLimit: number; 43 | /** Structured capability information */ 44 | capabilities: ModelCapabilities; 45 | features: string[]; 46 | bestFor: string[]; 47 | /** Recommended use cases */ 48 | useCases: string[]; 49 | thinking: boolean; 50 | lastUpdate: string; 51 | isDefault: boolean; 52 | /** Pricing information (optional) */ 53 | pricing?: ModelPricing; 54 | } 55 | 56 | /** 57 | * Supported Gemini model list 58 | * Curated 4 models focused on UI generation and frontend development 59 | */ 60 | export const SUPPORTED_MODELS: Record = { 61 | 'gemini-3-pro-preview': { 62 | id: 'gemini-3-pro-preview', 63 | name: 'Gemini 3.0 Pro Preview', 64 | description: 'Latest and most powerful model, #1 on WebDev Arena for UI generation', 65 | contextWindow: 1_048_576, // 1M tokens 66 | outputLimit: 65_536, 67 | capabilities: { 68 | maxInputTokens: 1_048_576, 69 | maxOutputTokens: 65_536, 70 | supportsVision: true, 71 | supportsFunctionCalling: true, 72 | supportsStreaming: true, 73 | supportsThinking: true, 74 | supportsSystemInstructions: true 75 | }, 76 | features: ['thinking', 'multimodal', 'function_calling', 'grounding', 'system_instructions'], 77 | bestFor: ['UI generation', 'Frontend development', 'Design to code', 'Interactive animations', 'Complex reasoning'], 78 | useCases: ['UI generation', 'Frontend development', 'Design to code', 'Interactive animations', 'Complex reasoning'], 79 | thinking: true, 80 | lastUpdate: 'November 2025', 81 | isDefault: true 82 | }, 83 | 'gemini-2.5-pro': { 84 | id: 'gemini-2.5-pro', 85 | name: 'Gemini 2.5 Pro', 86 | description: 'Stable production model with excellent coding capabilities', 87 | contextWindow: 1_048_576, // 1M tokens 88 | outputLimit: 65_536, 89 | capabilities: { 90 | maxInputTokens: 1_048_576, 91 | maxOutputTokens: 65_536, 92 | supportsVision: true, 93 | supportsFunctionCalling: true, 94 | supportsStreaming: true, 95 | supportsThinking: true, 96 | supportsSystemInstructions: true 97 | }, 98 | features: ['thinking', 'multimodal', 'function_calling', 'grounding', 'system_instructions'], 99 | bestFor: ['General coding', 'Large codebase analysis', 'Fallback option'], 100 | useCases: ['General coding', 'Large codebase analysis', 'Code review', 'Documentation generation'], 101 | thinking: true, 102 | lastUpdate: 'June 2025', 103 | isDefault: false 104 | }, 105 | 'gemini-2.5-flash': { 106 | id: 'gemini-2.5-flash', 107 | name: 'Gemini 2.5 Flash', 108 | description: 'Fast and cost-effective model with best price/performance ratio', 109 | contextWindow: 1_048_576, // 1M tokens 110 | outputLimit: 65_536, 111 | capabilities: { 112 | maxInputTokens: 1_048_576, 113 | maxOutputTokens: 65_536, 114 | supportsVision: true, 115 | supportsFunctionCalling: true, 116 | supportsStreaming: true, 117 | supportsThinking: true, 118 | supportsSystemInstructions: true 119 | }, 120 | features: ['thinking', 'multimodal', 'function_calling', 'grounding', 'system_instructions'], 121 | bestFor: ['High-frequency tasks', 'Batch processing', 'Cost optimization'], 122 | useCases: ['Quick Q&A', 'Real-time analysis', 'Batch processing', 'Cost optimization'], 123 | thinking: true, 124 | lastUpdate: 'June 2025', 125 | isDefault: false 126 | }, 127 | 'gemini-2.5-flash-lite': { 128 | id: 'gemini-2.5-flash-lite', 129 | name: 'Gemini 2.5 Flash Lite', 130 | description: 'Ultra-fast and most cost-efficient model for simple tasks', 131 | contextWindow: 1_048_576, // 1M tokens 132 | outputLimit: 65_536, 133 | capabilities: { 134 | maxInputTokens: 1_048_576, 135 | maxOutputTokens: 65_536, 136 | supportsVision: true, 137 | supportsFunctionCalling: true, 138 | supportsStreaming: true, 139 | supportsThinking: true, 140 | supportsSystemInstructions: true 141 | }, 142 | features: ['thinking', 'multimodal', 'function_calling', 'system_instructions'], 143 | bestFor: ['Simple queries', 'Quick prototypes', 'Maximum cost savings'], 144 | useCases: ['Simple queries', 'Quick validation', 'Low latency scenarios', 'Maximum cost savings'], 145 | thinking: true, 146 | lastUpdate: 'July 2025', 147 | isDefault: false 148 | } 149 | }; 150 | 151 | /** 152 | * Get default model 153 | */ 154 | export function getDefaultModel(): ModelConfig { 155 | return SUPPORTED_MODELS['gemini-3-pro-preview']; 156 | } 157 | 158 | /** 159 | * Get model configuration 160 | * @param modelId - Model ID 161 | * @returns Model configuration, returns default model if not found 162 | */ 163 | export function getModelConfig(modelId?: string): ModelConfig { 164 | if (!modelId) { 165 | return getDefaultModel(); 166 | } 167 | 168 | return SUPPORTED_MODELS[modelId] || getDefaultModel(); 169 | } 170 | 171 | /** 172 | * Validate if model is supported 173 | * @param modelId - Model ID 174 | * @returns Whether the model is supported 175 | */ 176 | export function isModelSupported(modelId: string): boolean { 177 | return modelId in SUPPORTED_MODELS; 178 | } 179 | 180 | /** 181 | * Get all supported models list 182 | */ 183 | export function getAllModels(): ModelConfig[] { 184 | return Object.values(SUPPORTED_MODELS); 185 | } 186 | 187 | /** 188 | * Model selection recommendations 189 | */ 190 | export const MODEL_RECOMMENDATIONS = { 191 | ui_generation: 'gemini-3-pro-preview', 192 | animation: 'gemini-3-pro-preview', 193 | multimodal: 'gemini-3-pro-preview', 194 | codebase_analysis: 'gemini-2.5-pro', 195 | batch_processing: 'gemini-2.5-flash', 196 | simple_tasks: 'gemini-2.5-flash-lite', 197 | fallback: 'gemini-2.5-pro' 198 | }; 199 | -------------------------------------------------------------------------------- /dist/tools/fix-ui.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Tool 3: gemini_fix_ui_from_screenshot 3 | * Identify and fix UI issues from screenshots 4 | * Priority: P0 - Core functionality 5 | */ 6 | import { validateRequired, validateString } from '../utils/validators.js'; 7 | import { handleAPIError, logError } from '../utils/error-handler.js'; 8 | import { readFile, readFiles } from '../utils/file-reader.js'; 9 | // System prompt for UI debugging 10 | const UI_FIX_SYSTEM_PROMPT = `You are a UI debugging expert specializing in visual problem diagnosis. 11 | 12 | Your expertise: 13 | - Identifying layout issues (alignment, spacing, overflow) 14 | - Detecting styling problems (colors, fonts, borders) 15 | - Spotting responsive design failures 16 | - Finding accessibility issues 17 | - Recognizing browser compatibility problems 18 | 19 | Analysis process: 20 | 1. Examine the screenshot carefully 21 | 2. Identify all visual problems 22 | 3. Determine root causes (CSS, HTML structure, JavaScript) 23 | 4. Provide targeted fixes 24 | 25 | Output requirements: 26 | 1. Diagnosis: 27 | - List all identified issues 28 | - Explain why each issue occurs 29 | - Prioritize by severity 30 | 2. Fixes: 31 | - Provide complete code fixes 32 | - Show before/after comparisons 33 | - Explain what each fix does 34 | 3. Prevention: 35 | - Suggest best practices to avoid similar issues 36 | - Recommend tools or techniques 37 | 38 | Code quality: 39 | - Minimal changes (fix only what's broken) 40 | - Maintain existing code style 41 | - Add comments explaining fixes 42 | - Ensure backward compatibility`; 43 | /** 44 | * Handle gemini_fix_ui_from_screenshot tool call 45 | */ 46 | export async function handleFixUI(params, client) { 47 | try { 48 | // Validate required parameters 49 | // screenshot can be file path or Base64, gemini-client.ts will handle conversion automatically 50 | validateRequired(params.screenshot, 'screenshot'); 51 | validateString(params.screenshot, 'screenshot', 5); 52 | // [NEW] Read source code files 53 | let codeContext = ''; 54 | const analyzedFiles = []; 55 | // Read main source code file 56 | if (params.sourceCodePath) { 57 | try { 58 | const fileContent = await readFile(params.sourceCodePath); 59 | analyzedFiles.push(fileContent.path); 60 | codeContext += `## Main source code file: ${fileContent.path}\n`; 61 | codeContext += `\`\`\`${fileContent.language?.toLowerCase() || ''}\n`; 62 | codeContext += fileContent.content; 63 | codeContext += '\n```\n\n'; 64 | } 65 | catch (error) { 66 | logError('fixUI:readSourceCodePath', error); 67 | // Continue execution, do not interrupt 68 | } 69 | } 70 | // Read related files 71 | if (params.relatedFiles && params.relatedFiles.length > 0) { 72 | try { 73 | const relatedContents = await readFiles(params.relatedFiles); 74 | for (const file of relatedContents) { 75 | analyzedFiles.push(file.path); 76 | codeContext += `## Related file: ${file.path}\n`; 77 | codeContext += `\`\`\`${file.language?.toLowerCase() || ''}\n`; 78 | codeContext += file.content; 79 | codeContext += '\n```\n\n'; 80 | } 81 | } 82 | catch (error) { 83 | logError('fixUI:readRelatedFiles', error); 84 | // Continue execution, do not interrupt 85 | } 86 | } 87 | // Backward compatibility: if currentCode provided and no source file read 88 | if (params.currentCode && !params.sourceCodePath) { 89 | codeContext += `## Current code\n\`\`\`\n${params.currentCode}\n\`\`\`\n\n`; 90 | } 91 | // Build prompt 92 | let prompt = `Analyze this screenshot and identify all UI problems.\n\n`; 93 | if (params.issueDescription) { 94 | prompt += `Known Issue: ${params.issueDescription}\n\n`; 95 | } 96 | // Add code context 97 | if (codeContext) { 98 | prompt += `# Source Code Context\n${codeContext}\n`; 99 | } 100 | if (params.targetState) { 101 | // Check if targetState is an image 102 | const isBase64Image = params.targetState.startsWith('data:image'); 103 | const isFilePath = /\.(png|jpg|jpeg|gif|webp|bmp|svg|ico)$/i.test(params.targetState); 104 | if (!isBase64Image && !isFilePath) { 105 | prompt += `Expected State: ${params.targetState}\n\n`; 106 | } 107 | } 108 | // [UPDATE] If there are source code files, require file path in fixes 109 | const hasSourceFiles = analyzedFiles.length > 0; 110 | prompt += `Please provide: 111 | 1. Diagnosis: What's wrong and why (analyze both the screenshot and source code) 112 | 2. Fixes: Complete code fixes for each issue${hasSourceFiles ? ' (include file path for each fix)' : ''} 113 | 3. Prevention: How to avoid similar issues 114 | 115 | Format your response as JSON with this structure: 116 | { 117 | "diagnosis": "detailed analysis", 118 | "fixes": [ 119 | { 120 | "description": "what this fix does", 121 | "code": "complete fixed code", 122 | "changes": ["list of changes made"]${hasSourceFiles ? ',\n "filePath": "path/to/file.tsx"' : ''} 123 | } 124 | ], 125 | "preventionTips": ["tip 1", "tip 2"] 126 | }`; 127 | // Call Gemini API 128 | const images = [params.screenshot]; 129 | // targetState can be an image (file path or Base64) or text description 130 | // If it looks like an image, add it to the image list 131 | if (params.targetState) { 132 | const isBase64Image = params.targetState.startsWith('data:image'); 133 | const isFilePath = /\.(png|jpg|jpeg|gif|webp|bmp|svg|ico)$/i.test(params.targetState); 134 | if (isBase64Image || isFilePath) { 135 | images.push(params.targetState); 136 | } 137 | } 138 | const response = await client.generateMultimodal(prompt, images, { 139 | systemInstruction: UI_FIX_SYSTEM_PROMPT, 140 | temperature: 0.5, 141 | maxTokens: 6144 142 | }); 143 | // Try to parse as JSON 144 | try { 145 | const result = JSON.parse(response); 146 | // Add analyzed files list 147 | if (analyzedFiles.length > 0) { 148 | result.analyzedFiles = analyzedFiles; 149 | } 150 | return result; 151 | } 152 | catch { 153 | // If not JSON, return structured response 154 | return { 155 | diagnosis: response, 156 | fixes: [{ 157 | description: 'General fix', 158 | code: extractCodeFromResponse(response), 159 | changes: ['See diagnosis for details'] 160 | }], 161 | analyzedFiles: analyzedFiles.length > 0 ? analyzedFiles : undefined 162 | }; 163 | } 164 | } 165 | catch (error) { 166 | logError('fixUI', error); 167 | throw handleAPIError(error); 168 | } 169 | } 170 | /** 171 | * Extract code from response (if JSON parsing fails) 172 | */ 173 | function extractCodeFromResponse(response) { 174 | // Try to extract code blocks 175 | const codeBlocks = response.match(/```[\s\S]*?```/g); 176 | if (codeBlocks && codeBlocks.length > 0) { 177 | return codeBlocks.map(block => block.replace(/```[a-z]*\n/g, '').replace(/```/g, '').trim()).join('\n\n'); 178 | } 179 | return response; 180 | } 181 | //# sourceMappingURL=fix-ui.js.map -------------------------------------------------------------------------------- /dist/tools/analyze-codebase.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"analyze-codebase.js","sourceRoot":"","sources":["../../src/tools/analyze-codebase.ts"],"names":[],"mappings":"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"} -------------------------------------------------------------------------------- /src/tools/fix-ui.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Tool 3: gemini_fix_ui_from_screenshot 3 | * Identify and fix UI issues from screenshots 4 | * Priority: P0 - Core functionality 5 | */ 6 | 7 | import { GeminiClient } from '../utils/gemini-client.js'; 8 | import { 9 | validateRequired, 10 | validateString 11 | } from '../utils/validators.js'; 12 | import { handleAPIError, logError } from '../utils/error-handler.js'; 13 | import { readFile, readFiles, FileContent } from '../utils/file-reader.js'; 14 | 15 | // System prompt for UI debugging 16 | const UI_FIX_SYSTEM_PROMPT = `You are a UI debugging expert specializing in visual problem diagnosis. 17 | 18 | Your expertise: 19 | - Identifying layout issues (alignment, spacing, overflow) 20 | - Detecting styling problems (colors, fonts, borders) 21 | - Spotting responsive design failures 22 | - Finding accessibility issues 23 | - Recognizing browser compatibility problems 24 | 25 | Analysis process: 26 | 1. Examine the screenshot carefully 27 | 2. Identify all visual problems 28 | 3. Determine root causes (CSS, HTML structure, JavaScript) 29 | 4. Provide targeted fixes 30 | 31 | Output requirements: 32 | 1. Diagnosis: 33 | - List all identified issues 34 | - Explain why each issue occurs 35 | - Prioritize by severity 36 | 2. Fixes: 37 | - Provide complete code fixes 38 | - Show before/after comparisons 39 | - Explain what each fix does 40 | 3. Prevention: 41 | - Suggest best practices to avoid similar issues 42 | - Recommend tools or techniques 43 | 44 | Code quality: 45 | - Minimal changes (fix only what's broken) 46 | - Maintain existing code style 47 | - Add comments explaining fixes 48 | - Ensure backward compatibility`; 49 | 50 | export interface FixUIParams { 51 | screenshot: string; 52 | 53 | // [NEW] Source code file path 54 | sourceCodePath?: string; 55 | 56 | // [NEW] Related files path list 57 | relatedFiles?: string[]; 58 | 59 | // [KEEP] Direct code input (backward compatible) 60 | currentCode?: string; 61 | 62 | issueDescription?: string; 63 | targetState?: string; 64 | } 65 | 66 | export interface FixUIResult { 67 | diagnosis: string; 68 | fixes: Array<{ 69 | description: string; 70 | code: string; 71 | changes: string[]; 72 | /** Target file path for this fix (if applicable) */ 73 | filePath?: string; 74 | }>; 75 | preventionTips?: string[]; 76 | /** List of source code files used in analysis */ 77 | analyzedFiles?: string[]; 78 | } 79 | 80 | /** 81 | * Handle gemini_fix_ui_from_screenshot tool call 82 | */ 83 | export async function handleFixUI( 84 | params: FixUIParams, 85 | client: GeminiClient 86 | ): Promise { 87 | try { 88 | // Validate required parameters 89 | // screenshot can be file path or Base64, gemini-client.ts will handle conversion automatically 90 | validateRequired(params.screenshot, 'screenshot'); 91 | validateString(params.screenshot, 'screenshot', 5); 92 | 93 | // [NEW] Read source code files 94 | let codeContext = ''; 95 | const analyzedFiles: string[] = []; 96 | 97 | // Read main source code file 98 | if (params.sourceCodePath) { 99 | try { 100 | const fileContent = await readFile(params.sourceCodePath); 101 | analyzedFiles.push(fileContent.path); 102 | codeContext += `## Main source code file: ${fileContent.path}\n`; 103 | codeContext += `\`\`\`${fileContent.language?.toLowerCase() || ''}\n`; 104 | codeContext += fileContent.content; 105 | codeContext += '\n```\n\n'; 106 | } catch (error) { 107 | logError('fixUI:readSourceCodePath', error); 108 | // Continue execution, do not interrupt 109 | } 110 | } 111 | 112 | // Read related files 113 | if (params.relatedFiles && params.relatedFiles.length > 0) { 114 | try { 115 | const relatedContents = await readFiles(params.relatedFiles); 116 | for (const file of relatedContents) { 117 | analyzedFiles.push(file.path); 118 | codeContext += `## Related file: ${file.path}\n`; 119 | codeContext += `\`\`\`${file.language?.toLowerCase() || ''}\n`; 120 | codeContext += file.content; 121 | codeContext += '\n```\n\n'; 122 | } 123 | } catch (error) { 124 | logError('fixUI:readRelatedFiles', error); 125 | // Continue execution, do not interrupt 126 | } 127 | } 128 | 129 | // Backward compatibility: if currentCode provided and no source file read 130 | if (params.currentCode && !params.sourceCodePath) { 131 | codeContext += `## Current code\n\`\`\`\n${params.currentCode}\n\`\`\`\n\n`; 132 | } 133 | 134 | // Build prompt 135 | let prompt = `Analyze this screenshot and identify all UI problems.\n\n`; 136 | 137 | if (params.issueDescription) { 138 | prompt += `Known Issue: ${params.issueDescription}\n\n`; 139 | } 140 | 141 | // Add code context 142 | if (codeContext) { 143 | prompt += `# Source Code Context\n${codeContext}\n`; 144 | } 145 | 146 | if (params.targetState) { 147 | // Check if targetState is an image 148 | const isBase64Image = params.targetState.startsWith('data:image'); 149 | const isFilePath = /\.(png|jpg|jpeg|gif|webp|bmp|svg|ico)$/i.test(params.targetState); 150 | if (!isBase64Image && !isFilePath) { 151 | prompt += `Expected State: ${params.targetState}\n\n`; 152 | } 153 | } 154 | 155 | // [UPDATE] If there are source code files, require file path in fixes 156 | const hasSourceFiles = analyzedFiles.length > 0; 157 | prompt += `Please provide: 158 | 1. Diagnosis: What's wrong and why (analyze both the screenshot and source code) 159 | 2. Fixes: Complete code fixes for each issue${hasSourceFiles ? ' (include file path for each fix)' : ''} 160 | 3. Prevention: How to avoid similar issues 161 | 162 | Format your response as JSON with this structure: 163 | { 164 | "diagnosis": "detailed analysis", 165 | "fixes": [ 166 | { 167 | "description": "what this fix does", 168 | "code": "complete fixed code", 169 | "changes": ["list of changes made"]${hasSourceFiles ? ',\n "filePath": "path/to/file.tsx"' : ''} 170 | } 171 | ], 172 | "preventionTips": ["tip 1", "tip 2"] 173 | }`; 174 | 175 | // Call Gemini API 176 | const images = [params.screenshot]; 177 | // targetState can be an image (file path or Base64) or text description 178 | // If it looks like an image, add it to the image list 179 | if (params.targetState) { 180 | const isBase64Image = params.targetState.startsWith('data:image'); 181 | const isFilePath = /\.(png|jpg|jpeg|gif|webp|bmp|svg|ico)$/i.test(params.targetState); 182 | if (isBase64Image || isFilePath) { 183 | images.push(params.targetState); 184 | } 185 | } 186 | 187 | const response = await client.generateMultimodal( 188 | prompt, 189 | images, 190 | { 191 | systemInstruction: UI_FIX_SYSTEM_PROMPT, 192 | temperature: 0.5, 193 | maxTokens: 6144 194 | } 195 | ); 196 | 197 | // Try to parse as JSON 198 | try { 199 | const result = JSON.parse(response); 200 | // Add analyzed files list 201 | if (analyzedFiles.length > 0) { 202 | result.analyzedFiles = analyzedFiles; 203 | } 204 | return result; 205 | } catch { 206 | // If not JSON, return structured response 207 | return { 208 | diagnosis: response, 209 | fixes: [{ 210 | description: 'General fix', 211 | code: extractCodeFromResponse(response), 212 | changes: ['See diagnosis for details'] 213 | }], 214 | analyzedFiles: analyzedFiles.length > 0 ? analyzedFiles : undefined 215 | }; 216 | } 217 | 218 | } catch (error: any) { 219 | logError('fixUI', error); 220 | throw handleAPIError(error); 221 | } 222 | } 223 | 224 | /** 225 | * Extract code from response (if JSON parsing fails) 226 | */ 227 | function extractCodeFromResponse(response: string): string { 228 | // Try to extract code blocks 229 | const codeBlocks = response.match(/```[\s\S]*?```/g); 230 | if (codeBlocks && codeBlocks.length > 0) { 231 | return codeBlocks.map(block => 232 | block.replace(/```[a-z]*\n/g, '').replace(/```/g, '').trim() 233 | ).join('\n\n'); 234 | } 235 | return response; 236 | } 237 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Gemini MCP Server 2 | 3 | [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) 4 | [![TypeScript](https://img.shields.io/badge/TypeScript-5.3-blue)](https://www.typescriptlang.org/) 5 | [![MCP Version](https://img.shields.io/badge/MCP-2024--11--05-green)](https://modelcontextprotocol.io/) 6 | 7 | A specialized MCP (Model Context Protocol) server focused on **UI generation and frontend development** using Google's latest Gemini 3.0 Pro model. Designed to complement Claude Code by handling what Gemini does best. 8 | 9 | 🚀 **Works with**: Claude Desktop, Claude Code, Cursor, Windsurf, and any MCP-compatible client 10 | 🎯 **Specialization**: UI generation, design-to-code, interactive animations, visual debugging 11 | ⚡ **Powered by**: Gemini 3.0 Pro (#1 on WebDev Arena for UI generation) 12 | 13 | ## Why This Server? 14 | 15 | Claude Code excels at code planning, architecture design, and code review. But for UI generation and frontend development, Gemini 3.0 Pro is the leader: 16 | 17 | - **#1 on WebDev Arena** (1487 Elo) for UI generation 18 | - **Superior visual understanding**: Design mockups → pixel-perfect code 19 | - **Animation expertise**: Canvas, WebGL, CSS animations, Three.js 20 | - **Native multimodal**: Seamless image + text understanding 21 | 22 | > **Philosophy**: Let Claude be the commander, let Gemini be the specialist. 23 | 24 | ## Features 25 | 26 | ### 8 Specialized Tools 27 | 28 | | Tool | Description | Priority | 29 | |------|-------------|----------| 30 | | `gemini_generate_ui` | Generate HTML/CSS/JS UI components from description or design image | 🔴 P0 | 31 | | `gemini_multimodal_query` | Analyze images with natural language queries | 🔴 P0 | 32 | | `gemini_fix_ui_from_screenshot` | Diagnose and fix UI issues from screenshots | 🔴 P0 | 33 | | `gemini_create_animation` | Create interactive animations (CSS/Canvas/WebGL/Three.js) | 🔴 P0 | 34 | | `gemini_analyze_content` | Analyze code, documents, or data (supports file path) | 🟡 P1 | 35 | | `gemini_analyze_codebase` | Analyze entire codebase (supports directory path) | 🟡 P1 | 36 | | `gemini_brainstorm` | Generate creative ideas with project context | 🟢 P2 | 37 | | `list_models` | List available Gemini models with capabilities | 🟢 P2 | 38 | 39 | ### v1.1.0 New Features 40 | 41 | #### Direct File System Access 42 | 43 | Tools can now read files directly from the file system, no need to pass file contents: 44 | 45 | | Tool | New Parameters | 46 | |------|----------------| 47 | | `analyze_codebase` | `directory`, `filePaths`, `include`, `exclude` | 48 | | `analyze_content` | `filePath` | 49 | | `generate_ui` | `techContext`, `configPath` | 50 | | `fix_ui_from_screenshot` | `sourceCodePath`, `relatedFiles` | 51 | | `brainstorm` | `contextFilePath`, `contextFiles` | 52 | 53 | #### Tech Stack Context 54 | 55 | `generate_ui` now supports technology stack context for generating code that matches your project: 56 | 57 | ```json 58 | { 59 | "description": "User login form", 60 | "framework": "react", 61 | "techContext": { 62 | "cssFramework": "tailwind", 63 | "uiLibrary": "shadcn", 64 | "typescript": true 65 | } 66 | } 67 | ``` 68 | 69 | Or auto-detect from `package.json`: 70 | ```json 71 | { 72 | "description": "User login form", 73 | "configPath": "./package.json" 74 | } 75 | ``` 76 | 77 | #### Structured Model Information 78 | 79 | `list_models` now returns detailed capability information: 80 | - `capabilities`: maxInputTokens, supportsVision, supportsFunctionCalling, etc. 81 | - `useCases`: Recommended use cases in Chinese 82 | - `recommendations`: Model recommendations by scenario 83 | 84 | ### Supported Models 85 | 86 | | Model | Context | Best For | Default | 87 | |-------|---------|----------|---------| 88 | | `gemini-3-pro-preview` | 1M tokens | UI generation, frontend development | ✅ Yes | 89 | | `gemini-2.5-pro` | 1M tokens | General coding, fallback | ❌ No | 90 | | `gemini-2.5-flash` | 1M tokens | High-frequency tasks, cost optimization | ❌ No | 91 | | `gemini-2.5-flash-lite` | 1M tokens | Simple queries, maximum cost savings | ❌ No | 92 | 93 | ## Quick Start 94 | 95 | ### 1. Get Gemini API Key 96 | 97 | Visit [Google AI Studio](https://makersuite.google.com/app/apikey) and create an API key. 98 | 99 | ### 2. Configure Your MCP Client 100 | 101 |
102 | Claude Desktop / Claude Code 103 | 104 | Config location: 105 | - Mac: `~/Library/Application Support/Claude/claude_desktop_config.json` 106 | - Windows: `%APPDATA%\Claude\claude_desktop_config.json` 107 | - Linux: `~/.config/Claude/claude_desktop_config.json` 108 | 109 | ```json 110 | { 111 | "mcpServers": { 112 | "gemini-assistant": { 113 | "command": "npx", 114 | "args": ["-y", "github:LKbaba/Gemini-mcp"], 115 | "env": { 116 | "GEMINI_API_KEY": "your_api_key_here" 117 | } 118 | } 119 | } 120 | } 121 | ``` 122 | 123 | **For users behind proxy/VPN**, add proxy environment variable: 124 | ```json 125 | { 126 | "mcpServers": { 127 | "gemini-assistant": { 128 | "command": "npx", 129 | "args": ["-y", "github:LKbaba/Gemini-mcp"], 130 | "env": { 131 | "GEMINI_API_KEY": "your_api_key_here", 132 | "HTTPS_PROXY": "http://127.0.0.1:7897" 133 | } 134 | } 135 | } 136 | } 137 | ``` 138 |
139 | 140 |
141 | Cursor / Windsurf 142 | 143 | Add to your MCP settings: 144 | ```json 145 | { 146 | "gemini-assistant": { 147 | "command": "npx", 148 | "args": ["-y", "github:LKbaba/Gemini-mcp"], 149 | "env": { 150 | "GEMINI_API_KEY": "your_api_key_here" 151 | } 152 | } 153 | } 154 | ``` 155 |
156 | 157 | ### 3. Restart Your MCP Client 158 | 159 | ## Usage Examples 160 | 161 | ### UI Generation 162 | 163 | ``` 164 | "Generate a responsive pricing card with three tiers using React" 165 | "Create a modern login form with glassmorphism style" 166 | "Build a dashboard sidebar with smooth hover animations" 167 | ``` 168 | 169 | ### Design to Code 170 | 171 | ``` 172 | "Convert this Figma screenshot to a React component" (attach image) 173 | "Implement this UI design pixel-perfectly" (attach image) 174 | ``` 175 | 176 | ### Visual Debugging 177 | 178 | ``` 179 | "Fix the layout issue in this screenshot" (attach screenshot) 180 | "The button is misaligned on mobile, here's a screenshot" (attach screenshot) 181 | ``` 182 | 183 | ### Animation Creation 184 | 185 | ``` 186 | "Create a particle system that follows the mouse cursor" 187 | "Build a 3D rotating cube with Three.js" 188 | "Make a smooth page transition animation with CSS" 189 | ``` 190 | 191 | ### Code Analysis 192 | 193 | ``` 194 | "Analyze this codebase for security issues" 195 | "Review this function for performance improvements" 196 | "Explain this complex algorithm" 197 | ``` 198 | 199 | ## Image Input Support 200 | 201 | All image-related tools support two input formats: 202 | 203 | 1. **File paths** (recommended for local files): 204 | ``` 205 | "./images/design.png" 206 | "C:/Users/name/Desktop/screenshot.png" 207 | ``` 208 | 209 | 2. **Base64 data URIs**: 210 | ``` 211 | "data:image/png;base64,iVBORw0KGgo..." 212 | ``` 213 | 214 | When you provide a file path, Claude Code will automatically read and convert it. 215 | 216 | ## Local Development 217 | 218 | ```bash 219 | # Clone repository 220 | git clone https://github.com/LKbaba/Gemini-mcp.git 221 | cd Gemini-mcp 222 | 223 | # Install dependencies 224 | npm install 225 | 226 | # Set up environment 227 | export GEMINI_API_KEY="your_api_key_here" 228 | 229 | # Build 230 | npm run build 231 | 232 | # Start server 233 | npm start 234 | ``` 235 | 236 | ## Project Structure 237 | 238 | ``` 239 | src/ 240 | ├── config/ 241 | │ ├── models.ts # 模型配置(含能力信息) 242 | │ └── constants.ts # 全局常量 243 | ├── tools/ 244 | │ ├── definitions.ts # MCP 工具定义 245 | │ ├── generate-ui.ts # UI 生成(支持技术栈上下文) 246 | │ ├── multimodal-query.ts # 多模态查询 247 | │ ├── fix-ui.ts # UI 修复(支持源代码路径) 248 | │ ├── create-animation.ts # 动画创建 249 | │ ├── analyze-content.ts # 内容分析(支持文件路径) 250 | │ ├── analyze-codebase.ts # 代码库分析(支持目录路径) 251 | │ ├── brainstorm.ts # 头脑风暴(支持项目上下文) 252 | │ └── list-models.ts # 模型列表(结构化输出) 253 | ├── utils/ 254 | │ ├── gemini-client.ts # Gemini API 客户端 255 | │ ├── error-handler.ts # 错误处理 256 | │ ├── validators.ts # 参数验证 257 | │ ├── security.ts # 安全验证模块(新增) 258 | │ └── file-reader.ts # 文件读取工具(新增) 259 | ├── types.ts # 类型定义 260 | └── server.ts # 主服务器 261 | ``` 262 | 263 | ## Credits 264 | 265 | Based on [aliargun/mcp-server-gemini](https://github.com/aliargun/mcp-server-gemini) v4.2.2 266 | 267 | Inspired by: 268 | - [RaiAnsar/claude_code-gemini-mcp](https://github.com/RaiAnsar/claude_code-gemini-mcp) 269 | - [cmdaltctr/claude-gemini-mcp-slim](https://github.com/cmdaltctr/claude-gemini-mcp-slim) 270 | - [RLabs-Inc/gemini-mcp](https://github.com/RLabs-Inc/gemini-mcp) 271 | 272 | ## License 273 | 274 | MIT 275 | 276 | --- 277 | 278 | *Specialized for UI generation and frontend development* 279 | *Powered by Gemini 3.0 Pro* 280 | -------------------------------------------------------------------------------- /src/server.ts: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /** 3 | * mcp-server-gemini-lkbaba 4 | * Main server file 5 | * 6 | * Specialized MCP server for Gemini 3.0 Pro focused on UI generation and frontend development 7 | * Based on: aliargun/mcp-server-gemini v4.2.2 8 | * Author: LKbaba 9 | */ 10 | 11 | import { createInterface } from 'readline'; 12 | import { MCPRequest, MCPResponse, InitializeResult } from './types.js'; 13 | import { SERVER_INFO, MCP_VERSION, ERROR_CODES, TOOL_NAMES } from './config/constants.js'; 14 | import { createGeminiClient, GeminiClient } from './utils/gemini-client.js'; 15 | import { handleAPIError, handleValidationError, handleInternalError, logError } from './utils/error-handler.js'; 16 | import { TOOL_DEFINITIONS } from './tools/definitions.js'; 17 | import { 18 | handleGenerateUI, 19 | handleMultimodalQuery, 20 | handleFixUI, 21 | handleCreateAnimation, 22 | handleAnalyzeContent, 23 | handleAnalyzeCodebase, 24 | handleBrainstorm, 25 | handleListModels 26 | } from './tools/index.js'; 27 | 28 | // Setup proxy for Node.js fetch (required for users behind proxy/VPN) 29 | async function setupProxy(): Promise { 30 | const proxyUrl = process.env.HTTP_PROXY || process.env.HTTPS_PROXY || process.env.http_proxy || process.env.https_proxy; 31 | 32 | if (proxyUrl) { 33 | try { 34 | const { ProxyAgent, setGlobalDispatcher } = await import('undici'); 35 | const dispatcher = new ProxyAgent(proxyUrl); 36 | setGlobalDispatcher(dispatcher); 37 | console.error(`🌐 Proxy configured: ${proxyUrl}`); 38 | } catch (error) { 39 | console.error('⚠️ Failed to configure proxy. If you need proxy support, run: npm install undici'); 40 | } 41 | } 42 | } 43 | 44 | // Initialize proxy before anything else 45 | await setupProxy(); 46 | 47 | // Increase stdin buffer size (for large images) 48 | if (process.stdin.setEncoding) { 49 | process.stdin.setEncoding('utf8'); 50 | } 51 | 52 | // Global state 53 | let geminiClient: GeminiClient | null = null; 54 | let isInitialized = false; 55 | 56 | /** 57 | * Send response to stdout 58 | */ 59 | function sendResponse(response: MCPResponse): void { 60 | console.log(JSON.stringify(response)); 61 | } 62 | 63 | /** 64 | * Send error response 65 | */ 66 | function sendError(id: string | number, code: number, message: string, data?: any): void { 67 | sendResponse({ 68 | jsonrpc: '2.0', 69 | id, 70 | error: { code, message, data } 71 | }); 72 | } 73 | 74 | /** 75 | * Handle initialize request 76 | */ 77 | function handleInitialize(request: MCPRequest): void { 78 | const result: InitializeResult = { 79 | protocolVersion: MCP_VERSION, 80 | serverInfo: { 81 | name: SERVER_INFO.name, 82 | version: SERVER_INFO.version 83 | }, 84 | capabilities: { 85 | tools: { 86 | listChanged: false 87 | } 88 | } 89 | }; 90 | 91 | sendResponse({ 92 | jsonrpc: '2.0', 93 | id: request.id, 94 | result 95 | }); 96 | 97 | isInitialized = true; 98 | } 99 | 100 | /** 101 | * Handle tools/list request 102 | */ 103 | function handleToolsList(request: MCPRequest): void { 104 | sendResponse({ 105 | jsonrpc: '2.0', 106 | id: request.id, 107 | result: { 108 | tools: TOOL_DEFINITIONS 109 | } 110 | }); 111 | } 112 | 113 | /** 114 | * Handle tools/call request 115 | */ 116 | async function handleToolsCall(request: MCPRequest): Promise { 117 | if (!isInitialized) { 118 | sendError(request.id, ERROR_CODES.INTERNAL_ERROR, 'Server not initialized'); 119 | return; 120 | } 121 | 122 | const { name, arguments: args } = request.params; 123 | 124 | // Initialize Gemini client (if not already) 125 | if (!geminiClient) { 126 | const apiKey = process.env.GEMINI_API_KEY; 127 | if (!apiKey) { 128 | sendError( 129 | request.id, 130 | ERROR_CODES.API_ERROR, 131 | 'GEMINI_API_KEY environment variable is not set' 132 | ); 133 | return; 134 | } 135 | geminiClient = createGeminiClient(apiKey); 136 | } 137 | 138 | try { 139 | let result: any; 140 | 141 | // Route to corresponding tool handler 142 | switch (name) { 143 | case TOOL_NAMES.LIST_MODELS: 144 | result = await handleListModels(); 145 | break; 146 | 147 | case TOOL_NAMES.GENERATE_UI: 148 | result = await handleGenerateUI(args, geminiClient); 149 | break; 150 | 151 | case TOOL_NAMES.MULTIMODAL_QUERY: 152 | result = await handleMultimodalQuery(args, geminiClient); 153 | break; 154 | 155 | case TOOL_NAMES.FIX_UI: 156 | result = await handleFixUI(args, geminiClient); 157 | break; 158 | 159 | case TOOL_NAMES.CREATE_ANIMATION: 160 | result = await handleCreateAnimation(args, geminiClient); 161 | break; 162 | 163 | case TOOL_NAMES.ANALYZE_CONTENT: 164 | result = await handleAnalyzeContent(args, geminiClient); 165 | break; 166 | 167 | case TOOL_NAMES.ANALYZE_CODEBASE: 168 | result = await handleAnalyzeCodebase(args, geminiClient); 169 | break; 170 | 171 | case TOOL_NAMES.BRAINSTORM: 172 | result = await handleBrainstorm(args, geminiClient); 173 | break; 174 | 175 | default: 176 | sendError( 177 | request.id, 178 | ERROR_CODES.METHOD_NOT_FOUND, 179 | `Unknown tool: ${name}` 180 | ); 181 | return; 182 | } 183 | 184 | // Send success response 185 | sendResponse({ 186 | jsonrpc: '2.0', 187 | id: request.id, 188 | result: { 189 | content: [ 190 | { 191 | type: 'text', 192 | text: typeof result === 'string' ? result : JSON.stringify(result, null, 2) 193 | } 194 | ] 195 | } 196 | }); 197 | } catch (error: any) { 198 | logError(`Tool: ${name}`, error); 199 | 200 | // Return appropriate error based on error type 201 | if (error.message?.includes('not yet implemented')) { 202 | sendError(request.id, ERROR_CODES.INTERNAL_ERROR, error.message); 203 | } else if (error.message?.includes('required') || error.message?.includes('must be')) { 204 | const validationError = handleValidationError(error.message); 205 | sendError(request.id, validationError.code, validationError.message, validationError.data); 206 | } else { 207 | const apiError = handleAPIError(error); 208 | sendError(request.id, apiError.code, apiError.message, apiError.data); 209 | } 210 | } 211 | } 212 | 213 | /** 214 | * Handle request 215 | */ 216 | async function handleRequest(request: MCPRequest): Promise { 217 | try { 218 | switch (request.method) { 219 | case 'initialize': 220 | handleInitialize(request); 221 | break; 222 | 223 | case 'tools/list': 224 | handleToolsList(request); 225 | break; 226 | 227 | case 'tools/call': 228 | await handleToolsCall(request); 229 | break; 230 | 231 | case 'ping': 232 | sendResponse({ 233 | jsonrpc: '2.0', 234 | id: request.id, 235 | result: { status: 'ok' } 236 | }); 237 | break; 238 | 239 | default: 240 | sendError( 241 | request.id, 242 | ERROR_CODES.METHOD_NOT_FOUND, 243 | `Method not found: ${request.method}` 244 | ); 245 | } 246 | } catch (error: any) { 247 | logError('Request handler', error); 248 | const internalError = handleInternalError(error); 249 | sendError(request.id, internalError.code, internalError.message, internalError.data); 250 | } 251 | } 252 | 253 | /** 254 | * Main function 255 | */ 256 | function main(): void { 257 | console.error(`🚀 ${SERVER_INFO.name} v${SERVER_INFO.version}`); 258 | console.error(`📋 Based on: ${SERVER_INFO.basedOn}`); 259 | console.error(`🎨 Specialized for UI generation and frontend development`); 260 | console.error(`⚡ Powered by Gemini 3.0 Pro`); 261 | console.error(''); 262 | console.error('Waiting for requests...'); 263 | console.error(''); 264 | 265 | // Read stdin line by line 266 | const rl = createInterface({ 267 | input: process.stdin, 268 | output: process.stdout, 269 | terminal: false 270 | }); 271 | 272 | rl.on('line', async (line) => { 273 | if (!line.trim()) return; 274 | 275 | try { 276 | const request: MCPRequest = JSON.parse(line); 277 | await handleRequest(request); 278 | } catch (error) { 279 | console.error('Failed to parse request:', error); 280 | sendError( 281 | 'unknown', 282 | ERROR_CODES.PARSE_ERROR, 283 | 'Invalid JSON-RPC request' 284 | ); 285 | } 286 | }); 287 | 288 | rl.on('close', () => { 289 | console.error('Connection closed'); 290 | process.exit(0); 291 | }); 292 | 293 | // Handle process signals 294 | process.on('SIGINT', () => { 295 | console.error('\nShutting down...'); 296 | process.exit(0); 297 | }); 298 | 299 | process.on('SIGTERM', () => { 300 | console.error('\nShutting down...'); 301 | process.exit(0); 302 | }); 303 | } 304 | 305 | // Start server 306 | main(); 307 | -------------------------------------------------------------------------------- /dist/server.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | /** 3 | * mcp-server-gemini-lkbaba 4 | * Main server file 5 | * 6 | * Specialized MCP server for Gemini 3.0 Pro focused on UI generation and frontend development 7 | * Based on: aliargun/mcp-server-gemini v4.2.2 8 | * Author: LKbaba 9 | */ 10 | import { createInterface } from 'readline'; 11 | import { SERVER_INFO, MCP_VERSION, ERROR_CODES, TOOL_NAMES } from './config/constants.js'; 12 | import { createGeminiClient } from './utils/gemini-client.js'; 13 | import { handleAPIError, handleValidationError, handleInternalError, logError } from './utils/error-handler.js'; 14 | import { TOOL_DEFINITIONS } from './tools/definitions.js'; 15 | import { handleGenerateUI, handleMultimodalQuery, handleFixUI, handleCreateAnimation, handleAnalyzeContent, handleAnalyzeCodebase, handleBrainstorm, handleListModels } from './tools/index.js'; 16 | // Setup proxy for Node.js fetch (required for users behind proxy/VPN) 17 | async function setupProxy() { 18 | const proxyUrl = process.env.HTTP_PROXY || process.env.HTTPS_PROXY || process.env.http_proxy || process.env.https_proxy; 19 | if (proxyUrl) { 20 | try { 21 | const { ProxyAgent, setGlobalDispatcher } = await import('undici'); 22 | const dispatcher = new ProxyAgent(proxyUrl); 23 | setGlobalDispatcher(dispatcher); 24 | console.error(`🌐 Proxy configured: ${proxyUrl}`); 25 | } 26 | catch (error) { 27 | console.error('⚠️ Failed to configure proxy. If you need proxy support, run: npm install undici'); 28 | } 29 | } 30 | } 31 | // Initialize proxy before anything else 32 | await setupProxy(); 33 | // Increase stdin buffer size (for large images) 34 | if (process.stdin.setEncoding) { 35 | process.stdin.setEncoding('utf8'); 36 | } 37 | // Global state 38 | let geminiClient = null; 39 | let isInitialized = false; 40 | /** 41 | * Send response to stdout 42 | */ 43 | function sendResponse(response) { 44 | console.log(JSON.stringify(response)); 45 | } 46 | /** 47 | * Send error response 48 | */ 49 | function sendError(id, code, message, data) { 50 | sendResponse({ 51 | jsonrpc: '2.0', 52 | id, 53 | error: { code, message, data } 54 | }); 55 | } 56 | /** 57 | * Handle initialize request 58 | */ 59 | function handleInitialize(request) { 60 | const result = { 61 | protocolVersion: MCP_VERSION, 62 | serverInfo: { 63 | name: SERVER_INFO.name, 64 | version: SERVER_INFO.version 65 | }, 66 | capabilities: { 67 | tools: { 68 | listChanged: false 69 | } 70 | } 71 | }; 72 | sendResponse({ 73 | jsonrpc: '2.0', 74 | id: request.id, 75 | result 76 | }); 77 | isInitialized = true; 78 | } 79 | /** 80 | * Handle tools/list request 81 | */ 82 | function handleToolsList(request) { 83 | sendResponse({ 84 | jsonrpc: '2.0', 85 | id: request.id, 86 | result: { 87 | tools: TOOL_DEFINITIONS 88 | } 89 | }); 90 | } 91 | /** 92 | * Handle tools/call request 93 | */ 94 | async function handleToolsCall(request) { 95 | if (!isInitialized) { 96 | sendError(request.id, ERROR_CODES.INTERNAL_ERROR, 'Server not initialized'); 97 | return; 98 | } 99 | const { name, arguments: args } = request.params; 100 | // Initialize Gemini client (if not already) 101 | if (!geminiClient) { 102 | const apiKey = process.env.GEMINI_API_KEY; 103 | if (!apiKey) { 104 | sendError(request.id, ERROR_CODES.API_ERROR, 'GEMINI_API_KEY environment variable is not set'); 105 | return; 106 | } 107 | geminiClient = createGeminiClient(apiKey); 108 | } 109 | try { 110 | let result; 111 | // Route to corresponding tool handler 112 | switch (name) { 113 | case TOOL_NAMES.LIST_MODELS: 114 | result = await handleListModels(); 115 | break; 116 | case TOOL_NAMES.GENERATE_UI: 117 | result = await handleGenerateUI(args, geminiClient); 118 | break; 119 | case TOOL_NAMES.MULTIMODAL_QUERY: 120 | result = await handleMultimodalQuery(args, geminiClient); 121 | break; 122 | case TOOL_NAMES.FIX_UI: 123 | result = await handleFixUI(args, geminiClient); 124 | break; 125 | case TOOL_NAMES.CREATE_ANIMATION: 126 | result = await handleCreateAnimation(args, geminiClient); 127 | break; 128 | case TOOL_NAMES.ANALYZE_CONTENT: 129 | result = await handleAnalyzeContent(args, geminiClient); 130 | break; 131 | case TOOL_NAMES.ANALYZE_CODEBASE: 132 | result = await handleAnalyzeCodebase(args, geminiClient); 133 | break; 134 | case TOOL_NAMES.BRAINSTORM: 135 | result = await handleBrainstorm(args, geminiClient); 136 | break; 137 | default: 138 | sendError(request.id, ERROR_CODES.METHOD_NOT_FOUND, `Unknown tool: ${name}`); 139 | return; 140 | } 141 | // Send success response 142 | sendResponse({ 143 | jsonrpc: '2.0', 144 | id: request.id, 145 | result: { 146 | content: [ 147 | { 148 | type: 'text', 149 | text: typeof result === 'string' ? result : JSON.stringify(result, null, 2) 150 | } 151 | ] 152 | } 153 | }); 154 | } 155 | catch (error) { 156 | logError(`Tool: ${name}`, error); 157 | // Return appropriate error based on error type 158 | if (error.message?.includes('not yet implemented')) { 159 | sendError(request.id, ERROR_CODES.INTERNAL_ERROR, error.message); 160 | } 161 | else if (error.message?.includes('required') || error.message?.includes('must be')) { 162 | const validationError = handleValidationError(error.message); 163 | sendError(request.id, validationError.code, validationError.message, validationError.data); 164 | } 165 | else { 166 | const apiError = handleAPIError(error); 167 | sendError(request.id, apiError.code, apiError.message, apiError.data); 168 | } 169 | } 170 | } 171 | /** 172 | * Handle request 173 | */ 174 | async function handleRequest(request) { 175 | try { 176 | switch (request.method) { 177 | case 'initialize': 178 | handleInitialize(request); 179 | break; 180 | case 'tools/list': 181 | handleToolsList(request); 182 | break; 183 | case 'tools/call': 184 | await handleToolsCall(request); 185 | break; 186 | case 'ping': 187 | sendResponse({ 188 | jsonrpc: '2.0', 189 | id: request.id, 190 | result: { status: 'ok' } 191 | }); 192 | break; 193 | default: 194 | sendError(request.id, ERROR_CODES.METHOD_NOT_FOUND, `Method not found: ${request.method}`); 195 | } 196 | } 197 | catch (error) { 198 | logError('Request handler', error); 199 | const internalError = handleInternalError(error); 200 | sendError(request.id, internalError.code, internalError.message, internalError.data); 201 | } 202 | } 203 | /** 204 | * Main function 205 | */ 206 | function main() { 207 | console.error(`🚀 ${SERVER_INFO.name} v${SERVER_INFO.version}`); 208 | console.error(`📋 Based on: ${SERVER_INFO.basedOn}`); 209 | console.error(`🎨 Specialized for UI generation and frontend development`); 210 | console.error(`⚡ Powered by Gemini 3.0 Pro`); 211 | console.error(''); 212 | console.error('Waiting for requests...'); 213 | console.error(''); 214 | // Read stdin line by line 215 | const rl = createInterface({ 216 | input: process.stdin, 217 | output: process.stdout, 218 | terminal: false 219 | }); 220 | rl.on('line', async (line) => { 221 | if (!line.trim()) 222 | return; 223 | try { 224 | const request = JSON.parse(line); 225 | await handleRequest(request); 226 | } 227 | catch (error) { 228 | console.error('Failed to parse request:', error); 229 | sendError('unknown', ERROR_CODES.PARSE_ERROR, 'Invalid JSON-RPC request'); 230 | } 231 | }); 232 | rl.on('close', () => { 233 | console.error('Connection closed'); 234 | process.exit(0); 235 | }); 236 | // Handle process signals 237 | process.on('SIGINT', () => { 238 | console.error('\nShutting down...'); 239 | process.exit(0); 240 | }); 241 | process.on('SIGTERM', () => { 242 | console.error('\nShutting down...'); 243 | process.exit(0); 244 | }); 245 | } 246 | // Start server 247 | main(); 248 | //# sourceMappingURL=server.js.map --------------------------------------------------------------------------------