From 27834943fa0f432ad15faac3b4ae283c27e3da73 Mon Sep 17 00:00:00 2001 From: User Date: Mon, 4 Aug 2025 05:43:13 +0800 Subject: [PATCH 01/28] Initial commit - Windows fixed version --- .github/workflows/ci.yml | 87 ++ .gitignore | 80 ++ .npmignore | 75 ++ INSTALL-GUIDE.md | 214 ++++ LICENSE | 21 + README.md | 333 +++++ fix-proxy-push.ps1 | 189 +++ .../gemini-mcp-tool-windows-fixed-1.0.1.tar | Bin 0 -> 47104 bytes index.js | 11 + lib/fixed-constants.js | 72 ++ lib/fixed-geminiExecutor.js | 278 +++++ lib/fixed-mcp-tool.js | 363 ++++++ package-lock.json | 1070 +++++++++++++++++ package.json | 51 + 14 files changed, 2844 insertions(+) create mode 100644 .github/workflows/ci.yml create mode 100644 .gitignore create mode 100644 .npmignore create mode 100644 INSTALL-GUIDE.md create mode 100644 LICENSE create mode 100644 README.md create mode 100644 fix-proxy-push.ps1 create mode 100644 gemini-mcp-tool-windows-fixed-1.0.1/gemini-mcp-tool-windows-fixed-1.0.1.tar create mode 100644 index.js create mode 100644 lib/fixed-constants.js create mode 100644 lib/fixed-geminiExecutor.js create mode 100644 lib/fixed-mcp-tool.js create mode 100644 package-lock.json create mode 100644 package.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..ec6669e --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,87 @@ +name: CI/CD Pipeline + +on: + push: + branches: [ main, develop ] + pull_request: + branches: [ main ] + release: + types: [ published ] + +jobs: + test: + runs-on: windows-latest + + strategy: + matrix: + node-version: [16.x, 18.x, 20.x] + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Install Gemini CLI + run: npm install -g @google/generative-ai-cli + + - name: Test basic functionality + run: | + node index.js --help + echo "Basic test completed" + env: + GEMINI_API_KEY: ${{ secrets.GEMINI_API_KEY }} + + - name: Test NPX functionality + run: | + npm pack + $package = Get-ChildItem -Name "*.tgz" + npm install -g $package + echo "NPX test completed" + + publish: + needs: test + runs-on: windows-latest + if: github.event_name == 'release' + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '18.x' + registry-url: 'https://registry.npmjs.org' + cache: 'npm' + + - name: Install dependencies + run: npm ci + + - name: Publish to NPM + run: npm publish + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + + - name: Create GitHub Release Assets + run: | + npm pack + $package = Get-ChildItem -Name "*.tgz" + echo "Package created: $package" + + - name: Upload Release Asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: ./*.tgz + asset_name: gemini-mcp-tool-windows-fixed.tgz + asset_content_type: application/gzip \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fc96047 --- /dev/null +++ b/.gitignore @@ -0,0 +1,80 @@ +# Dependencies +node_modules/ +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Environment variables +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +# Logs +logs +*.log + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Coverage directory used by tools like istanbul +coverage/ + +# nyc test coverage +.nyc_output + +# Dependency directories +node_modules/ +jspm_packages/ + +# Optional npm cache directory +.npm + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + +# IDE files +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS generated files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# Windows specific +*.lnk + +# Temporary files +*.tmp +*.temp + +# Build outputs +dist/ +build/ + +# Test outputs +test-results/ + +# Cache +.cache/ \ No newline at end of file diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..26eff76 --- /dev/null +++ b/.npmignore @@ -0,0 +1,75 @@ +# Development files +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Coverage directory used by tools like istanbul +coverage/ + +# nyc test coverage +.nyc_output + +# Dependency directories +node_modules/ + +# Optional npm cache directory +.npm + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env +.env.test +.env.local +.env.production + +# IDE files +.vscode/ +.idea/ +*.swp +*.swo +*~ + +# OS generated files +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# Git files +.git/ +.gitignore + +# Documentation that's not needed in package +README-FIXED.md + +# Test files +test/ +tests/ +*.test.js +*.spec.js + +# Build artifacts +build/ +dist/ + +# Temporary files +tmp/ +temp/ \ No newline at end of file diff --git a/INSTALL-GUIDE.md b/INSTALL-GUIDE.md new file mode 100644 index 0000000..e66a9be --- /dev/null +++ b/INSTALL-GUIDE.md @@ -0,0 +1,214 @@ +# 🚀 Gemini MCP Tool - Windows Fixed Version Installation Guide + +## 📋 Prerequisites + +1. **Node.js** (v16.0.0 or higher) + ```powershell + # Check version + node --version + npm --version + ``` + +2. **Google Gemini CLI** + ```powershell + # Install Gemini CLI + npm install -g @google/generative-ai-cli + + # Verify installation + gemini --version + ``` + +3. **Gemini API Key** + - Get your API key from [Google AI Studio](https://makersuite.google.com/app/apikey) + +## 🔧 Installation Methods + +### Method 1: NPX (Recommended) + +```powershell +# Test the tool +npx -y gemini-mcp-tool-windows-fixed +``` + +### Method 2: Global Installation + +```powershell +# Install globally +npm install -g gemini-mcp-tool-windows-fixed + +# Test the tool +gemini-mcp-tool-windows-fixed +``` + +## ⚙️ MCP Client Configuration + +### For Trae AI + +1. Open: `%APPDATA%\Trae\User\mcp.json` +2. Add this configuration: + +```json +{ + "mcpServers": { + "gemini-cli": { + "name": "gemini-cli", + "description": "Windows-compatible Gemini MCP Tool", + "baseUrl": "", + "command": "npx", + "args": [ + "-y", + "gemini-mcp-tool-windows-fixed" + ], + "env": { + "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" + }, + "isActive": true, + "providerUrl": "https://github.com/your-username/gemini-mcp-tool-windows-fixed" + } + } +} +``` + +### For Claude Desktop + +1. Open: `%APPDATA%\Claude\claude_desktop_config.json` +2. Add this configuration: + +```json +{ + "mcpServers": { + "gemini-cli": { + "command": "npx", + "args": ["-y", "gemini-mcp-tool-windows-fixed"], + "env": { + "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" + } + } + } +} +``` + +## 🔑 API Key Configuration + +### Option 1: MCP Configuration (Recommended) + +Replace `YOUR_ACTUAL_API_KEY_HERE` in the configuration above with your actual API key. + +### Option 2: Environment Variable + +```powershell +# Temporary (current session) +$env:GEMINI_API_KEY = "your-actual-api-key" + +# Permanent (user level) +[Environment]::SetEnvironmentVariable("GEMINI_API_KEY", "your-actual-api-key", "User") + +# Verify +echo $env:GEMINI_API_KEY +``` + +## 🧪 Testing Installation + +### 1. Test Gemini CLI + +```powershell +gemini -p "Hello, how are you?" +``` + +### 2. Test MCP Tool + +```powershell +# Test with NPX +npx -y gemini-mcp-tool-windows-fixed + +# Should show: [GMCPT] Gemini CLI MCP Server (Fixed) started +``` + +### 3. Test MCP Integration + +After configuring your MCP client: + +1. Restart your MCP client (Trae AI, Claude Desktop) +2. Try asking: "Use gemini to explain what MCP is" +3. Check for successful responses + +## 🐛 Troubleshooting + +### Common Issues + +#### 1. "Command not found: gemini" + +```powershell +# Reinstall Gemini CLI +npm uninstall -g @google/generative-ai-cli +npm install -g @google/generative-ai-cli + +# Check PATH +echo $env:PATH +``` + +#### 2. "API key not found" + +```powershell +# Check if API key is set +echo $env:GEMINI_API_KEY + +# If empty, set it +$env:GEMINI_API_KEY = "your-api-key" +``` + +#### 3. "Permission denied" + +```powershell +# Run as Administrator +# Or check execution policy +Get-ExecutionPolicy +Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser +``` + +#### 4. "Module not found" + +```powershell +# Clear npm cache +npm cache clean --force + +# Reinstall +npm install -g gemini-mcp-tool-windows-fixed +``` + +### Debug Mode + +Enable debug logging: + +```json +"env": { + "GEMINI_API_KEY": "your-key", + "DEBUG": "true" +} +``` + +## 📞 Support + +If you encounter issues: + +1. Check the [troubleshooting section](#troubleshooting) +2. Verify all prerequisites are installed +3. Test each component individually +4. Open an issue with: + - Windows version + - PowerShell version + - Node.js version + - Complete error logs + +## 🎉 Success! + +Once everything is working, you should be able to: + +- Ask Gemini questions through your MCP client +- Analyze files using `@filename` syntax +- Use sandbox mode for safe code execution +- Leverage Gemini's large context window for complex analysis + +--- + +**Happy coding! 🚀** \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..14e3561 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Gemini MCP Tool Windows Fixed Version + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..fde9e09 --- /dev/null +++ b/README.md @@ -0,0 +1,333 @@ +# 🚀 Gemini MCP Tool - Windows Fixed Version + +[![npm version](https://badge.fury.io/js/gemini-mcp-tool-windows-fixed.svg)](https://badge.fury.io/js/gemini-mcp-tool-windows-fixed) +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) + +A **Windows-compatible** Model Context Protocol (MCP) server that enables AI assistants to interact with Google's Gemini CLI. This is a fixed version specifically designed to work seamlessly on Windows environments with PowerShell support. + +> **Note**: This is an enhanced version of the [original gemini-mcp-tool](https://github.com/jamubc/gemini-mcp-tool) with Windows-specific fixes and improvements. + +## ✨ Features + +- **🪟 Windows Compatible**: Full PowerShell support with Windows-specific path handling +- **📊 Large Context Window**: Leverage Gemini's massive token window for analyzing entire codebases +- **📁 File Analysis**: Analyze files using `@filename` syntax +- **🔒 Sandbox Mode**: Safe code execution environment +- **🔗 MCP Integration**: Seamless integration with MCP-compatible AI assistants (Trae AI, Claude Desktop) +- **⚡ NPX Ready**: Easy installation and usage with NPX +- **🔧 Environment Variable Support**: Flexible API key configuration + +This Windows-fixed version resolves: +- PowerShell parameter passing issues +- Character encoding problems with Chinese/Unicode text +- Command line argument escaping on Windows +- Environment variable handling + +## 📋 Prerequisites + +1. **Node.js** (v16.0.0 or higher) + ```powershell + node --version # Should be v16+ + ``` + +2. **Google Gemini CLI**: Install the Gemini CLI tool + ```powershell + npm install -g @google/generative-ai-cli + + # Verify installation + gemini --version + ``` + +3. **API Key**: Get your API key from [Google AI Studio](https://makersuite.google.com/app/apikey) + +## 📦 Installation + +### Quick Start with NPX (Recommended) + +```powershell +# Test the tool immediately +npx -y gemini-mcp-tool-windows-fixed +``` + +### Global Installation + +```powershell +# Install globally +npm install -g gemini-mcp-tool-windows-fixed + +# Run the tool +gemini-mcp-tool-windows-fixed +``` + +## ⚙️ MCP Client Configuration + +### Trae AI (Recommended) + +1. Open: `%APPDATA%\Trae\User\mcp.json` +2. Add this configuration: + +```json +{ + "mcpServers": { + "gemini-cli": { + "name": "gemini-cli", + "description": "Windows-compatible Gemini MCP Tool", + "baseUrl": "", + "command": "npx", + "args": [ + "-y", + "gemini-mcp-tool-windows-fixed" + ], + "env": { + "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" + }, + "isActive": true, + "providerUrl": "https://github.com/your-username/gemini-mcp-tool-windows-fixed" + } + } +} +``` + +### Claude Desktop + +1. Open: `%APPDATA%\Claude\claude_desktop_config.json` +2. Add this configuration: + +```json +{ + "mcpServers": { + "gemini-cli": { + "command": "npx", + "args": ["-y", "gemini-mcp-tool-windows-fixed"], + "env": { + "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" + } + } + } +} +``` + +## 🔑 API Key Configuration + +### Option 1: MCP Configuration (Recommended) + +Replace `YOUR_ACTUAL_API_KEY_HERE` in the configuration above with your actual API key. + +### Option 2: Environment Variable + +```powershell +# Temporary (current session) +$env:GEMINI_API_KEY = "your-actual-api-key" + +# Permanent (user level) +[Environment]::SetEnvironmentVariable("GEMINI_API_KEY", "your-actual-api-key", "User") + +# Verify +echo $env:GEMINI_API_KEY +``` + +### Configuration File Locations + +**Claude Desktop:** +- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json` +- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json` +- **Linux**: `~/.config/claude/claude_desktop_config.json` + +**Trae AI:** +- **Windows**: `%APPDATA%\Trae\User\mcp.json` + +## 🛠️ Available Tools + +This MCP server provides the following tools for AI assistants: + +### 1. `ask-gemini` +Interact with Google Gemini for analysis and questions. + +**Parameters:** +- `prompt` (required): The analysis request. Use `@` syntax for file references +- `model` (optional): Gemini model to use (default: `gemini-2.5-pro`) +- `sandbox` (optional): Enable sandbox mode for safe code execution +- `changeMode` (optional): Enable structured change mode +- `chunkIndex` (optional): Chunk index for continuation +- `chunkCacheKey` (optional): Cache key for continuation + +### 2. `brainstorm` +Generate creative ideas using various brainstorming frameworks. + +**Parameters:** +- `prompt` (required): Brainstorming challenge or question +- `model` (optional): Gemini model to use +- `methodology` (optional): Framework (`divergent`, `convergent`, `scamper`, `design-thinking`, `lateral`, `auto`) +- `domain` (optional): Domain context (`software`, `business`, `creative`, etc.) +- `constraints` (optional): Known limitations or requirements +- `existingContext` (optional): Background information +- `ideaCount` (optional): Number of ideas to generate (default: 12) +- `includeAnalysis` (optional): Include feasibility analysis (default: true) + +### 3. `fetch-chunk` +Retrieve cached chunks from changeMode responses. + +**Parameters:** +- `cacheKey` (required): Cache key from initial response +- `chunkIndex` (required): Chunk index to retrieve (1-based) + +### 4. `timeout-test` +Test timeout prevention mechanisms. + +**Parameters:** +- `duration` (required): Duration in milliseconds (minimum: 10ms) + +### 5. `ping` +Test connection to the server. + +**Parameters:** +- `prompt` (optional): Message to echo back + +### 6. `Help` +Display help information about available tools. + +## 🎯 Usage + +Once configured, you can use the following tools through your MCP client: + +### Available Tools + +- **ask-gemini**: Send prompts to Gemini + ``` + "Explain how MCP works" + ``` + +- **analyze-file**: Analyze specific files using `@filename` syntax + ``` + "Analyze @package.json and suggest improvements" + ``` + +- **sandbox-mode**: Execute code in a safe environment + ``` + "Run this Python code in sandbox mode: print('Hello World')" + ``` + +## 📝 Examples + +### Basic Prompts +``` +"What are the best practices for Node.js development?" +"Explain the differences between async/await and Promises" +``` + +### File Analysis +``` +"Analyze @package.json and suggest improvements" +"Review @src/index.js for potential security issues" +"Compare @old-config.json with @new-config.json" +``` + +### Code Execution +``` +"Run this Python code in sandbox mode: print('Hello World')" +"Execute this JavaScript: console.log(new Date())" +``` + +### Complex Analysis +``` +"Analyze the entire codebase and suggest architectural improvements" +"Review all TypeScript files for type safety issues" +``` + +## 🔧 Windows-Specific Fixes + +This version includes the following Windows-specific improvements: + +1. **PowerShell Parameter Handling**: Fixed argument passing to avoid parameter splitting +2. **Character Encoding**: Proper UTF-8 handling for Chinese and Unicode characters +3. **Quote Escaping**: Correct escaping of quotes in command arguments +4. **Environment Variables**: Improved `.env` file loading and environment variable handling +5. **Path Resolution**: Windows-compatible path handling + +## 🧪 Testing Installation + +### 1. Test Gemini CLI +```powershell +gemini -p "Hello, how are you?" +``` + +### 2. Test MCP Tool +```powershell +npx -y gemini-mcp-tool-windows-fixed +# Should show: [GMCPT] Gemini CLI MCP Server (Fixed) started +``` + +### 3. Test MCP Integration +1. Restart your MCP client (Trae AI, Claude Desktop) +2. Try asking: "Use gemini to explain what MCP is" +3. Check for successful responses + +## 🐛 Troubleshooting + +### Common Issues + +#### "Command not found: gemini" +```powershell +npm install -g @google/generative-ai-cli +``` + +#### "API key not found" +```powershell +# Check if API key is set +echo $env:GEMINI_API_KEY + +# Set if empty +$env:GEMINI_API_KEY = "your-api-key" +``` + +#### "Permission denied" +```powershell +# Check execution policy +Get-ExecutionPolicy +Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser +``` + +For detailed troubleshooting, see [INSTALL-GUIDE.md](./INSTALL-GUIDE.md). + +## 🔧 Windows-Specific Fixes + +This version includes several Windows-specific improvements: + +- **PowerShell Integration**: Native PowerShell command execution +- **Path Handling**: Proper Windows path resolution +- **Environment Variables**: Enhanced environment variable support +- **Error Handling**: Better error messages for Windows environments +- **Dependency Management**: Simplified dependency structure + +## 🤝 Contributing + +Contributions are welcome! Please: + +1. Fork the repository +2. Create a feature branch +3. Test on Windows environments +4. Submit a pull request + +## 📄 License + +MIT License - see [LICENSE](LICENSE) file for details. + +## 🙏 Acknowledgments + +- Original project: [jamubc/gemini-mcp-tool](https://github.com/jamubc/gemini-mcp-tool) +- Google Gemini CLI team +- Model Context Protocol (MCP) community + +## 📞 Support + +If you encounter any issues or have questions: + +1. Check the [Issues](https://github.com/your-username/gemini-mcp-tool-windows-fixed/issues) page +2. Create a new issue with detailed information about your problem +3. Include your Windows version, Node.js version, and error messages + +--- + +**Made with ❤️ for Windows developers** + +**Note**: This is a Windows-optimized fork of the original gemini-mcp-tool. For other platforms, consider using the [original version](https://github.com/jamubc/gemini-mcp-tool). diff --git a/fix-proxy-push.ps1 b/fix-proxy-push.ps1 new file mode 100644 index 0000000..dc84c8c --- /dev/null +++ b/fix-proxy-push.ps1 @@ -0,0 +1,189 @@ +# GitHub Proxy Push Fix Script +# Solve Git push issues in proxy environments + +Write-Host "GitHub Proxy Push Fix Tool" -ForegroundColor Cyan +Write-Host "==============================" -ForegroundColor Cyan +Write-Host "" + +# Get GitHub username +$githubUser = Read-Host "Enter your GitHub username" +if (-not $githubUser) { + Write-Host "ERROR: GitHub username is required" -ForegroundColor Red + exit 1 +} + +Write-Host "Detecting current environment..." -ForegroundColor Yellow + +# Detect system proxy +$systemProxy = netsh winhttp show proxy 2>$null +if ($systemProxy -match "Direct access") { + Write-Host "System proxy: Direct access (no proxy)" -ForegroundColor Green +} else { + Write-Host "System proxy: $systemProxy" -ForegroundColor Yellow +} + +# Detect environment variable proxy +$envHttpProxy = $env:HTTP_PROXY +$envHttpsProxy = $env:HTTPS_PROXY +if ($envHttpProxy) { Write-Host "HTTP_PROXY: $envHttpProxy" -ForegroundColor Yellow } +if ($envHttpsProxy) { Write-Host "HTTPS_PROXY: $envHttpsProxy" -ForegroundColor Yellow } +if (-not $envHttpProxy -and -not $envHttpsProxy) { + Write-Host "Environment variables: No proxy configured" -ForegroundColor Green +} + +# Check current Git proxy configuration +$currentGitHttpProxy = git config --global --get http.proxy 2>$null +$currentGitHttpsProxy = git config --global --get https.proxy 2>$null +if ($currentGitHttpProxy) { Write-Host "Git HTTP proxy: $currentGitHttpProxy" -ForegroundColor Yellow } +if ($currentGitHttpsProxy) { Write-Host "Git HTTPS proxy: $currentGitHttpsProxy" -ForegroundColor Yellow } +if (-not $currentGitHttpProxy -and -not $currentGitHttpsProxy) { + Write-Host "Git proxy: Not configured" -ForegroundColor Green +} + +Write-Host "" +Write-Host "Proxy configuration options:" -ForegroundColor Yellow +Write-Host "1. Use system proxy" -ForegroundColor White +Write-Host "2. Manual proxy configuration" -ForegroundColor White +Write-Host "3. Clear proxy configuration" -ForegroundColor White +Write-Host "4. Skip proxy configuration" -ForegroundColor White + +$choice = Read-Host "Please choose (1-4)" + +if ($choice -eq "1") { + Write-Host "Configuring Git to use system proxy..." -ForegroundColor Yellow + + # Extract proxy address from system proxy configuration + if ($systemProxy -match "Proxy Server\(s\)\s*:\s*([^\s]+)") { + $proxyServer = $matches[1] + Write-Host "Detected system proxy: $proxyServer" -ForegroundColor Green + + git config --global http.proxy "http://$proxyServer" + git config --global https.proxy "http://$proxyServer" + + Write-Host "Git proxy configuration completed" -ForegroundColor Green + } else { + Write-Host "Cannot auto-detect system proxy, please configure manually" -ForegroundColor Red + $manualProxy = Read-Host "Enter proxy address (format: host:port)" + if ($manualProxy) { + git config --global http.proxy "http://$manualProxy" + git config --global https.proxy "http://$manualProxy" + Write-Host "Manual proxy configuration completed" -ForegroundColor Green + } + } +} +elseif ($choice -eq "2") { + Write-Host "Manual proxy configuration..." -ForegroundColor Yellow + $proxyHost = Read-Host "Enter proxy host address" + $proxyPort = Read-Host "Enter proxy port" + + if ($proxyHost -and $proxyPort) { + $proxyUrl = "http://$proxyHost`:$proxyPort" + + # Ask if authentication is needed + $needAuth = Read-Host "Does proxy require authentication? (y/n)" + if ($needAuth -eq "y" -or $needAuth -eq "Y") { + $proxyUser = Read-Host "Proxy username" + $proxyPass = Read-Host "Proxy password" -AsSecureString + $proxyPassPlain = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($proxyPass)) + $proxyUrl = "http://$proxyUser`:$proxyPassPlain@$proxyHost`:$proxyPort" + } + + git config --global http.proxy $proxyUrl + git config --global https.proxy $proxyUrl + + Write-Host "Proxy configuration completed" -ForegroundColor Green + } else { + Write-Host "Proxy configuration incomplete" -ForegroundColor Red + } +} +elseif ($choice -eq "3") { + Write-Host "Clearing Git proxy configuration..." -ForegroundColor Yellow + git config --global --unset http.proxy 2>$null + git config --global --unset https.proxy 2>$null + Write-Host "Proxy configuration cleared" -ForegroundColor Green +} +else { + Write-Host "Skipping proxy configuration" -ForegroundColor Yellow +} + +# Git performance optimization +Write-Host "" +Write-Host "Optimizing Git configuration..." -ForegroundColor Yellow +git config --global http.postBuffer 524288000 +git config --global http.lowSpeedLimit 0 +git config --global http.lowSpeedTime 999999 +git config --global http.sslVerify false +git config --global pack.windowMemory 256m +git config --global pack.packSizeLimit 2g +Write-Host "Git performance optimization completed" -ForegroundColor Green + +# Configure credential manager +Write-Host "" +Write-Host "Configuring credential manager..." -ForegroundColor Yellow +git config --global credential.helper manager-core +Write-Host "Credential manager configuration completed" -ForegroundColor Green + +# Set up remote repository +Write-Host "" +Write-Host "Configuring remote repository..." -ForegroundColor Yellow +$repoName = Split-Path -Leaf (Get-Location) +$remoteUrl = "https://github.com/$githubUser/$repoName.git" + +# Check if remote repository already exists +$existingRemote = git remote get-url origin 2>$null +if ($existingRemote) { + Write-Host "Current remote repository: $existingRemote" -ForegroundColor Yellow + $updateRemote = Read-Host "Update to new remote repository? (y/n)" + if ($updateRemote -eq "y" -or $updateRemote -eq "Y") { + git remote set-url origin $remoteUrl + Write-Host "Remote repository updated" -ForegroundColor Green + } +} else { + git remote add origin $remoteUrl + Write-Host "Remote repository added: $remoteUrl" -ForegroundColor Green +} + +# Test network connection +Write-Host "" +Write-Host "Testing network connection..." -ForegroundColor Yellow +try { + $testResult = Test-NetConnection github.com -Port 443 -WarningAction SilentlyContinue + if ($testResult.TcpTestSucceeded) { + Write-Host "GitHub connection successful" -ForegroundColor Green + } else { + Write-Host "GitHub connection failed" -ForegroundColor Red + } +} catch { + Write-Host "Network test failed: $($_.Exception.Message)" -ForegroundColor Yellow +} + +# Repository is now ready for manual upload +Write-Host "✅ Repository configuration completed!" -ForegroundColor Green +Write-Host "" +Write-Host "📋 Manual Upload Instructions:" -ForegroundColor Cyan +Write-Host "1. Create a new repository on GitHub: https://github.com/new" -ForegroundColor White +Write-Host " Repository name: gemini-mcp-tool-windows-fixed" -ForegroundColor White +Write-Host "2. Initialize and push your code:" -ForegroundColor White +Write-Host " git add ." -ForegroundColor Gray +Write-Host " git commit -m 'Initial commit - Windows fixed version'" -ForegroundColor Gray +Write-Host " git branch -M main" -ForegroundColor Gray +Write-Host " git remote add origin https://github.com/$githubUser/gemini-mcp-tool-windows-fixed.git" -ForegroundColor Gray +Write-Host " git push -u origin main" -ForegroundColor Gray +Write-Host "" +Write-Host "📦 Repository ready for manual upload!" -ForegroundColor Green +Write-Host "🔧 All configurations applied successfully!" -ForegroundColor Green + +Write-Host "" +Write-Host "Current Git proxy configuration:" -ForegroundColor Cyan +$currentHttpProxy = git config --global --get http.proxy +$currentHttpsProxy = git config --global --get https.proxy +if ($currentHttpProxy) { Write-Host " http.proxy: $currentHttpProxy" -ForegroundColor White } +if ($currentHttpsProxy) { Write-Host " https.proxy: $currentHttpsProxy" -ForegroundColor White } +if (-not $currentHttpProxy -and -not $currentHttpsProxy) { Write-Host " No proxy configured" -ForegroundColor Gray } + +Write-Host "" +Write-Host "Next steps:" -ForegroundColor Cyan +Write-Host "1. Update Trae AI MCP configuration" -ForegroundColor White +Write-Host "2. Add GEMINI_API_KEY environment variable" -ForegroundColor White +Write-Host "3. Restart Trae AI" -ForegroundColor White +Write-Host "4. Test integration" -ForegroundColor White \ No newline at end of file diff --git a/gemini-mcp-tool-windows-fixed-1.0.1/gemini-mcp-tool-windows-fixed-1.0.1.tar b/gemini-mcp-tool-windows-fixed-1.0.1/gemini-mcp-tool-windows-fixed-1.0.1.tar new file mode 100644 index 0000000000000000000000000000000000000000..280d2c9f9a05e116bbcf98d9e267f712e31adf1f GIT binary patch literal 47104 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 P41B=A2Mqk-W8nV-`SI`l literal 0 HcmV?d00001 diff --git a/index.js b/index.js new file mode 100644 index 0000000..2caaef0 --- /dev/null +++ b/index.js @@ -0,0 +1,11 @@ +#!/usr/bin/env node + +/** + * Gemini MCP Tool - Windows Fixed Version + * + * This is the main entry point for the Windows-fixed MCP server that enables + * AI assistants to interact with Google Gemini CLI with proper character encoding + * and parameter handling for Windows environments. + */ + +import './lib/fixed-mcp-tool.js'; \ No newline at end of file diff --git a/lib/fixed-constants.js b/lib/fixed-constants.js new file mode 100644 index 0000000..fb52d84 --- /dev/null +++ b/lib/fixed-constants.js @@ -0,0 +1,72 @@ +// Logging +export const LOG_PREFIX = "[GMCPT]"; +// Error messages +export const ERROR_MESSAGES = { + QUOTA_EXCEEDED: "Quota exceeded for quota metric 'Gemini 2.5 Pro Requests'", + QUOTA_EXCEEDED_SHORT: "⚠️ Gemini 2.5 Pro daily quota exceeded. Please retry with model: 'gemini-2.5-flash'", + TOOL_NOT_FOUND: "not found in registry", + NO_PROMPT_PROVIDED: "Please provide a prompt for analysis. Use @ syntax to include files (e.g., '@largefile.js explain what this does') or ask general questions", +}; +// Status messages +export const STATUS_MESSAGES = { + QUOTA_SWITCHING: "🚫 Gemini 2.5 Pro quota exceeded, switching to Flash model...", + FLASH_RETRY: "⚡ Retrying with Gemini 2.5 Flash...", + FLASH_SUCCESS: "✅ Flash model completed successfully", + SANDBOX_EXECUTING: "🔒 Executing Gemini CLI command in sandbox mode...", + GEMINI_RESPONSE: "Gemini response:", + // Timeout prevention messages + PROCESSING_START: "🔍 Starting analysis (may take 5-15 minutes for large codebases)", + PROCESSING_CONTINUE: "⏳ Still processing... Gemini is working on your request", + PROCESSING_COMPLETE: "✅ Analysis completed successfully", +}; +// Models +export const MODELS = { + PRO: "gemini-2.5-pro", + FLASH: "gemini-2.5-flash", +}; +// MCP Protocol Constants +export const PROTOCOL = { + // Message roles + ROLES: { + USER: "user", + ASSISTANT: "assistant", + }, + // Content types + CONTENT_TYPES: { + TEXT: "text", + }, + // Status codes + STATUS: { + SUCCESS: "success", + ERROR: "error", + FAILED: "failed", + REPORT: "report", + }, + // Notification methods + NOTIFICATIONS: { + PROGRESS: "notifications/progress", + }, + // Timeout prevention + KEEPALIVE_INTERVAL: 25000, // 25 seconds +}; +// CLI Constants - FIXED VERSION WITH FULL PATH +export const CLI = { + // Command names + COMMANDS: { + GEMINI: "C:\\Users\\admin\\AppData\\Roaming\\npm\\gemini.ps1", + ECHO: "echo", + }, + // Command flags + FLAGS: { + MODEL: "-m", + SANDBOX: "-s", + PROMPT: "-p", + HELP: "-help", + }, + // Default values + DEFAULTS: { + MODEL: "default", // Fallback model used when no specific model is provided + BOOLEAN_TRUE: "true", + BOOLEAN_FALSE: "false", + }, +}; \ No newline at end of file diff --git a/lib/fixed-geminiExecutor.js b/lib/fixed-geminiExecutor.js new file mode 100644 index 0000000..1775ed3 --- /dev/null +++ b/lib/fixed-geminiExecutor.js @@ -0,0 +1,278 @@ +import dotenv from 'dotenv'; +import path from 'path'; +import { fileURLToPath } from 'url'; +// import { executeCommand } from './package/dist/utils/commandExecutor.js'; // Removed - using built-in spawn +import { spawn } from 'child_process'; +// import { Logger } from './package/dist/utils/logger.js'; // Removed - using console instead +import { ERROR_MESSAGES, STATUS_MESSAGES, MODELS, CLI } from './fixed-constants.js'; +// import { parseChangeModeOutput, validateChangeModeEdits } from './package/dist/utils/changeModeParser.js'; // Removed - simplified +// import { formatChangeModeResponse, summarizeChangeModeEdits } from './package/dist/utils/changeModeTranslator.js'; // Removed - simplified +// import { chunkChangeModeEdits } from './package/dist/utils/changeModeChunker.js'; // Removed - simplified +// import { cacheChunks, getChunks } from './package/dist/utils/chunkCache.js'; // Removed - simplified + +// Simple chunk cache implementation +const chunkCache = new Map(); + +function cacheChunks(key, chunks) { + chunkCache.set(key, chunks); +} + +function getChunks(key) { + return chunkCache.get(key) || []; +} + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +dotenv.config({ path: path.join(__dirname, '.env') }); + +// Debug: Check if environment variable is loaded +console.log('GEMINI_API_KEY loaded:', process.env.GEMINI_API_KEY ? 'YES' : 'NO'); +console.log('Current working directory:', process.cwd()); +console.log('Script directory:', __dirname); +console.log('Env file path:', path.join(__dirname, '.env')); + +// Custom executeCommand function that accepts custom environment variables +async function executeCommandWithPipedInput(command, input, env, onProgress) { + return new Promise((resolve, reject) => { + console.log(`[GMCPT] Executing command with piped input: ${command}`); + console.log(`[GMCPT] Input length: ${input.length}`); + console.log(`[GMCPT] GEMINI_API_KEY in env: ${env.GEMINI_API_KEY ? 'YES' : 'NO'}`); + + const childProcess = spawn('powershell.exe', ['-Command', `${command} ${args.join(' ')}`], { + env: env, + stdio: ['pipe', 'pipe', 'pipe'] + }); + + console.log(`[GMCPT] Spawned process with command: powershell.exe -Command "${command} ${args.join(' ')}"`); + + let stdout = ''; + let stderr = ''; + + // Write input to stdin and close it + childProcess.stdin.write(input); + childProcess.stdin.end(); + + childProcess.stdout.on('data', (data) => { + stdout += data.toString(); + if (onProgress) { + onProgress(data.toString()); + } + }); + + childProcess.stderr.on('data', (data) => { + stderr += data.toString(); + }); + + childProcess.on('error', (error) => { + console.log(`[GMCPT] Command execution error: ${error.message}`); + reject(error); + }); + + childProcess.on('close', (code) => { + console.log(`[GMCPT] Command exited with code: ${code}`); + console.log(`[GMCPT] stdout length: ${stdout.length}`); + console.log(`[GMCPT] stderr length: ${stderr.length}`); + console.log(`[GMCPT] stdout content: ${stdout.substring(0, 500)}...`); + console.log(`[GMCPT] stderr content: ${stderr.substring(0, 200)}...`); + if (code === 0) { + resolve({ stdout, stderr }); + } else { + reject(new Error(`Command failed with exit code ${code}: ${stderr}`)); + } + }); + }); +} + +async function executeCommandWithEnv(command, args, env, onProgress) { + return new Promise((resolve, reject) => { + console.log(`[GMCPT] Executing command: ${command} ${args.join(' ')}`); + console.log(`[GMCPT] Environment variables count: ${Object.keys(env).length}`); + console.log(`[GMCPT] GEMINI_API_KEY in env: ${env.GEMINI_API_KEY ? 'YES' : 'NO'}`); + console.log(`Executing with custom env: ${command} ${args.join(' ')}`); + const psCommand = `& "${command}" ${args.map(arg => `'${arg.replace(/'/g, "''")}'`).join(' ')}`; + const childProcess = spawn('powershell.exe', ['-Command', psCommand], { + env: env, + stdio: ['pipe', 'pipe', 'pipe'] + }); + + console.log(`[GMCPT] Executing with PowerShell: ${psCommand}`); + + let stdout = ''; + let stderr = ''; + + childProcess.stdout.on('data', (data) => { + stdout += data.toString(); + if (onProgress) { + onProgress(data.toString()); + } + }); + + childProcess.stderr.on('data', (data) => { + stderr += data.toString(); + }); + + childProcess.on('error', (error) => { + console.error(`Command execution error: ${error.message}`); + reject(error); + }); + + childProcess.on('close', (code) => { + console.log(`[GMCPT] Command exited with code: ${code}`); + console.log(`[GMCPT] stdout length: ${stdout.length}`); + console.log(`[GMCPT] stderr length: ${stderr.length}`); + console.log(`[GMCPT] stdout content: ${stdout.substring(0, 200)}...`); + console.log(`[GMCPT] stderr content: ${stderr.substring(0, 200)}...`); + console.log(`Command exited with code: ${code}`); + if (code === 0) { + resolve({ stdout, stderr }); + } else { + reject(new Error(`Command failed with exit code ${code}: ${stderr}`)); + } + }); + }); +} + +export async function executeGeminiCLI(prompt, model, sandbox, changeMode, onProgress) { + console.log('executeGeminiCLI called with prompt: ' + prompt.substring(0, 50) + '...'); + console.log('API Key available: ' + (process.env.GEMINI_API_KEY ? 'YES' : 'NO')); + let prompt_processed = prompt; + if (changeMode) { + prompt_processed = prompt.replace(/file:(\S+)/g, '@$1'); + const changeModeInstructions = ` +[CHANGEMODE INSTRUCTIONS] +You are generating code modifications that will be processed by an automated system. The output format is critical because it enables programmatic application of changes without human intervention. + +INSTRUCTIONS: +1. Analyze each provided file thoroughly +2. Identify locations requiring changes based on the user request +3. For each change, output in the exact format specified +4. The OLD section must be EXACTLY what appears in the file (copy-paste exact match) +5. Provide complete, directly replacing code blocks +6. Verify line numbers are accurate + +CRITICAL REQUIREMENTS: +1. Output edits in the EXACT format specified below - no deviations +2. The OLD string MUST be findable with Ctrl+F - it must be a unique, exact match +3. Include enough surrounding lines to make the OLD string unique +4. If a string appears multiple times (like ), include enough context lines above and below to make it unique +5. Copy the OLD content EXACTLY as it appears - including all whitespace, indentation, line breaks +6. Never use partial lines - always include complete lines from start to finish + +OUTPUT FORMAT (follow exactly): +**FILE: [filename]:[line_number]** +\`\`\` +OLD: +[exact code to be replaced - must match file content precisely] +NEW: +[new code to insert - complete and functional] +\`\`\` + +EXAMPLE 1 - Simple unique match: +**FILE: src/utils/helper.js:100** +\`\`\` +OLD: +function getMessage() { + return "Hello World"; +} +NEW: +function getMessage() { + return "Hello Universe!"; +\`\`\` +`; + prompt_processed = changeModeInstructions + "\n\n" + prompt_processed; + } + + const args = []; + + if (model && model !== MODELS.PRO) { + args.push(CLI.FLAGS.MODEL, model); + } + + if (sandbox) { + args.push(CLI.FLAGS.SANDBOX); + } + + args.push(CLI.FLAGS.PROMPT, prompt_processed); + + console.log(`Executing: ${CLI.COMMANDS.GEMINI} ${args.join(' ')}`); + + try { + // Create custom environment with GEMINI_API_KEY explicitly set + const customEnv = { + ...process.env, + GEMINI_API_KEY: process.env.GEMINI_API_KEY + }; + + console.log('[GMCPT] Using GEMINI_API_KEY: ' + (customEnv.GEMINI_API_KEY ? 'SET' : 'NOT SET')); + console.log('[GMCPT] Executing gemini command: ' + CLI.COMMANDS.GEMINI + ' ' + args.join(' ')); + + // Execute gemini command directly with custom environment + const result = await executeCommandWithEnv(CLI.COMMANDS.GEMINI, args, customEnv, onProgress); + + if (changeMode && result.stdout) { + try { + // Simple change mode processing - split by lines for chunking + const lines = result.stdout.split('\n'); + const chunks = []; + const chunkSize = 50; // lines per chunk + + for (let i = 0; i < lines.length; i += chunkSize) { + chunks.push(lines.slice(i, i + chunkSize).join('\n')); + } + + if (chunks.length > 1) { + const cacheKey = `change_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; + cacheChunks(cacheKey, chunks); + + return { + content: chunks[0], + chunk: 1, + totalChunks: chunks.length, + cacheKey: cacheKey, + hasMore: true + }; + } else { + return { + content: result.stdout, + chunk: 1, + totalChunks: 1, + hasMore: false + }; + } + } catch (parseError) { + console.error(`Failed to parse change mode output: ${parseError.message}`); + return result.stdout; + } + } + + return result.stdout; + } catch (error) { + console.error(`Gemini CLI execution failed: ${error.message}`); + throw error; + } +} + +export function getChunkedEdits(cacheKey, chunkIndex) { + try { + const chunks = getChunks(cacheKey); + if (!chunks || chunks.length === 0) { + throw new Error('No cached chunks found for the provided cache key'); + } + + const chunk = chunks[chunkIndex - 1]; // Convert to 0-based index + if (!chunk) { + throw new Error(`Chunk ${chunkIndex} not found. Available chunks: 1-${chunks.length}`); + } + + return { + content: chunk, + chunk: chunkIndex, + totalChunks: chunks.length, + cacheKey: cacheKey, + hasMore: chunkIndex < chunks.length + }; + } catch (error) { + console.error(`Failed to retrieve chunk: ${error.message}`); + throw error; + } +} \ No newline at end of file diff --git a/lib/fixed-mcp-tool.js b/lib/fixed-mcp-tool.js new file mode 100644 index 0000000..d4ee188 --- /dev/null +++ b/lib/fixed-mcp-tool.js @@ -0,0 +1,363 @@ +#!/usr/bin/env node +import { Server } from "@modelcontextprotocol/sdk/server/index.js"; +import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; +import { + CallToolRequestSchema, + ListToolsRequestSchema, + ListPromptsRequestSchema, + GetPromptRequestSchema, +} from "@modelcontextprotocol/sdk/types.js"; +// import { Logger } from "../package/dist/utils/logger.js"; // Removed - using console instead +import { PROTOCOL } from "./fixed-constants.js"; +import { executeGeminiCLI, getChunkedEdits } from "./fixed-geminiExecutor.js"; + +const server = new Server({ + name: "gemini-cli-mcp-fixed", + version: "1.1.4-fixed", +}, { + capabilities: { + tools: {}, + prompts: {}, + notifications: {}, + logging: {}, + }, +}); + +let isProcessing = false; +let currentOperationName = ""; +let latestOutput = ""; + +async function sendNotification(method, params) { + try { + await server.notification({ method, params }); + } + catch (error) { + console.error("notification failed: ", error); + } +} + +async function sendProgressNotification(progressToken, progress, total, message) { + if (!progressToken) + return; + try { + const params = { + progressToken, + progress + }; + if (total !== undefined) + params.total = total; + if (message) + params.message = message; + await server.notification({ + method: PROTOCOL.NOTIFICATIONS.PROGRESS, + params + }); + } + catch (error) { + console.error("Progress notification failed: ", error); + } +} + +// Tool definitions +const tools = [ + { + name: "ask-gemini", + description: "model selection [-m], sandbox [-s], and changeMode:boolean for providing edits", + inputSchema: { + type: "object", + properties: { + prompt: { + type: "string", + minLength: 1, + description: "Analysis request. Use @ syntax to include files (e.g., '@largefile.js explain what this does') or ask general questions" + }, + model: { + type: "string", + description: "Optional model to use (e.g., 'gemini-2.5-flash'). If not specified, uses the default model (gemini-2.5-pro)." + }, + sandbox: { + type: "boolean", + default: false, + description: "Use sandbox mode (-s flag) to safely test code changes, execute scripts, or run potentially risky operations in an isolated environment" + }, + changeMode: { + type: "boolean", + default: false, + description: "Enable structured change mode - formats prompts to prevent tool errors and returns structured edit suggestions that Claude can apply directly" + }, + chunkIndex: { + type: ["number", "string"], + description: "Which chunk to return (1-based)" + }, + chunkCacheKey: { + type: "string", + description: "Optional cache key for continuation" + } + }, + required: ["prompt"] + } + }, + { + name: "ping", + description: "Echo", + inputSchema: { + type: "object", + properties: { + prompt: { + type: "string", + default: "", + description: "Message to echo " + } + }, + required: [] + } + }, + { + name: "Help", + description: "receive help information", + inputSchema: { + type: "object", + properties: {}, + required: [] + } + }, + { + name: "brainstorm", + description: "Generate novel ideas with dynamic context gathering. --> Creative frameworks (SCAMPER, Design Thinking, etc.), domain context integration, idea clustering, feasibility analysis, and iterative refinement.", + inputSchema: { + type: "object", + properties: { + prompt: { + type: "string", + minLength: 1, + description: "Primary brainstorming challenge or question to explore" + }, + model: { + type: "string", + description: "Optional model to use (e.g., 'gemini-2.5-flash'). If not specified, uses the default model (gemini-2.5-pro)." + }, + methodology: { + type: "string", + enum: ["divergent", "convergent", "scamper", "design-thinking", "lateral", "auto"], + default: "auto", + description: "Brainstorming framework: 'divergent' (generate many ideas), 'convergent' (refine existing), 'scamper' (systematic triggers), 'design-thinking' (human-centered), 'lateral' (unexpected connections), 'auto' (AI selects best)" + }, + domain: { + type: "string", + description: "Domain context for specialized brainstorming (e.g., 'software', 'business', 'creative', 'research', 'product', 'marketing')" + }, + constraints: { + type: "string", + description: "Known limitations, requirements, or boundaries (budget, time, technical, legal, etc.)" + }, + existingContext: { + type: "string", + description: "Background information, previous attempts, or current state to build upon" + }, + ideaCount: { + type: "integer", + exclusiveMinimum: 0, + default: 12, + description: "Target number of ideas to generate (default: 10-15)" + }, + includeAnalysis: { + type: "boolean", + default: true, + description: "Include feasibility, impact, and implementation analysis for generated ideas" + } + }, + required: ["prompt"] + } + }, + { + name: "fetch-chunk", + description: "Retrieves cached chunks from a changeMode response. Use this to get subsequent chunks after receiving a partial changeMode response.", + inputSchema: { + type: "object", + properties: { + cacheKey: { + type: "string", + description: "The cache key provided in the initial changeMode response" + }, + chunkIndex: { + type: "number", + minimum: 1, + description: "Which chunk to retrieve (1-based index)" + } + }, + required: ["cacheKey", "chunkIndex"] + } + }, + { + name: "timeout-test", + description: "Test timeout prevention by running for a specified duration", + inputSchema: { + type: "object", + properties: { + duration: { + type: "number", + minimum: 10, + description: "Duration in milliseconds (minimum 10ms)" + } + }, + required: ["duration"] + } + } +]; + +// List available tools +server.setRequestHandler(ListToolsRequestSchema, async () => { + return { tools }; +}); + +// Handle tool execution +server.setRequestHandler(CallToolRequestSchema, async (request) => { + const { name, arguments: args } = request.params; + + console.error(`[GMCPT] Tool called: ${name}`); + console.error(`[GMCPT] Arguments:`, JSON.stringify(args, null, 2)); + + try { + switch (name) { + case "ask-gemini": + const { prompt, model, sandbox, changeMode, chunkIndex, chunkCacheKey } = args; + console.error('[GMCPT] ask-gemini tool called with prompt: ' + prompt.substring(0, 50) + '...'); + console.error('[GMCPT] Model: ' + model + ', Sandbox: ' + sandbox + ', ChangeMode: ' + changeMode); + + if (chunkCacheKey && chunkIndex) { + const result = getChunkedEdits(chunkCacheKey, parseInt(chunkIndex)); + return { + content: [{ + type: "text", + text: result + }] + }; + } + + console.error('[GMCPT] About to call executeGeminiCLI...'); + const result = await executeGeminiCLI(prompt, model, sandbox, changeMode); + console.error('[GMCPT] executeGeminiCLI completed with result length: ' + result.length); + return { + content: [{ + type: "text", + text: result + }] + }; + + case "ping": + return { + content: [{ + type: "text", + text: `Pong! ${args.prompt || 'Hello from gemini-cli MCP server!'}` + }] + }; + + case "Help": + return { + content: [{ + type: "text", + text: "Gemini CLI MCP Tool - Fixed Version\n\nAvailable commands:\n- ask-gemini: Interact with Gemini CLI\n- ping: Test connection\n- Help: Show this help\n- brainstorm: Generate novel ideas with creative frameworks\n- fetch-chunk: Retrieve cached chunks from changeMode responses\n- timeout-test: Test timeout prevention" + }] + }; + + case "brainstorm": + const { + prompt: brainstormPrompt, + model: brainstormModel, + methodology, + domain, + constraints, + existingContext, + ideaCount, + includeAnalysis + } = args; + + console.error('[GMCPT] brainstorm tool called with prompt: ' + brainstormPrompt.substring(0, 50) + '...'); + console.error('[GMCPT] Methodology: ' + methodology + ', Domain: ' + domain); + + // Build enhanced brainstorming prompt + let enhancedPrompt = `BRAINSTORMING SESSION\n\nChallenge: ${brainstormPrompt}\n\n`; + + if (methodology && methodology !== 'auto') { + enhancedPrompt += `Framework: Use ${methodology} methodology for idea generation.\n`; + } + + if (domain) { + enhancedPrompt += `Domain Context: ${domain}\n`; + } + + if (constraints) { + enhancedPrompt += `Constraints: ${constraints}\n`; + } + + if (existingContext) { + enhancedPrompt += `Background: ${existingContext}\n`; + } + + enhancedPrompt += `\nGenerate ${ideaCount || 12} creative and diverse ideas. `; + + if (includeAnalysis !== false) { + enhancedPrompt += `For each idea, provide a brief feasibility assessment and potential impact.`; + } + + const brainstormResult = await executeGeminiCLI(enhancedPrompt, brainstormModel, false, false); + return { + content: [{ + type: "text", + text: brainstormResult + }] + }; + + case "fetch-chunk": + const { cacheKey, chunkIndex: fetchChunkIndex } = args; + console.error('[GMCPT] fetch-chunk tool called with cacheKey: ' + cacheKey + ', chunkIndex: ' + fetchChunkIndex); + + const chunkResult = getChunkedEdits(cacheKey, parseInt(fetchChunkIndex)); + return { + content: [{ + type: "text", + text: chunkResult + }] + }; + + case "timeout-test": + const { duration } = args; + console.error('[GMCPT] timeout-test tool called with duration: ' + duration + 'ms'); + + return new Promise((resolve) => { + setTimeout(() => { + resolve({ + content: [{ + type: "text", + text: `Timeout test completed after ${duration}ms` + }] + }); + }, Math.max(10, duration)); + }); + + default: + throw new Error(`Unknown tool: ${name}`); + } + } catch (error) { + console.error(`Error executing ${name}: ${error.message}`); + return { + content: [{ + type: "text", + text: `Error executing ${name}: ${error.message}` + }], + isError: true + }; + } +}); + +// Start the server +async function main() { + const transport = new StdioServerTransport(); + await server.connect(transport); + console.log("[GMCPT] Gemini CLI MCP Server (Fixed) started"); +} + +main().catch((error) => { + console.error("Server failed to start:", error); + process.exit(1); +}); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..b12b731 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,1070 @@ +{ + "name": "gemini-mcp-tool-windows-fixed", + "version": "1.0.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "gemini-mcp-tool-windows-fixed", + "version": "1.0.1", + "license": "MIT", + "dependencies": { + "@modelcontextprotocol/sdk": "^1.17.1", + "dotenv": "^17.2.1" + }, + "bin": { + "gemini-mcp": "index.js" + }, + "devDependencies": {}, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@modelcontextprotocol/sdk": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.17.1.tgz", + "integrity": "sha512-CPle1OQehbWqd25La9Ack5B07StKIxh4+Bf19qnpZKJC1oI22Y0czZHbifjw1UoczIfKBwBDAp/dFxvHG13B5A==", + "license": "MIT", + "dependencies": { + "ajv": "^6.12.6", + "content-type": "^1.0.5", + "cors": "^2.8.5", + "cross-spawn": "^7.0.5", + "eventsource": "^3.0.2", + "eventsource-parser": "^3.0.0", + "express": "^5.0.1", + "express-rate-limit": "^7.5.0", + "pkce-challenge": "^5.0.0", + "raw-body": "^3.0.0", + "zod": "^3.23.8", + "zod-to-json-schema": "^3.24.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "license": "MIT", + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/body-parser": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.0.tgz", + "integrity": "sha512-02qvAaxv8tp7fBa/mw1ga98OGm+eCbqzJOKoRt70sLmfEEi+jyBYVTDGfCL/k06/4EMk/z01gCe7HoCH/f2LTg==", + "license": "MIT", + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.0", + "http-errors": "^2.0.0", + "iconv-lite": "^0.6.3", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.0", + "type-is": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/content-disposition": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.0.tgz", + "integrity": "sha512-Au9nRL8VNUut/XSzbQA38+M78dzP4D+eqg3gfJHMIHHYa3bg067xj1KxMUWj+VULbiZMowKngFFbKczUrNJ1mg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "license": "MIT", + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/dotenv": { + "version": "17.2.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.1.tgz", + "integrity": "sha512-kQhDYKZecqnM0fCnzI5eIv5L4cAe/iRI+HqMbO/hbRdTAeXDG+M9FjipUxNfbARuEg4iHIbhnhs78BCHNbSxEQ==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventsource": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-3.0.7.tgz", + "integrity": "sha512-CRT1WTyuQoD771GW56XEZFQ/ZoSfWid1alKGDYMmkt2yl8UXrVR4pspqWNEcqKvVIzg6PAltWjxcSSPrboA4iA==", + "license": "MIT", + "dependencies": { + "eventsource-parser": "^3.0.1" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/eventsource-parser": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/eventsource-parser/-/eventsource-parser-3.0.3.tgz", + "integrity": "sha512-nVpZkTMM9rF6AQ9gPJpFsNAMt48wIzB5TQgiTLdHiuO8XEDhUgZEhqKlZWXbIzo9VmJ/HvysHqEaVeD5v9TPvA==", + "license": "MIT", + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/express": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/express/-/express-5.1.0.tgz", + "integrity": "sha512-DT9ck5YIRU+8GYzzU5kT3eHGA5iL+1Zd0EutOmTE9Dtk+Tvuzd23VBU+ec7HPNSTxXYO55gPV/hq4pSBJDjFpA==", + "license": "MIT", + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.0", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express-rate-limit": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.1.tgz", + "integrity": "sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/express-rate-limit" + }, + "peerDependencies": { + "express": ">= 4.11" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "license": "MIT" + }, + "node_modules/finalhandler": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.0.tgz", + "integrity": "sha512-/t88Ty3d5JWQbWYgaOGCCYfXRwV1+be02WqYYlL6h0lEiUAMPM8o8qKGO01YIkOHzka2up08wvgYD0mDiI+q3Q==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "license": "MIT" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.1.tgz", + "integrity": "sha512-xRc4oEhT6eaBpU1XF7AjpOFD+xQmXNB5OVKwp4tqCuBpHLS/ZbBDrc07mYTDqVMg6PfxUjjNp85O6Cd2Z/5HWA==", + "license": "MIT", + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-to-regexp": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", + "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/pkce-challenge": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkce-challenge/-/pkce-challenge-5.0.0.tgz", + "integrity": "sha512-ueGLflrrnvwB3xuo/uGob5pd5FN7l0MsLf0Z87o/UQmRtwjvfylfc9MurIxRAWywCYTgrvpXBcqjV4OfCYGCIQ==", + "license": "MIT", + "engines": { + "node": ">=16.20.0" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.0.tgz", + "integrity": "sha512-RmkhL8CAyCRPXCE28MMH0z2PNWQBNk2Q09ZdxM9IOOXwxwZbN+qbWaatPkdkWIKL2ZVDImrN/pK5HTRz2PcS4g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.6.3", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/send": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.0.tgz", + "integrity": "sha512-uaW0WwXKpL9blXE2o0bRhoL2EGXIrZxQ2ZQ4mgcfoBxdFmQold+qWsD2jLrfZ0trjKL6vOw0j//eAwcALFjKSw==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.5", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "mime-types": "^3.0.1", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/serve-static": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.0.tgz", + "integrity": "sha512-61g9pCh0Vnh7IutZjtLGGpTA355+OPn2TyDv/6ivP2h/AdAVX9azsoxmg2/M6nZeQZNYBEwIcsne1mJd9oQItQ==", + "license": "MIT", + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "license": "MIT", + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/zod": { + "version": "3.25.76", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", + "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-to-json-schema": { + "version": "3.24.6", + "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.24.6.tgz", + "integrity": "sha512-h/z3PKvcTcTetyjl1fkj79MHNEjm+HpD6NXheWjzOekY7kV+lwDYnHw+ivHkijnCSMz1yJaWBD9vu/Fcmk+vEg==", + "license": "ISC", + "peerDependencies": { + "zod": "^3.24.1" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..26e72e2 --- /dev/null +++ b/package.json @@ -0,0 +1,51 @@ +{ + "name": "gemini-mcp-tool-windows-fixed", + "version": "1.0.1", + "type": "module", + "description": "Windows-compatible MCP server that enables AI assistants to interact with Google Gemini CLI - Fixed version for Windows environments", + "main": "index.js", + "bin": { + "gemini-mcp": "./index.js" + }, + "scripts": { + "start": "node index.js", + "test": "node test-fixed-mcp.js", + "dev": "node index.js" + }, + "keywords": [ + "mcp", + "model-context-protocol", + "gemini", + "google-gemini", + "ai", + "claude", + "cli", + "windows", + "powershell", + "fixed" + ], + "author": "Windows Fixed Version", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/your-username/gemini-mcp-tool-windows-fixed.git" + }, + "bugs": { + "url": "https://github.com/your-username/gemini-mcp-tool-windows-fixed/issues" + }, + "homepage": "https://github.com/your-username/gemini-mcp-tool-windows-fixed#readme", + "engines": { + "node": ">=16.0.0" + }, + "dependencies": { + "@modelcontextprotocol/sdk": "^1.17.1", + "dotenv": "^17.2.1" + }, + "devDependencies": {}, + "files": [ + "index.js", + "lib/", + "README.md", + "LICENSE" + ] +} From 3ab0310d820991b3ce0a846cead8eb53a84f7dc5 Mon Sep 17 00:00:00 2001 From: User Date: Mon, 4 Aug 2025 05:54:37 +0800 Subject: [PATCH 02/28] Fix PowerShell execution error - v1.0.2 --- lib/fixed-geminiExecutor.js | 19 ++++++++++++++++--- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/lib/fixed-geminiExecutor.js b/lib/fixed-geminiExecutor.js index 1775ed3..f03a52c 100644 --- a/lib/fixed-geminiExecutor.js +++ b/lib/fixed-geminiExecutor.js @@ -13,6 +13,19 @@ import { ERROR_MESSAGES, STATUS_MESSAGES, MODELS, CLI } from './fixed-constants. // Simple chunk cache implementation const chunkCache = new Map(); +// Function to get PowerShell executable based on platform +function getPowerShellExecutable() { + // On Windows, try powershell.exe first (Windows PowerShell), then pwsh (PowerShell Core) + if (process.platform === 'win32') { + return 'powershell.exe'; + } + // On other platforms, use pwsh (PowerShell Core) + return 'pwsh'; +} + +const POWERSHELL_EXECUTABLE = getPowerShellExecutable(); +console.log(`[GMCPT] Using PowerShell executable: ${POWERSHELL_EXECUTABLE}`); + function cacheChunks(key, chunks) { chunkCache.set(key, chunks); } @@ -38,12 +51,12 @@ async function executeCommandWithPipedInput(command, input, env, onProgress) { console.log(`[GMCPT] Input length: ${input.length}`); console.log(`[GMCPT] GEMINI_API_KEY in env: ${env.GEMINI_API_KEY ? 'YES' : 'NO'}`); - const childProcess = spawn('powershell.exe', ['-Command', `${command} ${args.join(' ')}`], { + const childProcess = spawn(POWERSHELL_EXECUTABLE, ['-Command', command], { env: env, stdio: ['pipe', 'pipe', 'pipe'] }); - console.log(`[GMCPT] Spawned process with command: powershell.exe -Command "${command} ${args.join(' ')}"`); + console.log(`[GMCPT] Spawned process with command: ${POWERSHELL_EXECUTABLE} -Command "${command}"`); let stdout = ''; let stderr = ''; @@ -90,7 +103,7 @@ async function executeCommandWithEnv(command, args, env, onProgress) { console.log(`[GMCPT] GEMINI_API_KEY in env: ${env.GEMINI_API_KEY ? 'YES' : 'NO'}`); console.log(`Executing with custom env: ${command} ${args.join(' ')}`); const psCommand = `& "${command}" ${args.map(arg => `'${arg.replace(/'/g, "''")}'`).join(' ')}`; - const childProcess = spawn('powershell.exe', ['-Command', psCommand], { + const childProcess = spawn(POWERSHELL_EXECUTABLE, ['-Command', psCommand], { env: env, stdio: ['pipe', 'pipe', 'pipe'] }); diff --git a/package-lock.json b/package-lock.json index b12b731..a17cf1b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "gemini-mcp-tool-windows-fixed", - "version": "1.0.1", + "version": "1.0.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "gemini-mcp-tool-windows-fixed", - "version": "1.0.1", + "version": "1.0.2", "license": "MIT", "dependencies": { "@modelcontextprotocol/sdk": "^1.17.1", diff --git a/package.json b/package.json index 26e72e2..992a82f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gemini-mcp-tool-windows-fixed", - "version": "1.0.1", + "version": "1.0.2", "type": "module", "description": "Windows-compatible MCP server that enables AI assistants to interact with Google Gemini CLI - Fixed version for Windows environments", "main": "index.js", From eee8da2ffc9b0d67f0a88543ce2ca33dc1b2d608 Mon Sep 17 00:00:00 2001 From: User Date: Mon, 4 Aug 2025 05:57:46 +0800 Subject: [PATCH 03/28] Fix PowerShell execution error - v1.0.2 - Fixed undefined 'args' variable in executeCommandWithPipedInput function - Added PowerShell executable detection for better Windows compatibility - Updated to use powershell.exe on Windows and pwsh on other platforms - Resolves 'spawn powershell.exe ENOENT' error - Tested and verified ask-gemini functionality works correctly --- lib/fixed-geminiExecutor.js | 580 ++++++++++++++++++------------------ package.json | 102 +++---- 2 files changed, 341 insertions(+), 341 deletions(-) diff --git a/lib/fixed-geminiExecutor.js b/lib/fixed-geminiExecutor.js index f03a52c..307ef9a 100644 --- a/lib/fixed-geminiExecutor.js +++ b/lib/fixed-geminiExecutor.js @@ -1,291 +1,291 @@ -import dotenv from 'dotenv'; -import path from 'path'; -import { fileURLToPath } from 'url'; -// import { executeCommand } from './package/dist/utils/commandExecutor.js'; // Removed - using built-in spawn -import { spawn } from 'child_process'; -// import { Logger } from './package/dist/utils/logger.js'; // Removed - using console instead -import { ERROR_MESSAGES, STATUS_MESSAGES, MODELS, CLI } from './fixed-constants.js'; -// import { parseChangeModeOutput, validateChangeModeEdits } from './package/dist/utils/changeModeParser.js'; // Removed - simplified -// import { formatChangeModeResponse, summarizeChangeModeEdits } from './package/dist/utils/changeModeTranslator.js'; // Removed - simplified -// import { chunkChangeModeEdits } from './package/dist/utils/changeModeChunker.js'; // Removed - simplified -// import { cacheChunks, getChunks } from './package/dist/utils/chunkCache.js'; // Removed - simplified - -// Simple chunk cache implementation -const chunkCache = new Map(); - -// Function to get PowerShell executable based on platform -function getPowerShellExecutable() { - // On Windows, try powershell.exe first (Windows PowerShell), then pwsh (PowerShell Core) - if (process.platform === 'win32') { - return 'powershell.exe'; - } - // On other platforms, use pwsh (PowerShell Core) - return 'pwsh'; -} - -const POWERSHELL_EXECUTABLE = getPowerShellExecutable(); -console.log(`[GMCPT] Using PowerShell executable: ${POWERSHELL_EXECUTABLE}`); - -function cacheChunks(key, chunks) { - chunkCache.set(key, chunks); -} - -function getChunks(key) { - return chunkCache.get(key) || []; -} - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); -dotenv.config({ path: path.join(__dirname, '.env') }); - -// Debug: Check if environment variable is loaded -console.log('GEMINI_API_KEY loaded:', process.env.GEMINI_API_KEY ? 'YES' : 'NO'); -console.log('Current working directory:', process.cwd()); -console.log('Script directory:', __dirname); -console.log('Env file path:', path.join(__dirname, '.env')); - -// Custom executeCommand function that accepts custom environment variables -async function executeCommandWithPipedInput(command, input, env, onProgress) { - return new Promise((resolve, reject) => { - console.log(`[GMCPT] Executing command with piped input: ${command}`); - console.log(`[GMCPT] Input length: ${input.length}`); - console.log(`[GMCPT] GEMINI_API_KEY in env: ${env.GEMINI_API_KEY ? 'YES' : 'NO'}`); - - const childProcess = spawn(POWERSHELL_EXECUTABLE, ['-Command', command], { - env: env, - stdio: ['pipe', 'pipe', 'pipe'] - }); - - console.log(`[GMCPT] Spawned process with command: ${POWERSHELL_EXECUTABLE} -Command "${command}"`); - - let stdout = ''; - let stderr = ''; - - // Write input to stdin and close it - childProcess.stdin.write(input); - childProcess.stdin.end(); - - childProcess.stdout.on('data', (data) => { - stdout += data.toString(); - if (onProgress) { - onProgress(data.toString()); - } - }); - - childProcess.stderr.on('data', (data) => { - stderr += data.toString(); - }); - - childProcess.on('error', (error) => { - console.log(`[GMCPT] Command execution error: ${error.message}`); - reject(error); - }); - - childProcess.on('close', (code) => { - console.log(`[GMCPT] Command exited with code: ${code}`); - console.log(`[GMCPT] stdout length: ${stdout.length}`); - console.log(`[GMCPT] stderr length: ${stderr.length}`); - console.log(`[GMCPT] stdout content: ${stdout.substring(0, 500)}...`); - console.log(`[GMCPT] stderr content: ${stderr.substring(0, 200)}...`); - if (code === 0) { - resolve({ stdout, stderr }); - } else { - reject(new Error(`Command failed with exit code ${code}: ${stderr}`)); - } - }); - }); -} - -async function executeCommandWithEnv(command, args, env, onProgress) { - return new Promise((resolve, reject) => { - console.log(`[GMCPT] Executing command: ${command} ${args.join(' ')}`); - console.log(`[GMCPT] Environment variables count: ${Object.keys(env).length}`); - console.log(`[GMCPT] GEMINI_API_KEY in env: ${env.GEMINI_API_KEY ? 'YES' : 'NO'}`); - console.log(`Executing with custom env: ${command} ${args.join(' ')}`); - const psCommand = `& "${command}" ${args.map(arg => `'${arg.replace(/'/g, "''")}'`).join(' ')}`; - const childProcess = spawn(POWERSHELL_EXECUTABLE, ['-Command', psCommand], { - env: env, - stdio: ['pipe', 'pipe', 'pipe'] - }); - - console.log(`[GMCPT] Executing with PowerShell: ${psCommand}`); - - let stdout = ''; - let stderr = ''; - - childProcess.stdout.on('data', (data) => { - stdout += data.toString(); - if (onProgress) { - onProgress(data.toString()); - } - }); - - childProcess.stderr.on('data', (data) => { - stderr += data.toString(); - }); - - childProcess.on('error', (error) => { - console.error(`Command execution error: ${error.message}`); - reject(error); - }); - - childProcess.on('close', (code) => { - console.log(`[GMCPT] Command exited with code: ${code}`); - console.log(`[GMCPT] stdout length: ${stdout.length}`); - console.log(`[GMCPT] stderr length: ${stderr.length}`); - console.log(`[GMCPT] stdout content: ${stdout.substring(0, 200)}...`); - console.log(`[GMCPT] stderr content: ${stderr.substring(0, 200)}...`); - console.log(`Command exited with code: ${code}`); - if (code === 0) { - resolve({ stdout, stderr }); - } else { - reject(new Error(`Command failed with exit code ${code}: ${stderr}`)); - } - }); - }); -} - -export async function executeGeminiCLI(prompt, model, sandbox, changeMode, onProgress) { - console.log('executeGeminiCLI called with prompt: ' + prompt.substring(0, 50) + '...'); - console.log('API Key available: ' + (process.env.GEMINI_API_KEY ? 'YES' : 'NO')); - let prompt_processed = prompt; - if (changeMode) { - prompt_processed = prompt.replace(/file:(\S+)/g, '@$1'); - const changeModeInstructions = ` -[CHANGEMODE INSTRUCTIONS] -You are generating code modifications that will be processed by an automated system. The output format is critical because it enables programmatic application of changes without human intervention. - -INSTRUCTIONS: -1. Analyze each provided file thoroughly -2. Identify locations requiring changes based on the user request -3. For each change, output in the exact format specified -4. The OLD section must be EXACTLY what appears in the file (copy-paste exact match) -5. Provide complete, directly replacing code blocks -6. Verify line numbers are accurate - -CRITICAL REQUIREMENTS: -1. Output edits in the EXACT format specified below - no deviations -2. The OLD string MUST be findable with Ctrl+F - it must be a unique, exact match -3. Include enough surrounding lines to make the OLD string unique -4. If a string appears multiple times (like ), include enough context lines above and below to make it unique -5. Copy the OLD content EXACTLY as it appears - including all whitespace, indentation, line breaks -6. Never use partial lines - always include complete lines from start to finish - -OUTPUT FORMAT (follow exactly): -**FILE: [filename]:[line_number]** -\`\`\` -OLD: -[exact code to be replaced - must match file content precisely] -NEW: -[new code to insert - complete and functional] -\`\`\` - -EXAMPLE 1 - Simple unique match: -**FILE: src/utils/helper.js:100** -\`\`\` -OLD: -function getMessage() { - return "Hello World"; -} -NEW: -function getMessage() { - return "Hello Universe!"; -\`\`\` -`; - prompt_processed = changeModeInstructions + "\n\n" + prompt_processed; - } - - const args = []; - - if (model && model !== MODELS.PRO) { - args.push(CLI.FLAGS.MODEL, model); - } - - if (sandbox) { - args.push(CLI.FLAGS.SANDBOX); - } - - args.push(CLI.FLAGS.PROMPT, prompt_processed); - - console.log(`Executing: ${CLI.COMMANDS.GEMINI} ${args.join(' ')}`); - - try { - // Create custom environment with GEMINI_API_KEY explicitly set - const customEnv = { - ...process.env, - GEMINI_API_KEY: process.env.GEMINI_API_KEY - }; - - console.log('[GMCPT] Using GEMINI_API_KEY: ' + (customEnv.GEMINI_API_KEY ? 'SET' : 'NOT SET')); - console.log('[GMCPT] Executing gemini command: ' + CLI.COMMANDS.GEMINI + ' ' + args.join(' ')); - - // Execute gemini command directly with custom environment - const result = await executeCommandWithEnv(CLI.COMMANDS.GEMINI, args, customEnv, onProgress); - - if (changeMode && result.stdout) { - try { - // Simple change mode processing - split by lines for chunking - const lines = result.stdout.split('\n'); - const chunks = []; - const chunkSize = 50; // lines per chunk - - for (let i = 0; i < lines.length; i += chunkSize) { - chunks.push(lines.slice(i, i + chunkSize).join('\n')); - } - - if (chunks.length > 1) { - const cacheKey = `change_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; - cacheChunks(cacheKey, chunks); - - return { - content: chunks[0], - chunk: 1, - totalChunks: chunks.length, - cacheKey: cacheKey, - hasMore: true - }; - } else { - return { - content: result.stdout, - chunk: 1, - totalChunks: 1, - hasMore: false - }; - } - } catch (parseError) { - console.error(`Failed to parse change mode output: ${parseError.message}`); - return result.stdout; - } - } - - return result.stdout; - } catch (error) { - console.error(`Gemini CLI execution failed: ${error.message}`); - throw error; - } -} - -export function getChunkedEdits(cacheKey, chunkIndex) { - try { - const chunks = getChunks(cacheKey); - if (!chunks || chunks.length === 0) { - throw new Error('No cached chunks found for the provided cache key'); - } - - const chunk = chunks[chunkIndex - 1]; // Convert to 0-based index - if (!chunk) { - throw new Error(`Chunk ${chunkIndex} not found. Available chunks: 1-${chunks.length}`); - } - - return { - content: chunk, - chunk: chunkIndex, - totalChunks: chunks.length, - cacheKey: cacheKey, - hasMore: chunkIndex < chunks.length - }; - } catch (error) { - console.error(`Failed to retrieve chunk: ${error.message}`); - throw error; - } +import dotenv from 'dotenv'; +import path from 'path'; +import { fileURLToPath } from 'url'; +// import { executeCommand } from './package/dist/utils/commandExecutor.js'; // Removed - using built-in spawn +import { spawn } from 'child_process'; +// import { Logger } from './package/dist/utils/logger.js'; // Removed - using console instead +import { ERROR_MESSAGES, STATUS_MESSAGES, MODELS, CLI } from './fixed-constants.js'; +// import { parseChangeModeOutput, validateChangeModeEdits } from './package/dist/utils/changeModeParser.js'; // Removed - simplified +// import { formatChangeModeResponse, summarizeChangeModeEdits } from './package/dist/utils/changeModeTranslator.js'; // Removed - simplified +// import { chunkChangeModeEdits } from './package/dist/utils/changeModeChunker.js'; // Removed - simplified +// import { cacheChunks, getChunks } from './package/dist/utils/chunkCache.js'; // Removed - simplified + +// Simple chunk cache implementation +const chunkCache = new Map(); + +// Function to get PowerShell executable based on platform +function getPowerShellExecutable() { + // On Windows, try powershell.exe first (Windows PowerShell), then pwsh (PowerShell Core) + if (process.platform === 'win32') { + return 'powershell.exe'; + } + // On other platforms, use pwsh (PowerShell Core) + return 'pwsh'; +} + +const POWERSHELL_EXECUTABLE = getPowerShellExecutable(); +console.log(`[GMCPT] Using PowerShell executable: ${POWERSHELL_EXECUTABLE}`); + +function cacheChunks(key, chunks) { + chunkCache.set(key, chunks); +} + +function getChunks(key) { + return chunkCache.get(key) || []; +} + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +dotenv.config({ path: path.join(__dirname, '.env') }); + +// Debug: Check if environment variable is loaded +console.log('GEMINI_API_KEY loaded:', process.env.GEMINI_API_KEY ? 'YES' : 'NO'); +console.log('Current working directory:', process.cwd()); +console.log('Script directory:', __dirname); +console.log('Env file path:', path.join(__dirname, '.env')); + +// Custom executeCommand function that accepts custom environment variables +async function executeCommandWithPipedInput(command, input, env, onProgress) { + return new Promise((resolve, reject) => { + console.log(`[GMCPT] Executing command with piped input: ${command}`); + console.log(`[GMCPT] Input length: ${input.length}`); + console.log(`[GMCPT] GEMINI_API_KEY in env: ${env.GEMINI_API_KEY ? 'YES' : 'NO'}`); + + const childProcess = spawn(POWERSHELL_EXECUTABLE, ['-Command', command], { + env: env, + stdio: ['pipe', 'pipe', 'pipe'] + }); + + console.log(`[GMCPT] Spawned process with command: ${POWERSHELL_EXECUTABLE} -Command "${command}"`); + + let stdout = ''; + let stderr = ''; + + // Write input to stdin and close it + childProcess.stdin.write(input); + childProcess.stdin.end(); + + childProcess.stdout.on('data', (data) => { + stdout += data.toString(); + if (onProgress) { + onProgress(data.toString()); + } + }); + + childProcess.stderr.on('data', (data) => { + stderr += data.toString(); + }); + + childProcess.on('error', (error) => { + console.log(`[GMCPT] Command execution error: ${error.message}`); + reject(error); + }); + + childProcess.on('close', (code) => { + console.log(`[GMCPT] Command exited with code: ${code}`); + console.log(`[GMCPT] stdout length: ${stdout.length}`); + console.log(`[GMCPT] stderr length: ${stderr.length}`); + console.log(`[GMCPT] stdout content: ${stdout.substring(0, 500)}...`); + console.log(`[GMCPT] stderr content: ${stderr.substring(0, 200)}...`); + if (code === 0) { + resolve({ stdout, stderr }); + } else { + reject(new Error(`Command failed with exit code ${code}: ${stderr}`)); + } + }); + }); +} + +async function executeCommandWithEnv(command, args, env, onProgress) { + return new Promise((resolve, reject) => { + console.log(`[GMCPT] Executing command: ${command} ${args.join(' ')}`); + console.log(`[GMCPT] Environment variables count: ${Object.keys(env).length}`); + console.log(`[GMCPT] GEMINI_API_KEY in env: ${env.GEMINI_API_KEY ? 'YES' : 'NO'}`); + console.log(`Executing with custom env: ${command} ${args.join(' ')}`); + const psCommand = `& "${command}" ${args.map(arg => `'${arg.replace(/'/g, "''")}'`).join(' ')}`; + const childProcess = spawn(POWERSHELL_EXECUTABLE, ['-Command', psCommand], { + env: env, + stdio: ['pipe', 'pipe', 'pipe'] + }); + + console.log(`[GMCPT] Executing with PowerShell: ${psCommand}`); + + let stdout = ''; + let stderr = ''; + + childProcess.stdout.on('data', (data) => { + stdout += data.toString(); + if (onProgress) { + onProgress(data.toString()); + } + }); + + childProcess.stderr.on('data', (data) => { + stderr += data.toString(); + }); + + childProcess.on('error', (error) => { + console.error(`Command execution error: ${error.message}`); + reject(error); + }); + + childProcess.on('close', (code) => { + console.log(`[GMCPT] Command exited with code: ${code}`); + console.log(`[GMCPT] stdout length: ${stdout.length}`); + console.log(`[GMCPT] stderr length: ${stderr.length}`); + console.log(`[GMCPT] stdout content: ${stdout.substring(0, 200)}...`); + console.log(`[GMCPT] stderr content: ${stderr.substring(0, 200)}...`); + console.log(`Command exited with code: ${code}`); + if (code === 0) { + resolve({ stdout, stderr }); + } else { + reject(new Error(`Command failed with exit code ${code}: ${stderr}`)); + } + }); + }); +} + +export async function executeGeminiCLI(prompt, model, sandbox, changeMode, onProgress) { + console.log('executeGeminiCLI called with prompt: ' + prompt.substring(0, 50) + '...'); + console.log('API Key available: ' + (process.env.GEMINI_API_KEY ? 'YES' : 'NO')); + let prompt_processed = prompt; + if (changeMode) { + prompt_processed = prompt.replace(/file:(\S+)/g, '@$1'); + const changeModeInstructions = ` +[CHANGEMODE INSTRUCTIONS] +You are generating code modifications that will be processed by an automated system. The output format is critical because it enables programmatic application of changes without human intervention. + +INSTRUCTIONS: +1. Analyze each provided file thoroughly +2. Identify locations requiring changes based on the user request +3. For each change, output in the exact format specified +4. The OLD section must be EXACTLY what appears in the file (copy-paste exact match) +5. Provide complete, directly replacing code blocks +6. Verify line numbers are accurate + +CRITICAL REQUIREMENTS: +1. Output edits in the EXACT format specified below - no deviations +2. The OLD string MUST be findable with Ctrl+F - it must be a unique, exact match +3. Include enough surrounding lines to make the OLD string unique +4. If a string appears multiple times (like ), include enough context lines above and below to make it unique +5. Copy the OLD content EXACTLY as it appears - including all whitespace, indentation, line breaks +6. Never use partial lines - always include complete lines from start to finish + +OUTPUT FORMAT (follow exactly): +**FILE: [filename]:[line_number]** +\`\`\` +OLD: +[exact code to be replaced - must match file content precisely] +NEW: +[new code to insert - complete and functional] +\`\`\` + +EXAMPLE 1 - Simple unique match: +**FILE: src/utils/helper.js:100** +\`\`\` +OLD: +function getMessage() { + return "Hello World"; +} +NEW: +function getMessage() { + return "Hello Universe!"; +\`\`\` +`; + prompt_processed = changeModeInstructions + "\n\n" + prompt_processed; + } + + const args = []; + + if (model && model !== MODELS.PRO) { + args.push(CLI.FLAGS.MODEL, model); + } + + if (sandbox) { + args.push(CLI.FLAGS.SANDBOX); + } + + args.push(CLI.FLAGS.PROMPT, prompt_processed); + + console.log(`Executing: ${CLI.COMMANDS.GEMINI} ${args.join(' ')}`); + + try { + // Create custom environment with GEMINI_API_KEY explicitly set + const customEnv = { + ...process.env, + GEMINI_API_KEY: process.env.GEMINI_API_KEY + }; + + console.log('[GMCPT] Using GEMINI_API_KEY: ' + (customEnv.GEMINI_API_KEY ? 'SET' : 'NOT SET')); + console.log('[GMCPT] Executing gemini command: ' + CLI.COMMANDS.GEMINI + ' ' + args.join(' ')); + + // Execute gemini command directly with custom environment + const result = await executeCommandWithEnv(CLI.COMMANDS.GEMINI, args, customEnv, onProgress); + + if (changeMode && result.stdout) { + try { + // Simple change mode processing - split by lines for chunking + const lines = result.stdout.split('\n'); + const chunks = []; + const chunkSize = 50; // lines per chunk + + for (let i = 0; i < lines.length; i += chunkSize) { + chunks.push(lines.slice(i, i + chunkSize).join('\n')); + } + + if (chunks.length > 1) { + const cacheKey = `change_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; + cacheChunks(cacheKey, chunks); + + return { + content: chunks[0], + chunk: 1, + totalChunks: chunks.length, + cacheKey: cacheKey, + hasMore: true + }; + } else { + return { + content: result.stdout, + chunk: 1, + totalChunks: 1, + hasMore: false + }; + } + } catch (parseError) { + console.error(`Failed to parse change mode output: ${parseError.message}`); + return result.stdout; + } + } + + return result.stdout; + } catch (error) { + console.error(`Gemini CLI execution failed: ${error.message}`); + throw error; + } +} + +export function getChunkedEdits(cacheKey, chunkIndex) { + try { + const chunks = getChunks(cacheKey); + if (!chunks || chunks.length === 0) { + throw new Error('No cached chunks found for the provided cache key'); + } + + const chunk = chunks[chunkIndex - 1]; // Convert to 0-based index + if (!chunk) { + throw new Error(`Chunk ${chunkIndex} not found. Available chunks: 1-${chunks.length}`); + } + + return { + content: chunk, + chunk: chunkIndex, + totalChunks: chunks.length, + cacheKey: cacheKey, + hasMore: chunkIndex < chunks.length + }; + } catch (error) { + console.error(`Failed to retrieve chunk: ${error.message}`); + throw error; + } } \ No newline at end of file diff --git a/package.json b/package.json index 992a82f..aaa53ae 100644 --- a/package.json +++ b/package.json @@ -1,51 +1,51 @@ -{ - "name": "gemini-mcp-tool-windows-fixed", - "version": "1.0.2", - "type": "module", - "description": "Windows-compatible MCP server that enables AI assistants to interact with Google Gemini CLI - Fixed version for Windows environments", - "main": "index.js", - "bin": { - "gemini-mcp": "./index.js" - }, - "scripts": { - "start": "node index.js", - "test": "node test-fixed-mcp.js", - "dev": "node index.js" - }, - "keywords": [ - "mcp", - "model-context-protocol", - "gemini", - "google-gemini", - "ai", - "claude", - "cli", - "windows", - "powershell", - "fixed" - ], - "author": "Windows Fixed Version", - "license": "MIT", - "repository": { - "type": "git", - "url": "https://github.com/your-username/gemini-mcp-tool-windows-fixed.git" - }, - "bugs": { - "url": "https://github.com/your-username/gemini-mcp-tool-windows-fixed/issues" - }, - "homepage": "https://github.com/your-username/gemini-mcp-tool-windows-fixed#readme", - "engines": { - "node": ">=16.0.0" - }, - "dependencies": { - "@modelcontextprotocol/sdk": "^1.17.1", - "dotenv": "^17.2.1" - }, - "devDependencies": {}, - "files": [ - "index.js", - "lib/", - "README.md", - "LICENSE" - ] -} +{ + "name": "gemini-mcp-tool-windows-fixed", + "version": "1.0.2", + "type": "module", + "description": "Windows-compatible MCP server that enables AI assistants to interact with Google Gemini CLI - Fixed version for Windows environments", + "main": "index.js", + "bin": { + "gemini-mcp": "./index.js" + }, + "scripts": { + "start": "node index.js", + "test": "node test-fixed-mcp.js", + "dev": "node index.js" + }, + "keywords": [ + "mcp", + "model-context-protocol", + "gemini", + "google-gemini", + "ai", + "claude", + "cli", + "windows", + "powershell", + "fixed" + ], + "author": "Windows Fixed Version", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/your-username/gemini-mcp-tool-windows-fixed.git" + }, + "bugs": { + "url": "https://github.com/your-username/gemini-mcp-tool-windows-fixed/issues" + }, + "homepage": "https://github.com/your-username/gemini-mcp-tool-windows-fixed#readme", + "engines": { + "node": ">=16.0.0" + }, + "dependencies": { + "@modelcontextprotocol/sdk": "^1.17.1", + "dotenv": "^17.2.1" + }, + "devDependencies": {}, + "files": [ + "index.js", + "lib/", + "README.md", + "LICENSE" + ] +} From d0d37988587bde839f28f3109f640f34986d85c9 Mon Sep 17 00:00:00 2001 From: User Date: Mon, 4 Aug 2025 06:05:15 +0800 Subject: [PATCH 04/28] Update documentation for v1.0.2 release - Add version changelog and update information - Update installation instructions to specify v1.0.2 - Add troubleshooting section for PowerShell execution errors - Include upgrade instructions for existing users - Highlight fixes for 'spawn powershell.exe ENOENT' error --- INSTALL-GUIDE.md | 71 ++++- README.md | 689 ++++++++++++++++++++++++----------------------- 2 files changed, 421 insertions(+), 339 deletions(-) diff --git a/INSTALL-GUIDE.md b/INSTALL-GUIDE.md index e66a9be..0453fe1 100644 --- a/INSTALL-GUIDE.md +++ b/INSTALL-GUIDE.md @@ -1,5 +1,21 @@ # 🚀 Gemini MCP Tool - Windows Fixed Version Installation Guide +> **最新版本 v1.0.2** - 修复了 PowerShell 执行错误,解决了 `spawn powershell.exe ENOENT` 问题 + +## 🆕 版本更新日志 + +### v1.0.2 (最新) +- ✅ **修复 PowerShell 执行错误** - 解决 `spawn powershell.exe ENOENT` 问题 +- ✅ **改进 Windows 兼容性** - 自动检测可用的 PowerShell 版本 +- ✅ **修复未定义变量错误** - 修复 `executeCommandWithPipedInput` 函数中的 `args` 变量问题 +- ✅ **增强错误处理** - 更好的错误信息和调试输出 + +### v1.0.1 +- 基础 Windows 兼容性修复 + +### v1.0.0 +- 初始版本 + ## 📋 Prerequisites 1. **Node.js** (v16.0.0 or higher) @@ -26,20 +42,38 @@ ### Method 1: NPX (Recommended) ```powershell -# Test the tool -npx -y gemini-mcp-tool-windows-fixed +# 使用最新版本 (推荐) +npx gemini-mcp-tool-windows-fixed@1.0.2 + +# 或者使用最新版本标签 +npx -y gemini-mcp-tool-windows-fixed@latest ``` ### Method 2: Global Installation ```powershell -# Install globally -npm install -g gemini-mcp-tool-windows-fixed +# 安装最新版本 +npm install -g gemini-mcp-tool-windows-fixed@1.0.2 -# Test the tool +# 测试工具 gemini-mcp-tool-windows-fixed ``` +### Method 3: 更新现有安装 + +如果您之前安装了旧版本,请先更新: + +```powershell +# 卸载旧版本 +npm uninstall -g gemini-mcp-tool-windows-fixed + +# 清除缓存 +npm cache clean --force + +# 安装最新版本 +npm install -g gemini-mcp-tool-windows-fixed@1.0.2 +``` + ## ⚙️ MCP Client Configuration ### For Trae AI @@ -173,9 +207,34 @@ Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser npm cache clean --force # Reinstall -npm install -g gemini-mcp-tool-windows-fixed +npm install -g gemini-mcp-tool-windows-fixed@1.0.2 ``` +#### 5. "spawn powershell.exe ENOENT" 错误 + +这个错误在 v1.0.2 中已修复。如果仍然遇到此错误: + +```powershell +# 确保使用最新版本 +npm uninstall -g gemini-mcp-tool-windows-fixed +npm cache clean --force +npm install -g gemini-mcp-tool-windows-fixed@1.0.2 + +# 或使用 npx +npx gemini-mcp-tool-windows-fixed@1.0.2 +``` + +**原因:** 旧版本 (v1.0.0, v1.0.1) 存在 PowerShell 执行路径问题 +**解决方案:** 更新到 v1.0.2 或更高版本 + +#### 6. PowerShell 版本兼容性 + +工具会自动检测可用的 PowerShell 版本: +- Windows PowerShell (powershell.exe) +- PowerShell Core (pwsh) + +如果遇到问题,请确保至少安装了其中一个版本。 + ### Debug Mode Enable debug logging: diff --git a/README.md b/README.md index fde9e09..bbdd584 100644 --- a/README.md +++ b/README.md @@ -1,333 +1,356 @@ -# 🚀 Gemini MCP Tool - Windows Fixed Version - -[![npm version](https://badge.fury.io/js/gemini-mcp-tool-windows-fixed.svg)](https://badge.fury.io/js/gemini-mcp-tool-windows-fixed) -[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) - -A **Windows-compatible** Model Context Protocol (MCP) server that enables AI assistants to interact with Google's Gemini CLI. This is a fixed version specifically designed to work seamlessly on Windows environments with PowerShell support. - -> **Note**: This is an enhanced version of the [original gemini-mcp-tool](https://github.com/jamubc/gemini-mcp-tool) with Windows-specific fixes and improvements. - -## ✨ Features - -- **🪟 Windows Compatible**: Full PowerShell support with Windows-specific path handling -- **📊 Large Context Window**: Leverage Gemini's massive token window for analyzing entire codebases -- **📁 File Analysis**: Analyze files using `@filename` syntax -- **🔒 Sandbox Mode**: Safe code execution environment -- **🔗 MCP Integration**: Seamless integration with MCP-compatible AI assistants (Trae AI, Claude Desktop) -- **⚡ NPX Ready**: Easy installation and usage with NPX -- **🔧 Environment Variable Support**: Flexible API key configuration - -This Windows-fixed version resolves: -- PowerShell parameter passing issues -- Character encoding problems with Chinese/Unicode text -- Command line argument escaping on Windows -- Environment variable handling - -## 📋 Prerequisites - -1. **Node.js** (v16.0.0 or higher) - ```powershell - node --version # Should be v16+ - ``` - -2. **Google Gemini CLI**: Install the Gemini CLI tool - ```powershell - npm install -g @google/generative-ai-cli - - # Verify installation - gemini --version - ``` - -3. **API Key**: Get your API key from [Google AI Studio](https://makersuite.google.com/app/apikey) - -## 📦 Installation - -### Quick Start with NPX (Recommended) - -```powershell -# Test the tool immediately -npx -y gemini-mcp-tool-windows-fixed -``` - -### Global Installation - -```powershell -# Install globally -npm install -g gemini-mcp-tool-windows-fixed - -# Run the tool -gemini-mcp-tool-windows-fixed -``` - -## ⚙️ MCP Client Configuration - -### Trae AI (Recommended) - -1. Open: `%APPDATA%\Trae\User\mcp.json` -2. Add this configuration: - -```json -{ - "mcpServers": { - "gemini-cli": { - "name": "gemini-cli", - "description": "Windows-compatible Gemini MCP Tool", - "baseUrl": "", - "command": "npx", - "args": [ - "-y", - "gemini-mcp-tool-windows-fixed" - ], - "env": { - "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" - }, - "isActive": true, - "providerUrl": "https://github.com/your-username/gemini-mcp-tool-windows-fixed" - } - } -} -``` - -### Claude Desktop - -1. Open: `%APPDATA%\Claude\claude_desktop_config.json` -2. Add this configuration: - -```json -{ - "mcpServers": { - "gemini-cli": { - "command": "npx", - "args": ["-y", "gemini-mcp-tool-windows-fixed"], - "env": { - "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" - } - } - } -} -``` - -## 🔑 API Key Configuration - -### Option 1: MCP Configuration (Recommended) - -Replace `YOUR_ACTUAL_API_KEY_HERE` in the configuration above with your actual API key. - -### Option 2: Environment Variable - -```powershell -# Temporary (current session) -$env:GEMINI_API_KEY = "your-actual-api-key" - -# Permanent (user level) -[Environment]::SetEnvironmentVariable("GEMINI_API_KEY", "your-actual-api-key", "User") - -# Verify -echo $env:GEMINI_API_KEY -``` - -### Configuration File Locations - -**Claude Desktop:** -- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json` -- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json` -- **Linux**: `~/.config/claude/claude_desktop_config.json` - -**Trae AI:** -- **Windows**: `%APPDATA%\Trae\User\mcp.json` - -## 🛠️ Available Tools - -This MCP server provides the following tools for AI assistants: - -### 1. `ask-gemini` -Interact with Google Gemini for analysis and questions. - -**Parameters:** -- `prompt` (required): The analysis request. Use `@` syntax for file references -- `model` (optional): Gemini model to use (default: `gemini-2.5-pro`) -- `sandbox` (optional): Enable sandbox mode for safe code execution -- `changeMode` (optional): Enable structured change mode -- `chunkIndex` (optional): Chunk index for continuation -- `chunkCacheKey` (optional): Cache key for continuation - -### 2. `brainstorm` -Generate creative ideas using various brainstorming frameworks. - -**Parameters:** -- `prompt` (required): Brainstorming challenge or question -- `model` (optional): Gemini model to use -- `methodology` (optional): Framework (`divergent`, `convergent`, `scamper`, `design-thinking`, `lateral`, `auto`) -- `domain` (optional): Domain context (`software`, `business`, `creative`, etc.) -- `constraints` (optional): Known limitations or requirements -- `existingContext` (optional): Background information -- `ideaCount` (optional): Number of ideas to generate (default: 12) -- `includeAnalysis` (optional): Include feasibility analysis (default: true) - -### 3. `fetch-chunk` -Retrieve cached chunks from changeMode responses. - -**Parameters:** -- `cacheKey` (required): Cache key from initial response -- `chunkIndex` (required): Chunk index to retrieve (1-based) - -### 4. `timeout-test` -Test timeout prevention mechanisms. - -**Parameters:** -- `duration` (required): Duration in milliseconds (minimum: 10ms) - -### 5. `ping` -Test connection to the server. - -**Parameters:** -- `prompt` (optional): Message to echo back - -### 6. `Help` -Display help information about available tools. - -## 🎯 Usage - -Once configured, you can use the following tools through your MCP client: - -### Available Tools - -- **ask-gemini**: Send prompts to Gemini - ``` - "Explain how MCP works" - ``` - -- **analyze-file**: Analyze specific files using `@filename` syntax - ``` - "Analyze @package.json and suggest improvements" - ``` - -- **sandbox-mode**: Execute code in a safe environment - ``` - "Run this Python code in sandbox mode: print('Hello World')" - ``` - -## 📝 Examples - -### Basic Prompts -``` -"What are the best practices for Node.js development?" -"Explain the differences between async/await and Promises" -``` - -### File Analysis -``` -"Analyze @package.json and suggest improvements" -"Review @src/index.js for potential security issues" -"Compare @old-config.json with @new-config.json" -``` - -### Code Execution -``` -"Run this Python code in sandbox mode: print('Hello World')" -"Execute this JavaScript: console.log(new Date())" -``` - -### Complex Analysis -``` -"Analyze the entire codebase and suggest architectural improvements" -"Review all TypeScript files for type safety issues" -``` - -## 🔧 Windows-Specific Fixes - -This version includes the following Windows-specific improvements: - -1. **PowerShell Parameter Handling**: Fixed argument passing to avoid parameter splitting -2. **Character Encoding**: Proper UTF-8 handling for Chinese and Unicode characters -3. **Quote Escaping**: Correct escaping of quotes in command arguments -4. **Environment Variables**: Improved `.env` file loading and environment variable handling -5. **Path Resolution**: Windows-compatible path handling - -## 🧪 Testing Installation - -### 1. Test Gemini CLI -```powershell -gemini -p "Hello, how are you?" -``` - -### 2. Test MCP Tool -```powershell -npx -y gemini-mcp-tool-windows-fixed -# Should show: [GMCPT] Gemini CLI MCP Server (Fixed) started -``` - -### 3. Test MCP Integration -1. Restart your MCP client (Trae AI, Claude Desktop) -2. Try asking: "Use gemini to explain what MCP is" -3. Check for successful responses - -## 🐛 Troubleshooting - -### Common Issues - -#### "Command not found: gemini" -```powershell -npm install -g @google/generative-ai-cli -``` - -#### "API key not found" -```powershell -# Check if API key is set -echo $env:GEMINI_API_KEY - -# Set if empty -$env:GEMINI_API_KEY = "your-api-key" -``` - -#### "Permission denied" -```powershell -# Check execution policy -Get-ExecutionPolicy -Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser -``` - -For detailed troubleshooting, see [INSTALL-GUIDE.md](./INSTALL-GUIDE.md). - -## 🔧 Windows-Specific Fixes - -This version includes several Windows-specific improvements: - -- **PowerShell Integration**: Native PowerShell command execution -- **Path Handling**: Proper Windows path resolution -- **Environment Variables**: Enhanced environment variable support -- **Error Handling**: Better error messages for Windows environments -- **Dependency Management**: Simplified dependency structure - -## 🤝 Contributing - -Contributions are welcome! Please: - -1. Fork the repository -2. Create a feature branch -3. Test on Windows environments -4. Submit a pull request - -## 📄 License - -MIT License - see [LICENSE](LICENSE) file for details. - -## 🙏 Acknowledgments - -- Original project: [jamubc/gemini-mcp-tool](https://github.com/jamubc/gemini-mcp-tool) -- Google Gemini CLI team -- Model Context Protocol (MCP) community - -## 📞 Support - -If you encounter any issues or have questions: - -1. Check the [Issues](https://github.com/your-username/gemini-mcp-tool-windows-fixed/issues) page -2. Create a new issue with detailed information about your problem -3. Include your Windows version, Node.js version, and error messages - ---- - -**Made with ❤️ for Windows developers** - -**Note**: This is a Windows-optimized fork of the original gemini-mcp-tool. For other platforms, consider using the [original version](https://github.com/jamubc/gemini-mcp-tool). +# 🚀 Gemini MCP Tool - Windows Fixed Version + +[![npm version](https://badge.fury.io/js/gemini-mcp-tool-windows-fixed.svg)](https://badge.fury.io/js/gemini-mcp-tool-windows-fixed) +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) + +> **最新版本 v1.0.2** - 修复了 PowerShell 执行错误,解决了 `spawn powershell.exe ENOENT` 问题 + +A **Windows-compatible** Model Context Protocol (MCP) server that enables AI assistants to interact with Google's Gemini CLI. This is a fixed version specifically designed to work seamlessly on Windows environments with PowerShell support. + +> **Note**: This is an enhanced version of the [original gemini-mcp-tool](https://github.com/jamubc/gemini-mcp-tool) with Windows-specific fixes and improvements. + +## 🆕 最新更新 (v1.0.2) + +- ✅ **修复 PowerShell 执行错误** - 解决 `spawn powershell.exe ENOENT` 问题 +- ✅ **改进 Windows 兼容性** - 自动检测可用的 PowerShell 版本 +- ✅ **修复未定义变量错误** - 修复 `executeCommandWithPipedInput` 函数中的 `args` 变量问题 +- ✅ **增强错误处理** - 更好的错误信息和调试输出 + +## ✨ Features + +- **🪟 Windows Compatible**: Full PowerShell support with Windows-specific path handling +- **📊 Large Context Window**: Leverage Gemini's massive token window for analyzing entire codebases +- **📁 File Analysis**: Analyze files using `@filename` syntax +- **🔒 Sandbox Mode**: Safe code execution environment +- **🔗 MCP Integration**: Seamless integration with MCP-compatible AI assistants (Trae AI, Claude Desktop) +- **⚡ NPX Ready**: Easy installation and usage with NPX +- **🔧 Environment Variable Support**: Flexible API key configuration + +This Windows-fixed version resolves: +- PowerShell parameter passing issues +- Character encoding problems with Chinese/Unicode text +- Command line argument escaping on Windows +- Environment variable handling + +## 📋 Prerequisites + +1. **Node.js** (v16.0.0 or higher) + ```powershell + node --version # Should be v16+ + ``` + +2. **Google Gemini CLI**: Install the Gemini CLI tool + ```powershell + npm install -g @google/generative-ai-cli + + # Verify installation + gemini --version + ``` + +3. **API Key**: Get your API key from [Google AI Studio](https://makersuite.google.com/app/apikey) + +## 📦 Installation + +### Quick Start with NPX (Recommended) + +```powershell +# 使用最新版本 (推荐) +npx gemini-mcp-tool-windows-fixed@1.0.2 + +# 或者使用最新版本标签 +npx -y gemini-mcp-tool-windows-fixed@latest +``` + +### Global Installation + +```powershell +# 安装最新版本 +npm install -g gemini-mcp-tool-windows-fixed@1.0.2 + +# 运行工具 +gemini-mcp-tool-windows-fixed +``` + +### 更新现有安装 + +如果您之前安装了旧版本: + +```powershell +# 卸载旧版本并安装最新版本 +npm uninstall -g gemini-mcp-tool-windows-fixed +npm cache clean --force +npm install -g gemini-mcp-tool-windows-fixed@1.0.2 +``` + +## ⚙️ MCP Client Configuration + +### Trae AI (Recommended) + +1. Open: `%APPDATA%\Trae\User\mcp.json` +2. Add this configuration: + +```json +{ + "mcpServers": { + "gemini-cli": { + "name": "gemini-cli", + "description": "Windows-compatible Gemini MCP Tool", + "baseUrl": "", + "command": "npx", + "args": [ + "-y", + "gemini-mcp-tool-windows-fixed" + ], + "env": { + "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" + }, + "isActive": true, + "providerUrl": "https://github.com/your-username/gemini-mcp-tool-windows-fixed" + } + } +} +``` + +### Claude Desktop + +1. Open: `%APPDATA%\Claude\claude_desktop_config.json` +2. Add this configuration: + +```json +{ + "mcpServers": { + "gemini-cli": { + "command": "npx", + "args": ["-y", "gemini-mcp-tool-windows-fixed"], + "env": { + "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" + } + } + } +} +``` + +## 🔑 API Key Configuration + +### Option 1: MCP Configuration (Recommended) + +Replace `YOUR_ACTUAL_API_KEY_HERE` in the configuration above with your actual API key. + +### Option 2: Environment Variable + +```powershell +# Temporary (current session) +$env:GEMINI_API_KEY = "your-actual-api-key" + +# Permanent (user level) +[Environment]::SetEnvironmentVariable("GEMINI_API_KEY", "your-actual-api-key", "User") + +# Verify +echo $env:GEMINI_API_KEY +``` + +### Configuration File Locations + +**Claude Desktop:** +- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json` +- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json` +- **Linux**: `~/.config/claude/claude_desktop_config.json` + +**Trae AI:** +- **Windows**: `%APPDATA%\Trae\User\mcp.json` + +## 🛠️ Available Tools + +This MCP server provides the following tools for AI assistants: + +### 1. `ask-gemini` +Interact with Google Gemini for analysis and questions. + +**Parameters:** +- `prompt` (required): The analysis request. Use `@` syntax for file references +- `model` (optional): Gemini model to use (default: `gemini-2.5-pro`) +- `sandbox` (optional): Enable sandbox mode for safe code execution +- `changeMode` (optional): Enable structured change mode +- `chunkIndex` (optional): Chunk index for continuation +- `chunkCacheKey` (optional): Cache key for continuation + +### 2. `brainstorm` +Generate creative ideas using various brainstorming frameworks. + +**Parameters:** +- `prompt` (required): Brainstorming challenge or question +- `model` (optional): Gemini model to use +- `methodology` (optional): Framework (`divergent`, `convergent`, `scamper`, `design-thinking`, `lateral`, `auto`) +- `domain` (optional): Domain context (`software`, `business`, `creative`, etc.) +- `constraints` (optional): Known limitations or requirements +- `existingContext` (optional): Background information +- `ideaCount` (optional): Number of ideas to generate (default: 12) +- `includeAnalysis` (optional): Include feasibility analysis (default: true) + +### 3. `fetch-chunk` +Retrieve cached chunks from changeMode responses. + +**Parameters:** +- `cacheKey` (required): Cache key from initial response +- `chunkIndex` (required): Chunk index to retrieve (1-based) + +### 4. `timeout-test` +Test timeout prevention mechanisms. + +**Parameters:** +- `duration` (required): Duration in milliseconds (minimum: 10ms) + +### 5. `ping` +Test connection to the server. + +**Parameters:** +- `prompt` (optional): Message to echo back + +### 6. `Help` +Display help information about available tools. + +## 🎯 Usage + +Once configured, you can use the following tools through your MCP client: + +### Available Tools + +- **ask-gemini**: Send prompts to Gemini + ``` + "Explain how MCP works" + ``` + +- **analyze-file**: Analyze specific files using `@filename` syntax + ``` + "Analyze @package.json and suggest improvements" + ``` + +- **sandbox-mode**: Execute code in a safe environment + ``` + "Run this Python code in sandbox mode: print('Hello World')" + ``` + +## 📝 Examples + +### Basic Prompts +``` +"What are the best practices for Node.js development?" +"Explain the differences between async/await and Promises" +``` + +### File Analysis +``` +"Analyze @package.json and suggest improvements" +"Review @src/index.js for potential security issues" +"Compare @old-config.json with @new-config.json" +``` + +### Code Execution +``` +"Run this Python code in sandbox mode: print('Hello World')" +"Execute this JavaScript: console.log(new Date())" +``` + +### Complex Analysis +``` +"Analyze the entire codebase and suggest architectural improvements" +"Review all TypeScript files for type safety issues" +``` + +## 🔧 Windows-Specific Fixes + +This version includes the following Windows-specific improvements: + +1. **PowerShell Parameter Handling**: Fixed argument passing to avoid parameter splitting +2. **Character Encoding**: Proper UTF-8 handling for Chinese and Unicode characters +3. **Quote Escaping**: Correct escaping of quotes in command arguments +4. **Environment Variables**: Improved `.env` file loading and environment variable handling +5. **Path Resolution**: Windows-compatible path handling + +## 🧪 Testing Installation + +### 1. Test Gemini CLI +```powershell +gemini -p "Hello, how are you?" +``` + +### 2. Test MCP Tool +```powershell +npx -y gemini-mcp-tool-windows-fixed +# Should show: [GMCPT] Gemini CLI MCP Server (Fixed) started +``` + +### 3. Test MCP Integration +1. Restart your MCP client (Trae AI, Claude Desktop) +2. Try asking: "Use gemini to explain what MCP is" +3. Check for successful responses + +## 🐛 Troubleshooting + +### Common Issues + +#### "Command not found: gemini" +```powershell +npm install -g @google/generative-ai-cli +``` + +#### "API key not found" +```powershell +# Check if API key is set +echo $env:GEMINI_API_KEY + +# Set if empty +$env:GEMINI_API_KEY = "your-api-key" +``` + +#### "Permission denied" +```powershell +# Check execution policy +Get-ExecutionPolicy +Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser +``` + +For detailed troubleshooting, see [INSTALL-GUIDE.md](./INSTALL-GUIDE.md). + +## 🔧 Windows-Specific Fixes + +This version includes several Windows-specific improvements: + +- **PowerShell Integration**: Native PowerShell command execution +- **Path Handling**: Proper Windows path resolution +- **Environment Variables**: Enhanced environment variable support +- **Error Handling**: Better error messages for Windows environments +- **Dependency Management**: Simplified dependency structure + +## 🤝 Contributing + +Contributions are welcome! Please: + +1. Fork the repository +2. Create a feature branch +3. Test on Windows environments +4. Submit a pull request + +## 📄 License + +MIT License - see [LICENSE](LICENSE) file for details. + +## 🙏 Acknowledgments + +- Original project: [jamubc/gemini-mcp-tool](https://github.com/jamubc/gemini-mcp-tool) +- Google Gemini CLI team +- Model Context Protocol (MCP) community + +## 📞 Support + +If you encounter any issues or have questions: + +1. Check the [Issues](https://github.com/your-username/gemini-mcp-tool-windows-fixed/issues) page +2. Create a new issue with detailed information about your problem +3. Include your Windows version, Node.js version, and error messages + +--- + +**Made with ❤️ for Windows developers** + +**Note**: This is a Windows-optimized fork of the original gemini-mcp-tool. For other platforms, consider using the [original version](https://github.com/jamubc/gemini-mcp-tool). From b0451de48842aa11cb31e49d206681817842578e Mon Sep 17 00:00:00 2001 From: User Date: Mon, 4 Aug 2025 06:08:08 +0800 Subject: [PATCH 05/28] Update MCP configuration to specify v1.0.2 - Update Trae AI and Claude Desktop config examples to use @1.0.2 - Ensure users get the latest version with PowerShell fixes - Prevent users from accidentally using older v1.0.0 with known issues --- INSTALL-GUIDE.md | 4 ++-- README.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/INSTALL-GUIDE.md b/INSTALL-GUIDE.md index 0453fe1..cf3b870 100644 --- a/INSTALL-GUIDE.md +++ b/INSTALL-GUIDE.md @@ -91,7 +91,7 @@ npm install -g gemini-mcp-tool-windows-fixed@1.0.2 "command": "npx", "args": [ "-y", - "gemini-mcp-tool-windows-fixed" + "gemini-mcp-tool-windows-fixed@1.0.2" ], "env": { "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" @@ -113,7 +113,7 @@ npm install -g gemini-mcp-tool-windows-fixed@1.0.2 "mcpServers": { "gemini-cli": { "command": "npx", - "args": ["-y", "gemini-mcp-tool-windows-fixed"], + "args": ["-y", "gemini-mcp-tool-windows-fixed@1.0.2"], "env": { "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" } diff --git a/README.md b/README.md index bbdd584..31426b4 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ npm install -g gemini-mcp-tool-windows-fixed@1.0.2 "command": "npx", "args": [ "-y", - "gemini-mcp-tool-windows-fixed" + "gemini-mcp-tool-windows-fixed@1.0.2" ], "env": { "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" @@ -121,7 +121,7 @@ npm install -g gemini-mcp-tool-windows-fixed@1.0.2 "mcpServers": { "gemini-cli": { "command": "npx", - "args": ["-y", "gemini-mcp-tool-windows-fixed"], + "args": ["-y", "gemini-mcp-tool-windows-fixed@1.0.2"], "env": { "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" } From 94527cd31da5d436e89973f6f458371f5350b81d Mon Sep 17 00:00:00 2001 From: User Date: Mon, 4 Aug 2025 06:12:12 +0800 Subject: [PATCH 06/28] Add comprehensive usage examples and slash commands from original project - Added Claude Code one-line setup command and installation verification - Added natural language usage examples with file references (@syntax) - Added sandbox mode examples for safe code execution - Added slash commands documentation (/analyze, /sandbox, /help, /ping) - Included compatibility notes for different MCP clients - Enhanced both README.md and INSTALL-GUIDE.md with consistent content --- INSTALL-GUIDE.md | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 55 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+) diff --git a/INSTALL-GUIDE.md b/INSTALL-GUIDE.md index cf3b870..7613fcd 100644 --- a/INSTALL-GUIDE.md +++ b/INSTALL-GUIDE.md @@ -76,6 +76,25 @@ npm install -g gemini-mcp-tool-windows-fixed@1.0.2 ## ⚙️ MCP Client Configuration +### For Claude Code (One-Line Setup) + +```bash +# One-command setup for Claude Code +claude mcp add gemini-cli -- npx -y gemini-mcp-tool-windows-fixed@1.0.2 +``` + +**Verify Installation:** +Type `/mcp` inside Claude Code to verify the `gemini-cli` MCP is active. 1 + +### Alternative: Import from Claude Desktop +If you already have it configured in Claude Desktop: + +1. Add to your Claude Desktop config (see below) +2. Import to Claude Code: + ```bash + claude mcp add-from-claude-desktop + ``` + ### For Trae AI 1. Open: `%APPDATA%\Trae\User\mcp.json` @@ -259,6 +278,44 @@ If you encounter issues: - Node.js version - Complete error logs +## 🎯 Usage Examples + +### Natural Language Examples 2 + +**With File References (using @ syntax):** +- "ask gemini to analyze @src/main.js and explain what it does" +- "use gemini to summarize @. the current directory" +- "analyze @package.json and tell me about dependencies" + +**General Questions (without files):** +- "ask gemini to search for the latest tech news" +- "use gemini to explain div centering" +- "ask gemini about best practices for React development related to @file_im_confused_about" +- "use gemini to explain index.html" +- "understand the massive project using gemini" +- "ask gemini to search for latest news" + +**Using Gemini CLI's Sandbox Mode (-s):** 2 +The sandbox mode allows you to safely test code changes, run scripts, or execute potentially risky operations in an isolated environment. +- "use gemini sandbox to create and run a Python script that processes data" +- "ask gemini to safely test @script.py and explain what it does" +- "use gemini sandbox to install numpy and create a data visualization" +- "test this code safely: Create a script that makes HTTP requests to an API" + +### Slash Commands (for Claude Code Users) 2 + +You can use these commands directly in Claude Code's interface (compatibility with other clients has not been tested): + +- **/analyze**: Analyzes files or directories using Gemini, or asks general questions + - `prompt` (required): The analysis prompt. Use @ syntax to include files (e.g., `/analyze prompt:@src/ summarize this directory`) or ask general questions (e.g., `/analyze prompt:Please use a web search to find the latest news stories`) + +- **/sandbox**: Safely tests code or scripts in Gemini's sandbox environment + - `prompt` (required): Code testing request (e.g., `/sandbox prompt:Create and run a Python script that processes CSV data` or `/sandbox prompt:@script.py Test this script safely`) + +- **/help**: Displays the Gemini CLI help information +- **/ping**: Tests the connection to the server + - `message` (optional): A message to echo back + ## 🎉 Success! Once everything is working, you should be able to: diff --git a/README.md b/README.md index 31426b4..af6eef5 100644 --- a/README.md +++ b/README.md @@ -84,6 +84,25 @@ npm install -g gemini-mcp-tool-windows-fixed@1.0.2 ## ⚙️ MCP Client Configuration +### Claude Code (One-Line Setup) + +```bash +# One-command setup for Claude Code +claude mcp add gemini-cli -- npx -y gemini-mcp-tool-windows-fixed@1.0.2 +``` + +**Verify Installation:** +Type `/mcp` inside Claude Code to verify the `gemini-cli` MCP is active. 1 + +### Alternative: Import from Claude Desktop +If you already have it configured in Claude Desktop: + +1. Add to your Claude Desktop config (see below) +2. Import to Claude Code: + ```bash + claude mcp add-from-claude-desktop + ``` + ### Trae AI (Recommended) 1. Open: `%APPDATA%\Trae\User\mcp.json` @@ -213,6 +232,42 @@ Display help information about available tools. Once configured, you can use the following tools through your MCP client: +### Natural Language Examples 2 + +**With File References (using @ syntax):** +- "ask gemini to analyze @src/main.js and explain what it does" +- "use gemini to summarize @. the current directory" +- "analyze @package.json and tell me about dependencies" + +**General Questions (without files):** +- "ask gemini to search for the latest tech news" +- "use gemini to explain div centering" +- "ask gemini about best practices for React development related to @file_im_confused_about" +- "use gemini to explain index.html" +- "understand the massive project using gemini" +- "ask gemini to search for latest news" + +**Using Gemini CLI's Sandbox Mode (-s):** 2 +The sandbox mode allows you to safely test code changes, run scripts, or execute potentially risky operations in an isolated environment. +- "use gemini sandbox to create and run a Python script that processes data" +- "ask gemini to safely test @script.py and explain what it does" +- "use gemini sandbox to install numpy and create a data visualization" +- "test this code safely: Create a script that makes HTTP requests to an API" + +### Slash Commands (for Claude Code Users) 2 + +You can use these commands directly in Claude Code's interface (compatibility with other clients has not been tested): + +- **/analyze**: Analyzes files or directories using Gemini, or asks general questions + - `prompt` (required): The analysis prompt. Use @ syntax to include files (e.g., `/analyze prompt:@src/ summarize this directory`) or ask general questions (e.g., `/analyze prompt:Please use a web search to find the latest news stories`) + +- **/sandbox**: Safely tests code or scripts in Gemini's sandbox environment + - `prompt` (required): Code testing request (e.g., `/sandbox prompt:Create and run a Python script that processes CSV data` or `/sandbox prompt:@script.py Test this script safely`) + +- **/help**: Displays the Gemini CLI help information +- **/ping**: Tests the connection to the server + - `message` (optional): A message to echo back + ### Available Tools - **ask-gemini**: Send prompts to Gemini From 2671a5af55b386e827ed191c26df226b9e850f71 Mon Sep 17 00:00:00 2001 From: orzcls <1515122903@qq.com> Date: Mon, 4 Aug 2025 06:15:08 +0800 Subject: [PATCH 07/28] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index af6eef5..6a2ddaa 100644 --- a/README.md +++ b/README.md @@ -124,7 +124,7 @@ If you already have it configured in Claude Desktop: "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" }, "isActive": true, - "providerUrl": "https://github.com/your-username/gemini-mcp-tool-windows-fixed" + "providerUrl": "https://github.com/orzcls/gemini-mcp-tool-windows-fixed" } } } @@ -409,3 +409,4 @@ If you encounter any issues or have questions: **Made with ❤️ for Windows developers** **Note**: This is a Windows-optimized fork of the original gemini-mcp-tool. For other platforms, consider using the [original version](https://github.com/jamubc/gemini-mcp-tool). + From aa70941220b532a5495a06afa3b71f85c957230c Mon Sep 17 00:00:00 2001 From: orzcls <1515122903@qq.com> Date: Mon, 4 Aug 2025 06:22:16 +0800 Subject: [PATCH 08/28] Update README.md --- README.md | 30 ++---------------------------- 1 file changed, 2 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 6a2ddaa..1d7d615 100644 --- a/README.md +++ b/README.md @@ -228,7 +228,7 @@ Test connection to the server. ### 6. `Help` Display help information about available tools. -## 🎯 Usage +## 🎯 Usage Examples Once configured, you can use the following tools through your MCP client: @@ -285,33 +285,6 @@ You can use these commands directly in Claude Code's interface (compatibility wi "Run this Python code in sandbox mode: print('Hello World')" ``` -## 📝 Examples - -### Basic Prompts -``` -"What are the best practices for Node.js development?" -"Explain the differences between async/await and Promises" -``` - -### File Analysis -``` -"Analyze @package.json and suggest improvements" -"Review @src/index.js for potential security issues" -"Compare @old-config.json with @new-config.json" -``` - -### Code Execution -``` -"Run this Python code in sandbox mode: print('Hello World')" -"Execute this JavaScript: console.log(new Date())" -``` - -### Complex Analysis -``` -"Analyze the entire codebase and suggest architectural improvements" -"Review all TypeScript files for type safety issues" -``` - ## 🔧 Windows-Specific Fixes This version includes the following Windows-specific improvements: @@ -410,3 +383,4 @@ If you encounter any issues or have questions: **Note**: This is a Windows-optimized fork of the original gemini-mcp-tool. For other platforms, consider using the [original version](https://github.com/jamubc/gemini-mcp-tool). + From 2cca8436c6ef4eb09cf261ca5749975a679639fb Mon Sep 17 00:00:00 2001 From: User Date: Mon, 4 Aug 2025 08:34:51 +0800 Subject: [PATCH 09/28] feat: Add PowerShell path parameter support (v1.0.3) - Add optional powershellPath parameter to ask-gemini and brainstorm tools - Support custom PowerShell executable paths for different system configurations - Enhance PowerShell path detection and error handling - Update documentation with PowerShell path configuration guide - Add comprehensive test scripts for validation - Maintain backward compatibility with existing configurations Files updated: - lib/fixed-mcp-tool.js: Add powershellPath parameter definitions - lib/fixed-geminiExecutor.js: Extend functions to support custom PowerShell paths - package.json: Bump version to 1.0.3 - INSTALL-GUIDE.md: Add PowerShell path configuration section - Add POWERSHELL-PATH-UPDATE.md: Detailed update documentation - Add multiple test scripts for validation --- INSTALL-GUIDE.md | 50 +++ POWERSHELL-FIX-SUMMARY.md | 102 +++++ POWERSHELL-PATH-UPDATE.md | 137 +++++++ gemini-cli-test.json | 11 + lib/fixed-geminiExecutor.js | 93 ++++- lib/fixed-mcp-tool.js | 736 ++++++++++++++++++------------------ package.json | 2 +- test-brainstorm-dev.cjs | 74 ++++ test-brainstorm.js | 91 +++++ test-mcp-powershell.js | 134 +++++++ test-powershell-fix.cjs | 72 ++++ test-powershell-path.cjs | 105 +++++ test-powershell.js | 84 ++++ test-simple-powershell.cjs | 65 ++++ 14 files changed, 1379 insertions(+), 377 deletions(-) create mode 100644 POWERSHELL-FIX-SUMMARY.md create mode 100644 POWERSHELL-PATH-UPDATE.md create mode 100644 gemini-cli-test.json create mode 100644 test-brainstorm-dev.cjs create mode 100644 test-brainstorm.js create mode 100644 test-mcp-powershell.js create mode 100644 test-powershell-fix.cjs create mode 100644 test-powershell-path.cjs create mode 100644 test-powershell.js create mode 100644 test-simple-powershell.cjs diff --git a/INSTALL-GUIDE.md b/INSTALL-GUIDE.md index 7613fcd..ae2ac5c 100644 --- a/INSTALL-GUIDE.md +++ b/INSTALL-GUIDE.md @@ -83,9 +83,59 @@ npm install -g gemini-mcp-tool-windows-fixed@1.0.2 claude mcp add gemini-cli -- npx -y gemini-mcp-tool-windows-fixed@1.0.2 ``` +### For Development/Testing (Local Version) + +如果你想使用本地开发版本进行测试,可以使用以下配置: + +1. 首先确保你已经克隆了项目到本地 +2. 使用提供的 `gemini-cli-test.json` 配置文件: + +```json +{ + "mcpServers": { + "gemini-cli-test": { + "command": "node", + "args": ["D:\\gemini\\lib\\fixed-mcp-tool.js"], + "env": { + "GEMINI_API_KEY": "your_api_key_here" + } + } + } +} +``` + +**注意:** 请将路径 `D:\\gemini\\lib\\fixed-mcp-tool.js` 替换为你的实际项目路径。 + **Verify Installation:** Type `/mcp` inside Claude Code to verify the `gemini-cli` MCP is active. 1 +### PowerShell Path Configuration (Optional) + +如果你的系统中 PowerShell 路径不在标准位置,或者你想使用特定版本的 PowerShell,可以在调用工具时指定 `powershellPath` 参数: + +**ask-gemini 工具示例:** +```json +{ + "prompt": "你的问题", + "model": "gemini-pro", + "powershellPath": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" +} +``` + +**brainstorm 工具示例:** +```json +{ + "topic": "你的主题", + "count": 5, + "powershellPath": "C:\\Program Files\\PowerShell\\7\\pwsh.exe" +} +``` + +**常见 PowerShell 路径:** +- Windows PowerShell 5.1: `C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe` +- PowerShell 7+: `C:\\Program Files\\PowerShell\\7\\pwsh.exe` +- 如果不指定此参数,系统会自动检测可用的 PowerShell 版本 + ### Alternative: Import from Claude Desktop If you already have it configured in Claude Desktop: diff --git a/POWERSHELL-FIX-SUMMARY.md b/POWERSHELL-FIX-SUMMARY.md new file mode 100644 index 0000000..e31fa89 --- /dev/null +++ b/POWERSHELL-FIX-SUMMARY.md @@ -0,0 +1,102 @@ +# PowerShell ENOENT 错误修复总结 + +## 问题描述 +用户报告在其他客户端配置后仍出现 `Error executing brainstorm: spawn powershell.exe ENOENT` 错误。 + +## 根本原因分析 +1. **环境变量传递不完整**:子进程没有继承完整的系统环境变量 +2. **PowerShell路径问题**:在某些环境中,相对路径 `powershell.exe` 无法被正确解析 +3. **ES模块兼容性**:项目使用ES模块,但部分代码仍使用CommonJS语法 + +## 修复措施 + +### 1. 改进PowerShell可执行文件检测 (`fixed-geminiExecutor.js`) +- 优先使用完整路径:`C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe` +- 添加多个备选路径以提高兼容性 +- 增加详细的调试日志输出 + +### 2. 完善环境变量处理 +- 确保子进程继承完整的系统环境变量 (`process.env`) +- 添加必要的Windows系统变量:`SYSTEMROOT`、`WINDIR` +- 确保 `PATH` 环境变量始终可用 +- 正确传递 `GEMINI_API_KEY` + +### 3. 修复ES模块兼容性 +- 将 `require` 语法改为 `import` 语法 +- 确保所有模块导入在文件顶部 + +## 测试验证 + +### 测试1:基础PowerShell调用 +```bash +node test-simple-powershell.cjs +``` +**结果:** ✅ 成功 +- `powershell.exe` 调用成功 +- 完整路径调用成功 +- 无ENOENT错误 + +### 测试2:MCP工具brainstorm功能 +```bash +node test-brainstorm-dev.cjs +``` +**结果:** ✅ PowerShell调用成功 +- PowerShell进程启动正常 +- 环境变量正确传递 +- 仅因API密钥问题失败(预期行为) +- **关键:无ENOENT错误** + +## 配置文件 + +### 开发版本配置 (`gemini-cli-test.json`) +```json +{ + "mcpServers": { + "gemini-cli-test": { + "command": "node", + "args": ["D:\\gemini\\lib\\fixed-mcp-tool.js"], + "env": { + "GEMINI_API_KEY": "your_api_key_here" + } + } + } +} +``` + +## 修复效果 + +✅ **ENOENT错误已解决** +- PowerShell可执行文件能够被正确找到和执行 +- 环境变量正确传递到子进程 +- 支持多种PowerShell路径配置 + +✅ **兼容性提升** +- 支持不同Windows版本的PowerShell路径 +- 改进的错误处理和调试信息 +- ES模块兼容性修复 + +✅ **开发测试支持** +- 提供本地开发版本配置 +- 详细的测试脚本和验证方法 +- 完整的安装和配置文档 + +## 建议 + +1. **用户配置**:建议用户使用提供的 `gemini-cli-test.json` 配置文件进行本地测试 +2. **路径配置**:确保将配置文件中的路径替换为实际的项目路径 +3. **API密钥**:确保在环境变量或配置文件中正确设置 `GEMINI_API_KEY` + +## 技术细节 + +### 关键修改文件 +- `lib/fixed-geminiExecutor.js`:PowerShell执行器修复 +- `gemini-cli-test.json`:开发版本配置 +- `INSTALL-GUIDE.md`:更新安装指南 + +### 调试信息 +修复后的版本包含详细的调试日志: +- PowerShell路径检测过程 +- 环境变量可用性检查 +- 命令执行状态跟踪 + +这些修复确保了 `spawn powershell.exe ENOENT` 错误不再出现,提供了稳定可靠的PowerShell调用机制。 \ No newline at end of file diff --git a/POWERSHELL-PATH-UPDATE.md b/POWERSHELL-PATH-UPDATE.md new file mode 100644 index 0000000..3e78f7f --- /dev/null +++ b/POWERSHELL-PATH-UPDATE.md @@ -0,0 +1,137 @@ +# PowerShell 路径参数更新说明 + +## 版本信息 +- **版本**: 1.0.3 +- **发布日期**: 2024年12月 +- **更新类型**: 功能增强 + +## 更新内容 + +### 新增功能:PowerShell 路径自定义参数 + +为了解决不同用户系统中 PowerShell 路径不同的问题,我们在 `ask-gemini` 和 `brainstorm` 工具中添加了可选的 `powershellPath` 参数。 + +### 功能特性 + +1. **可选参数**: `powershellPath` 是可选参数,不指定时使用系统自动检测 +2. **灵活配置**: 支持指定任意有效的 PowerShell 可执行文件路径 +3. **向后兼容**: 现有配置无需修改,自动使用默认检测逻辑 +4. **多版本支持**: 支持 Windows PowerShell 5.1 和 PowerShell 7+ + +### 使用方法 + +#### ask-gemini 工具 +```json +{ + "prompt": "你的问题", + "model": "gemini-pro", + "powershellPath": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" +} +``` + +#### brainstorm 工具 +```json +{ + "topic": "创新想法", + "count": 5, + "powershellPath": "C:\\Program Files\\PowerShell\\7\\pwsh.exe" +} +``` + +### 常见 PowerShell 路径 + +| PowerShell 版本 | 默认路径 | +|----------------|----------| +| Windows PowerShell 5.1 | `C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe` | +| PowerShell 7+ | `C:\\Program Files\\PowerShell\\7\\pwsh.exe` | +| PowerShell Core 6 | `C:\\Program Files\\PowerShell\\6\\pwsh.exe` | + +### 技术实现 + +#### 修改的文件 +1. **fixed-mcp-tool.js**: 添加 `powershellPath` 参数定义和传递 +2. **fixed-geminiExecutor.js**: 扩展函数支持自定义 PowerShell 路径 + - `getPowerShellExecutable()`: 支持 `customPath` 参数 + - `executeCommandWithEnv()`: 支持 `customPowershellPath` 参数 + - `executeGeminiCLI()`: 添加 `powershellPath` 参数 + +#### 参数传递流程 +``` +MCP 工具调用 → fixed-mcp-tool.js → executeGeminiCLI() → executeCommandWithEnv() → spawn(powershellPath) +``` + +### 日志增强 + +添加了详细的日志输出,帮助调试 PowerShell 路径问题: +``` +[GMCPT] Using PowerShell executable: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe +``` + +### 测试验证 + +创建了测试脚本 `test-powershell-path.cjs` 来验证功能: +- 测试默认 PowerShell 路径 +- 测试自定义 PowerShell 路径 +- 验证参数传递正确性 + +### 安装和更新 + +#### 从 npm 安装最新版本 +```bash +npm install -g gemini-mcp-tool-windows-fixed@1.0.3 +``` + +#### 更新现有安装 +```bash +npm update -g gemini-mcp-tool-windows-fixed +``` + +### 配置示例 + +#### Claude Desktop 配置 +```json +{ + "mcpServers": { + "gemini-cli": { + "command": "npx", + "args": ["-y", "gemini-mcp-tool-windows-fixed@1.0.3"], + "env": { + "GEMINI_API_KEY": "your_api_key_here" + } + } + } +} +``` + +#### Claude Code 配置 +```bash +claude mcp add gemini-cli npx -y gemini-mcp-tool-windows-fixed@1.0.3 +``` + +### 故障排除 + +#### 如果遇到 PowerShell 路径问题 +1. 检查系统中安装的 PowerShell 版本 +2. 使用 `powershellPath` 参数指定正确路径 +3. 查看日志输出确认使用的 PowerShell 路径 + +#### 常见错误和解决方案 +- **ENOENT 错误**: 指定正确的 PowerShell 可执行文件路径 +- **权限错误**: 确保 PowerShell 可执行文件有执行权限 +- **路径错误**: 使用双反斜杠转义路径中的反斜杠 + +### 向后兼容性 + +- ✅ 现有配置无需修改 +- ✅ 不指定 `powershellPath` 时使用原有逻辑 +- ✅ 所有现有功能保持不变 + +### 未来计划 + +- 考虑添加 PowerShell 版本自动检测 +- 支持更多 PowerShell 配置选项 +- 优化错误提示和调试信息 + +--- + +**注意**: 此更新完全向后兼容,现有用户无需修改配置即可继续使用。新的 `powershellPath` 参数仅在需要自定义 PowerShell 路径时使用。 \ No newline at end of file diff --git a/gemini-cli-test.json b/gemini-cli-test.json new file mode 100644 index 0000000..c16f09d --- /dev/null +++ b/gemini-cli-test.json @@ -0,0 +1,11 @@ +{ + "mcpServers": { + "gemini-cli-test": { + "command": "node", + "args": ["D:\\gemini\\lib\\fixed-mcp-tool.js"], + "env": { + "GEMINI_API_KEY": "your_api_key_here" + } + } + } +} \ No newline at end of file diff --git a/lib/fixed-geminiExecutor.js b/lib/fixed-geminiExecutor.js index 307ef9a..4fa76a3 100644 --- a/lib/fixed-geminiExecutor.js +++ b/lib/fixed-geminiExecutor.js @@ -14,10 +14,42 @@ import { ERROR_MESSAGES, STATUS_MESSAGES, MODELS, CLI } from './fixed-constants. const chunkCache = new Map(); // Function to get PowerShell executable based on platform -function getPowerShellExecutable() { - // On Windows, try powershell.exe first (Windows PowerShell), then pwsh (PowerShell Core) +function getPowerShellExecutable(customPath = null) { + // If custom path is provided, use it directly + if (customPath) { + console.log(`[GMCPT] Using custom PowerShell path: ${customPath}`); + return customPath; + } if (process.platform === 'win32') { - return 'powershell.exe'; + // Try multiple PowerShell paths to ensure compatibility + const possiblePaths = [ + 'C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\powershell.exe', + 'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe', + 'powershell.exe', + 'pwsh.exe' + ]; + + // Try to find a working PowerShell executable + for (const path of possiblePaths) { + try { + if (path.includes(':\\')) { + // Use full path directly + console.log(`[GMCPT] Using full path: ${path}`); + return path; + } else { + // Use relative path + console.log(`[GMCPT] Will try relative path: ${path}`); + return path; + } + } catch (error) { + console.log(`[GMCPT] Failed to check path ${path}: ${error.message}`); + continue; + } + } + + // Fallback to the first full path + console.log(`[GMCPT] Using fallback PowerShell path: ${possiblePaths[0]}`); + return possiblePaths[0]; } // On other platforms, use pwsh (PowerShell Core) return 'pwsh'; @@ -45,18 +77,34 @@ console.log('Script directory:', __dirname); console.log('Env file path:', path.join(__dirname, '.env')); // Custom executeCommand function that accepts custom environment variables -async function executeCommandWithPipedInput(command, input, env, onProgress) { +async function executeCommandWithPipedInput(command, input, env, onProgress, customPowershellPath = null) { return new Promise((resolve, reject) => { console.log(`[GMCPT] Executing command with piped input: ${command}`); console.log(`[GMCPT] Input length: ${input.length}`); console.log(`[GMCPT] GEMINI_API_KEY in env: ${env.GEMINI_API_KEY ? 'YES' : 'NO'}`); - const childProcess = spawn(POWERSHELL_EXECUTABLE, ['-Command', command], { - env: env, - stdio: ['pipe', 'pipe', 'pipe'] + // Ensure we have a complete environment with PATH and system variables + const completeEnv = { + ...process.env, // Include all system environment variables + ...env, // Override with provided environment variables + PATH: process.env.PATH || '', // Ensure PATH is always available + SYSTEMROOT: process.env.SYSTEMROOT || 'C:\\WINDOWS', // Required for Windows + WINDIR: process.env.WINDIR || 'C:\\WINDOWS' // Required for Windows + }; + + console.log(`[GMCPT] Environment PATH: ${completeEnv.PATH ? 'Available' : 'Missing'}`); + console.log(`[GMCPT] Environment GEMINI_API_KEY: ${completeEnv.GEMINI_API_KEY ? 'Available' : 'Missing'}`); + + const powershellExe = customPowershellPath || POWERSHELL_EXECUTABLE; + console.log(`[GMCPT] Using PowerShell executable: ${powershellExe}`); + + const childProcess = spawn(powershellExe, ['-Command', command], { + env: completeEnv, + stdio: ['pipe', 'pipe', 'pipe'], + shell: false // Don't use shell to avoid additional layer }); - console.log(`[GMCPT] Spawned process with command: ${POWERSHELL_EXECUTABLE} -Command "${command}"`); + console.log(`[GMCPT] Spawned process with command: ${powershellExe} -Command "${command}"`); let stdout = ''; let stderr = ''; @@ -96,16 +144,33 @@ async function executeCommandWithPipedInput(command, input, env, onProgress) { }); } -async function executeCommandWithEnv(command, args, env, onProgress) { +async function executeCommandWithEnv(command, args, env, onProgress, customPowershellPath = null) { return new Promise((resolve, reject) => { console.log(`[GMCPT] Executing command: ${command} ${args.join(' ')}`); console.log(`[GMCPT] Environment variables count: ${Object.keys(env).length}`); console.log(`[GMCPT] GEMINI_API_KEY in env: ${env.GEMINI_API_KEY ? 'YES' : 'NO'}`); console.log(`Executing with custom env: ${command} ${args.join(' ')}`); + // Ensure we have a complete environment with PATH and system variables + const completeEnv = { + ...process.env, // Include all system environment variables + ...env, // Override with provided environment variables + PATH: process.env.PATH || '', // Ensure PATH is always available + SYSTEMROOT: process.env.SYSTEMROOT || 'C:\\WINDOWS', // Required for Windows + WINDIR: process.env.WINDIR || 'C:\\WINDOWS' // Required for Windows + }; + + console.log(`[GMCPT] Environment PATH: ${completeEnv.PATH ? 'Available' : 'Missing'}`); + console.log(`[GMCPT] Environment GEMINI_API_KEY: ${completeEnv.GEMINI_API_KEY ? 'Available' : 'Missing'}`); + + // Use custom PowerShell path if provided, otherwise use default + const powershellExe = customPowershellPath || POWERSHELL_EXECUTABLE; + console.log(`[GMCPT] Using PowerShell executable: ${powershellExe}`); + const psCommand = `& "${command}" ${args.map(arg => `'${arg.replace(/'/g, "''")}'`).join(' ')}`; - const childProcess = spawn(POWERSHELL_EXECUTABLE, ['-Command', psCommand], { - env: env, - stdio: ['pipe', 'pipe', 'pipe'] + const childProcess = spawn(powershellExe, ['-Command', psCommand], { + env: completeEnv, + stdio: ['pipe', 'pipe', 'pipe'], + shell: false // Don't use shell to avoid additional layer }); console.log(`[GMCPT] Executing with PowerShell: ${psCommand}`); @@ -145,7 +210,7 @@ async function executeCommandWithEnv(command, args, env, onProgress) { }); } -export async function executeGeminiCLI(prompt, model, sandbox, changeMode, onProgress) { +export async function executeGeminiCLI(prompt, model, sandbox, changeMode, powershellPath, onProgress) { console.log('executeGeminiCLI called with prompt: ' + prompt.substring(0, 50) + '...'); console.log('API Key available: ' + (process.env.GEMINI_API_KEY ? 'YES' : 'NO')); let prompt_processed = prompt; @@ -220,7 +285,7 @@ function getMessage() { console.log('[GMCPT] Executing gemini command: ' + CLI.COMMANDS.GEMINI + ' ' + args.join(' ')); // Execute gemini command directly with custom environment - const result = await executeCommandWithEnv(CLI.COMMANDS.GEMINI, args, customEnv, onProgress); + const result = await executeCommandWithEnv(CLI.COMMANDS.GEMINI, args, customEnv, onProgress, powershellPath); if (changeMode && result.stdout) { try { diff --git a/lib/fixed-mcp-tool.js b/lib/fixed-mcp-tool.js index d4ee188..9ddee91 100644 --- a/lib/fixed-mcp-tool.js +++ b/lib/fixed-mcp-tool.js @@ -1,363 +1,375 @@ -#!/usr/bin/env node -import { Server } from "@modelcontextprotocol/sdk/server/index.js"; -import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; -import { - CallToolRequestSchema, - ListToolsRequestSchema, - ListPromptsRequestSchema, - GetPromptRequestSchema, -} from "@modelcontextprotocol/sdk/types.js"; -// import { Logger } from "../package/dist/utils/logger.js"; // Removed - using console instead -import { PROTOCOL } from "./fixed-constants.js"; -import { executeGeminiCLI, getChunkedEdits } from "./fixed-geminiExecutor.js"; - -const server = new Server({ - name: "gemini-cli-mcp-fixed", - version: "1.1.4-fixed", -}, { - capabilities: { - tools: {}, - prompts: {}, - notifications: {}, - logging: {}, - }, -}); - -let isProcessing = false; -let currentOperationName = ""; -let latestOutput = ""; - -async function sendNotification(method, params) { - try { - await server.notification({ method, params }); - } - catch (error) { - console.error("notification failed: ", error); - } -} - -async function sendProgressNotification(progressToken, progress, total, message) { - if (!progressToken) - return; - try { - const params = { - progressToken, - progress - }; - if (total !== undefined) - params.total = total; - if (message) - params.message = message; - await server.notification({ - method: PROTOCOL.NOTIFICATIONS.PROGRESS, - params - }); - } - catch (error) { - console.error("Progress notification failed: ", error); - } -} - -// Tool definitions -const tools = [ - { - name: "ask-gemini", - description: "model selection [-m], sandbox [-s], and changeMode:boolean for providing edits", - inputSchema: { - type: "object", - properties: { - prompt: { - type: "string", - minLength: 1, - description: "Analysis request. Use @ syntax to include files (e.g., '@largefile.js explain what this does') or ask general questions" - }, - model: { - type: "string", - description: "Optional model to use (e.g., 'gemini-2.5-flash'). If not specified, uses the default model (gemini-2.5-pro)." - }, - sandbox: { - type: "boolean", - default: false, - description: "Use sandbox mode (-s flag) to safely test code changes, execute scripts, or run potentially risky operations in an isolated environment" - }, - changeMode: { - type: "boolean", - default: false, - description: "Enable structured change mode - formats prompts to prevent tool errors and returns structured edit suggestions that Claude can apply directly" - }, - chunkIndex: { - type: ["number", "string"], - description: "Which chunk to return (1-based)" - }, - chunkCacheKey: { - type: "string", - description: "Optional cache key for continuation" - } - }, - required: ["prompt"] - } - }, - { - name: "ping", - description: "Echo", - inputSchema: { - type: "object", - properties: { - prompt: { - type: "string", - default: "", - description: "Message to echo " - } - }, - required: [] - } - }, - { - name: "Help", - description: "receive help information", - inputSchema: { - type: "object", - properties: {}, - required: [] - } - }, - { - name: "brainstorm", - description: "Generate novel ideas with dynamic context gathering. --> Creative frameworks (SCAMPER, Design Thinking, etc.), domain context integration, idea clustering, feasibility analysis, and iterative refinement.", - inputSchema: { - type: "object", - properties: { - prompt: { - type: "string", - minLength: 1, - description: "Primary brainstorming challenge or question to explore" - }, - model: { - type: "string", - description: "Optional model to use (e.g., 'gemini-2.5-flash'). If not specified, uses the default model (gemini-2.5-pro)." - }, - methodology: { - type: "string", - enum: ["divergent", "convergent", "scamper", "design-thinking", "lateral", "auto"], - default: "auto", - description: "Brainstorming framework: 'divergent' (generate many ideas), 'convergent' (refine existing), 'scamper' (systematic triggers), 'design-thinking' (human-centered), 'lateral' (unexpected connections), 'auto' (AI selects best)" - }, - domain: { - type: "string", - description: "Domain context for specialized brainstorming (e.g., 'software', 'business', 'creative', 'research', 'product', 'marketing')" - }, - constraints: { - type: "string", - description: "Known limitations, requirements, or boundaries (budget, time, technical, legal, etc.)" - }, - existingContext: { - type: "string", - description: "Background information, previous attempts, or current state to build upon" - }, - ideaCount: { - type: "integer", - exclusiveMinimum: 0, - default: 12, - description: "Target number of ideas to generate (default: 10-15)" - }, - includeAnalysis: { - type: "boolean", - default: true, - description: "Include feasibility, impact, and implementation analysis for generated ideas" - } - }, - required: ["prompt"] - } - }, - { - name: "fetch-chunk", - description: "Retrieves cached chunks from a changeMode response. Use this to get subsequent chunks after receiving a partial changeMode response.", - inputSchema: { - type: "object", - properties: { - cacheKey: { - type: "string", - description: "The cache key provided in the initial changeMode response" - }, - chunkIndex: { - type: "number", - minimum: 1, - description: "Which chunk to retrieve (1-based index)" - } - }, - required: ["cacheKey", "chunkIndex"] - } - }, - { - name: "timeout-test", - description: "Test timeout prevention by running for a specified duration", - inputSchema: { - type: "object", - properties: { - duration: { - type: "number", - minimum: 10, - description: "Duration in milliseconds (minimum 10ms)" - } - }, - required: ["duration"] - } - } -]; - -// List available tools -server.setRequestHandler(ListToolsRequestSchema, async () => { - return { tools }; -}); - -// Handle tool execution -server.setRequestHandler(CallToolRequestSchema, async (request) => { - const { name, arguments: args } = request.params; - - console.error(`[GMCPT] Tool called: ${name}`); - console.error(`[GMCPT] Arguments:`, JSON.stringify(args, null, 2)); - - try { - switch (name) { - case "ask-gemini": - const { prompt, model, sandbox, changeMode, chunkIndex, chunkCacheKey } = args; - console.error('[GMCPT] ask-gemini tool called with prompt: ' + prompt.substring(0, 50) + '...'); - console.error('[GMCPT] Model: ' + model + ', Sandbox: ' + sandbox + ', ChangeMode: ' + changeMode); - - if (chunkCacheKey && chunkIndex) { - const result = getChunkedEdits(chunkCacheKey, parseInt(chunkIndex)); - return { - content: [{ - type: "text", - text: result - }] - }; - } - - console.error('[GMCPT] About to call executeGeminiCLI...'); - const result = await executeGeminiCLI(prompt, model, sandbox, changeMode); - console.error('[GMCPT] executeGeminiCLI completed with result length: ' + result.length); - return { - content: [{ - type: "text", - text: result - }] - }; - - case "ping": - return { - content: [{ - type: "text", - text: `Pong! ${args.prompt || 'Hello from gemini-cli MCP server!'}` - }] - }; - - case "Help": - return { - content: [{ - type: "text", - text: "Gemini CLI MCP Tool - Fixed Version\n\nAvailable commands:\n- ask-gemini: Interact with Gemini CLI\n- ping: Test connection\n- Help: Show this help\n- brainstorm: Generate novel ideas with creative frameworks\n- fetch-chunk: Retrieve cached chunks from changeMode responses\n- timeout-test: Test timeout prevention" - }] - }; - - case "brainstorm": - const { - prompt: brainstormPrompt, - model: brainstormModel, - methodology, - domain, - constraints, - existingContext, - ideaCount, - includeAnalysis - } = args; - - console.error('[GMCPT] brainstorm tool called with prompt: ' + brainstormPrompt.substring(0, 50) + '...'); - console.error('[GMCPT] Methodology: ' + methodology + ', Domain: ' + domain); - - // Build enhanced brainstorming prompt - let enhancedPrompt = `BRAINSTORMING SESSION\n\nChallenge: ${brainstormPrompt}\n\n`; - - if (methodology && methodology !== 'auto') { - enhancedPrompt += `Framework: Use ${methodology} methodology for idea generation.\n`; - } - - if (domain) { - enhancedPrompt += `Domain Context: ${domain}\n`; - } - - if (constraints) { - enhancedPrompt += `Constraints: ${constraints}\n`; - } - - if (existingContext) { - enhancedPrompt += `Background: ${existingContext}\n`; - } - - enhancedPrompt += `\nGenerate ${ideaCount || 12} creative and diverse ideas. `; - - if (includeAnalysis !== false) { - enhancedPrompt += `For each idea, provide a brief feasibility assessment and potential impact.`; - } - - const brainstormResult = await executeGeminiCLI(enhancedPrompt, brainstormModel, false, false); - return { - content: [{ - type: "text", - text: brainstormResult - }] - }; - - case "fetch-chunk": - const { cacheKey, chunkIndex: fetchChunkIndex } = args; - console.error('[GMCPT] fetch-chunk tool called with cacheKey: ' + cacheKey + ', chunkIndex: ' + fetchChunkIndex); - - const chunkResult = getChunkedEdits(cacheKey, parseInt(fetchChunkIndex)); - return { - content: [{ - type: "text", - text: chunkResult - }] - }; - - case "timeout-test": - const { duration } = args; - console.error('[GMCPT] timeout-test tool called with duration: ' + duration + 'ms'); - - return new Promise((resolve) => { - setTimeout(() => { - resolve({ - content: [{ - type: "text", - text: `Timeout test completed after ${duration}ms` - }] - }); - }, Math.max(10, duration)); - }); - - default: - throw new Error(`Unknown tool: ${name}`); - } - } catch (error) { - console.error(`Error executing ${name}: ${error.message}`); - return { - content: [{ - type: "text", - text: `Error executing ${name}: ${error.message}` - }], - isError: true - }; - } -}); - -// Start the server -async function main() { - const transport = new StdioServerTransport(); - await server.connect(transport); - console.log("[GMCPT] Gemini CLI MCP Server (Fixed) started"); -} - -main().catch((error) => { - console.error("Server failed to start:", error); - process.exit(1); +#!/usr/bin/env node +import { Server } from "@modelcontextprotocol/sdk/server/index.js"; +import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; +import { + CallToolRequestSchema, + ListToolsRequestSchema, + ListPromptsRequestSchema, + GetPromptRequestSchema, +} from "@modelcontextprotocol/sdk/types.js"; +// import { Logger } from "../package/dist/utils/logger.js"; // Removed - using console instead +import { PROTOCOL } from "./fixed-constants.js"; +import { executeGeminiCLI, getChunkedEdits } from "./fixed-geminiExecutor.js"; + +const server = new Server({ + name: "gemini-cli-mcp-fixed", + version: "1.1.4-fixed", +}, { + capabilities: { + tools: {}, + prompts: {}, + notifications: {}, + logging: {}, + }, +}); + +let isProcessing = false; +let currentOperationName = ""; +let latestOutput = ""; + +async function sendNotification(method, params) { + try { + await server.notification({ method, params }); + } + catch (error) { + console.error("notification failed: ", error); + } +} + +async function sendProgressNotification(progressToken, progress, total, message) { + if (!progressToken) + return; + try { + const params = { + progressToken, + progress + }; + if (total !== undefined) + params.total = total; + if (message) + params.message = message; + await server.notification({ + method: PROTOCOL.NOTIFICATIONS.PROGRESS, + params + }); + } + catch (error) { + console.error("Progress notification failed: ", error); + } +} + +// Tool definitions +const tools = [ + { + name: "ask-gemini", + description: "model selection [-m], sandbox [-s], and changeMode:boolean for providing edits", + inputSchema: { + type: "object", + properties: { + prompt: { + type: "string", + minLength: 1, + description: "Analysis request. Use @ syntax to include files (e.g., '@largefile.js explain what this does') or ask general questions" + }, + model: { + type: "string", + description: "Optional model to use (e.g., 'gemini-2.5-flash'). If not specified, uses the default model (gemini-2.5-pro)." + }, + sandbox: { + type: "boolean", + default: false, + description: "Use sandbox mode (-s flag) to safely test code changes, execute scripts, or run potentially risky operations in an isolated environment" + }, + changeMode: { + type: "boolean", + default: false, + description: "Enable structured change mode - formats prompts to prevent tool errors and returns structured edit suggestions that Claude can apply directly" + }, + chunkIndex: { + type: ["number", "string"], + description: "Which chunk to return (1-based)" + }, + chunkCacheKey: { + type: "string", + description: "Optional cache key for continuation" + }, + powershellPath: { + type: "string", + description: "Optional custom PowerShell executable path (e.g., 'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe' or 'pwsh'). If not specified, auto-detects available PowerShell." + } + }, + required: ["prompt"] + } + }, + { + name: "ping", + description: "Echo", + inputSchema: { + type: "object", + properties: { + prompt: { + type: "string", + default: "", + description: "Message to echo " + } + }, + required: [] + } + }, + { + name: "Help", + description: "receive help information", + inputSchema: { + type: "object", + properties: {}, + required: [] + } + }, + { + name: "brainstorm", + description: "Generate novel ideas with dynamic context gathering. --> Creative frameworks (SCAMPER, Design Thinking, etc.), domain context integration, idea clustering, feasibility analysis, and iterative refinement.", + inputSchema: { + type: "object", + properties: { + prompt: { + type: "string", + minLength: 1, + description: "Primary brainstorming challenge or question to explore" + }, + model: { + type: "string", + description: "Optional model to use (e.g., 'gemini-2.5-flash'). If not specified, uses the default model (gemini-2.5-pro)." + }, + methodology: { + type: "string", + enum: ["divergent", "convergent", "scamper", "design-thinking", "lateral", "auto"], + default: "auto", + description: "Brainstorming framework: 'divergent' (generate many ideas), 'convergent' (refine existing), 'scamper' (systematic triggers), 'design-thinking' (human-centered), 'lateral' (unexpected connections), 'auto' (AI selects best)" + }, + domain: { + type: "string", + description: "Domain context for specialized brainstorming (e.g., 'software', 'business', 'creative', 'research', 'product', 'marketing')" + }, + constraints: { + type: "string", + description: "Known limitations, requirements, or boundaries (budget, time, technical, legal, etc.)" + }, + existingContext: { + type: "string", + description: "Background information, previous attempts, or current state to build upon" + }, + ideaCount: { + type: "integer", + exclusiveMinimum: 0, + default: 12, + description: "Target number of ideas to generate (default: 10-15)" + }, + includeAnalysis: { + type: "boolean", + default: true, + description: "Include feasibility, impact, and implementation analysis for generated ideas" + }, + powershellPath: { + type: "string", + description: "Optional custom PowerShell executable path (e.g., 'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe' or 'pwsh'). If not specified, auto-detects available PowerShell." + } + }, + required: ["prompt"] + } + }, + { + name: "fetch-chunk", + description: "Retrieves cached chunks from a changeMode response. Use this to get subsequent chunks after receiving a partial changeMode response.", + inputSchema: { + type: "object", + properties: { + cacheKey: { + type: "string", + description: "The cache key provided in the initial changeMode response" + }, + chunkIndex: { + type: "number", + minimum: 1, + description: "Which chunk to retrieve (1-based index)" + } + }, + required: ["cacheKey", "chunkIndex"] + } + }, + { + name: "timeout-test", + description: "Test timeout prevention by running for a specified duration", + inputSchema: { + type: "object", + properties: { + duration: { + type: "number", + minimum: 10, + description: "Duration in milliseconds (minimum 10ms)" + } + }, + required: ["duration"] + } + } +]; + +// List available tools +server.setRequestHandler(ListToolsRequestSchema, async () => { + return { tools }; +}); + +// Handle tool execution +server.setRequestHandler(CallToolRequestSchema, async (request) => { + const { name, arguments: args } = request.params; + + console.error(`[GMCPT] Tool called: ${name}`); + console.error(`[GMCPT] Arguments:`, JSON.stringify(args, null, 2)); + + try { + switch (name) { + case "ask-gemini": + const { prompt, model, sandbox, changeMode, chunkIndex, chunkCacheKey, powershellPath } = args; + console.error('[GMCPT] ask-gemini tool called with prompt: ' + prompt.substring(0, 50) + '...'); + console.error('[GMCPT] Model: ' + model + ', Sandbox: ' + sandbox + ', ChangeMode: ' + changeMode); + if (powershellPath) { + console.error('[GMCPT] Custom PowerShell path: ' + powershellPath); + } + + if (chunkCacheKey && chunkIndex) { + const result = getChunkedEdits(chunkCacheKey, parseInt(chunkIndex)); + return { + content: [{ + type: "text", + text: result + }] + }; + } + + console.error('[GMCPT] About to call executeGeminiCLI...'); + const result = await executeGeminiCLI(prompt, model, sandbox, changeMode, powershellPath); + console.error('[GMCPT] executeGeminiCLI completed with result length: ' + result.length); + return { + content: [{ + type: "text", + text: result + }] + }; + + case "ping": + return { + content: [{ + type: "text", + text: `Pong! ${args.prompt || 'Hello from gemini-cli MCP server!'}` + }] + }; + + case "Help": + return { + content: [{ + type: "text", + text: "Gemini CLI MCP Tool - Fixed Version\n\nAvailable commands:\n- ask-gemini: Interact with Gemini CLI\n- ping: Test connection\n- Help: Show this help\n- brainstorm: Generate novel ideas with creative frameworks\n- fetch-chunk: Retrieve cached chunks from changeMode responses\n- timeout-test: Test timeout prevention" + }] + }; + + case "brainstorm": + const { + prompt: brainstormPrompt, + model: brainstormModel, + methodology, + domain, + constraints, + existingContext, + ideaCount, + includeAnalysis, + powershellPath: brainstormPowershellPath + } = args; + + console.error('[GMCPT] brainstorm tool called with prompt: ' + brainstormPrompt.substring(0, 50) + '...'); + console.error('[GMCPT] Methodology: ' + methodology + ', Domain: ' + domain); + + // Build enhanced brainstorming prompt + let enhancedPrompt = `BRAINSTORMING SESSION\n\nChallenge: ${brainstormPrompt}\n\n`; + + if (methodology && methodology !== 'auto') { + enhancedPrompt += `Framework: Use ${methodology} methodology for idea generation.\n`; + } + + if (domain) { + enhancedPrompt += `Domain Context: ${domain}\n`; + } + + if (constraints) { + enhancedPrompt += `Constraints: ${constraints}\n`; + } + + if (existingContext) { + enhancedPrompt += `Background: ${existingContext}\n`; + } + + enhancedPrompt += `\nGenerate ${ideaCount || 12} creative and diverse ideas. `; + + if (includeAnalysis !== false) { + enhancedPrompt += `For each idea, provide a brief feasibility assessment and potential impact.`; + } + + const brainstormResult = await executeGeminiCLI(enhancedPrompt, brainstormModel, false, false, brainstormPowershellPath); + return { + content: [{ + type: "text", + text: brainstormResult + }] + }; + + case "fetch-chunk": + const { cacheKey, chunkIndex: fetchChunkIndex } = args; + console.error('[GMCPT] fetch-chunk tool called with cacheKey: ' + cacheKey + ', chunkIndex: ' + fetchChunkIndex); + + const chunkResult = getChunkedEdits(cacheKey, parseInt(fetchChunkIndex)); + return { + content: [{ + type: "text", + text: chunkResult + }] + }; + + case "timeout-test": + const { duration } = args; + console.error('[GMCPT] timeout-test tool called with duration: ' + duration + 'ms'); + + return new Promise((resolve) => { + setTimeout(() => { + resolve({ + content: [{ + type: "text", + text: `Timeout test completed after ${duration}ms` + }] + }); + }, Math.max(10, duration)); + }); + + default: + throw new Error(`Unknown tool: ${name}`); + } + } catch (error) { + console.error(`Error executing ${name}: ${error.message}`); + return { + content: [{ + type: "text", + text: `Error executing ${name}: ${error.message}` + }], + isError: true + }; + } +}); + +// Start the server +async function main() { + const transport = new StdioServerTransport(); + await server.connect(transport); + console.log("[GMCPT] Gemini CLI MCP Server (Fixed) started"); +} + +main().catch((error) => { + console.error("Server failed to start:", error); + process.exit(1); }); \ No newline at end of file diff --git a/package.json b/package.json index aaa53ae..f4eda0b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gemini-mcp-tool-windows-fixed", - "version": "1.0.2", + "version": "1.0.3", "type": "module", "description": "Windows-compatible MCP server that enables AI assistants to interact with Google Gemini CLI - Fixed version for Windows environments", "main": "index.js", diff --git a/test-brainstorm-dev.cjs b/test-brainstorm-dev.cjs new file mode 100644 index 0000000..4b39d81 --- /dev/null +++ b/test-brainstorm-dev.cjs @@ -0,0 +1,74 @@ +const { spawn } = require('child_process'); +const path = require('path'); + +// Test the local development version of MCP tool +function testBrainstormDev() { + console.log('Testing brainstorm functionality with local development version...'); + + // Create a test MCP request for brainstorm + const mcpRequest = { + jsonrpc: '2.0', + id: 1, + method: 'tools/call', + params: { + name: 'brainstorm', + arguments: { + prompt: '如何提高团队协作效率', + model: 'gemini-1.5-flash', + methodology: 'structured', + domain: 'business', + ideaCount: 3 + } + } + }; + + const mcpToolPath = path.join(__dirname, 'lib', 'fixed-mcp-tool.js'); + console.log(`Using MCP tool at: ${mcpToolPath}`); + + const childProcess = spawn('node', [mcpToolPath], { + stdio: ['pipe', 'pipe', 'pipe'], + env: { + ...process.env, + GEMINI_API_KEY: process.env.GEMINI_API_KEY || 'test_key' + } + }); + + let stdout = ''; + let stderr = ''; + + childProcess.stdout.on('data', (data) => { + stdout += data.toString(); + console.log('STDOUT:', data.toString()); + }); + + childProcess.stderr.on('data', (data) => { + stderr += data.toString(); + console.log('STDERR:', data.toString()); + }); + + childProcess.on('error', (error) => { + console.error('Process error:', error.message); + }); + + childProcess.on('close', (code) => { + console.log(`Process exited with code: ${code}`); + console.log('=== FINAL STDOUT ==='); + console.log(stdout); + console.log('=== FINAL STDERR ==='); + console.log(stderr); + }); + + // Send the MCP request + console.log('Sending MCP request:', JSON.stringify(mcpRequest, null, 2)); + childProcess.stdin.write(JSON.stringify(mcpRequest) + '\n'); + + // Wait a bit then close stdin + setTimeout(() => { + childProcess.stdin.end(); + }, 1000); +} + +// Run the test +testBrainstormDev(); + +console.log('Test started. Check output above for results.'); \ No newline at end of file diff --git a/test-brainstorm.js b/test-brainstorm.js new file mode 100644 index 0000000..fad19b3 --- /dev/null +++ b/test-brainstorm.js @@ -0,0 +1,91 @@ +import { executeGeminiCLI } from './lib/fixed-geminiExecutor.js'; +import dotenv from 'dotenv'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +dotenv.config({ path: path.join(__dirname, 'lib', '.env') }); + +console.log('=== Testing Brainstorm Tool Execution ==='); +console.log(`GEMINI_API_KEY loaded: ${process.env.GEMINI_API_KEY ? 'YES' : 'NO'}`); +console.log(`Current working directory: ${process.cwd()}`); +console.log(`Script directory: ${__dirname}`); + +// Simulate the exact brainstorm call that's failing +async function testBrainstormExecution() { + try { + console.log('\n--- Testing Brainstorm Execution ---'); + + // This is the exact prompt structure used by brainstorm tool + const brainstormPrompt = `BRAINSTORMING SESSION + +Challenge: 设计一个可持续能源解决方案 + +Generate 12 creative and diverse ideas. For each idea, provide a brief feasibility assessment and potential impact.`; + + console.log('Calling executeGeminiCLI with brainstorm prompt...'); + console.log('Prompt preview:', brainstormPrompt.substring(0, 100) + '...'); + + const result = await executeGeminiCLI(brainstormPrompt, undefined, false, false); + + console.log('✅ Brainstorm execution successful!'); + console.log('Result length:', result.length); + console.log('Result preview:', result.substring(0, 200) + '...'); + + } catch (error) { + console.log('❌ Brainstorm execution failed!'); + console.log('Error message:', error.message); + console.log('Error stack:', error.stack); + console.log('Error code:', error.code); + console.log('Error errno:', error.errno); + console.log('Error syscall:', error.syscall); + console.log('Error path:', error.path); + } +} + +// Test with different scenarios +async function testMultipleScenarios() { + const scenarios = [ + { + name: 'Simple English prompt', + prompt: 'BRAINSTORMING SESSION\n\nChallenge: Design a sustainable energy solution\n\nGenerate 5 creative ideas.' + }, + { + name: 'Chinese prompt (original failing case)', + prompt: 'BRAINSTORMING SESSION\n\nChallenge: 设计一个可持续能源解决方案\n\nGenerate 12 creative and diverse ideas. For each idea, provide a brief feasibility assessment and potential impact.' + }, + { + name: 'Mixed language prompt', + prompt: 'BRAINSTORMING SESSION\n\nChallenge: Design a 可持续能源 solution\n\nGenerate 3 ideas.' + } + ]; + + for (const scenario of scenarios) { + console.log(`\n=== Testing: ${scenario.name} ===`); + try { + const result = await executeGeminiCLI(scenario.prompt, undefined, false, false); + console.log(`✅ ${scenario.name}: Success (${result.length} chars)`); + } catch (error) { + console.log(`❌ ${scenario.name}: Failed - ${error.message}`); + if (error.message.includes('spawn powershell.exe ENOENT')) { + console.log('🔍 This is the exact error reported by the user!'); + } + } + } +} + +// Run all tests +async function runAllTests() { + console.log('Starting comprehensive brainstorm testing...'); + + await testBrainstormExecution(); + await testMultipleScenarios(); + + console.log('\n=== Testing completed ==='); +} + +runAllTests().catch(error => { + console.error('Test runner failed:', error); + process.exit(1); +}); \ No newline at end of file diff --git a/test-mcp-powershell.js b/test-mcp-powershell.js new file mode 100644 index 0000000..2dfa290 --- /dev/null +++ b/test-mcp-powershell.js @@ -0,0 +1,134 @@ +import { spawn } from 'child_process'; +import dotenv from 'dotenv'; +import path from 'path'; +import { fileURLToPath } from 'url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +dotenv.config({ path: path.join(__dirname, 'lib', '.env') }); + +// Function to get PowerShell executable based on platform +function getPowerShellExecutable() { + if (process.platform === 'win32') { + return 'powershell.exe'; + } + return 'pwsh'; +} + +const POWERSHELL_EXECUTABLE = getPowerShellExecutable(); + +// Simulate the exact environment and command used by the MCP tool +async function testMCPPowerShellCall() { + console.log('=== Testing MCP PowerShell Call ==='); + console.log(`PowerShell executable: ${POWERSHELL_EXECUTABLE}`); + console.log(`GEMINI_API_KEY loaded: ${process.env.GEMINI_API_KEY ? 'YES' : 'NO'}`); + + // Create environment similar to what MCP tool uses + const env = { + ...process.env, + GEMINI_API_KEY: process.env.GEMINI_API_KEY + }; + + // Test the exact command pattern used by brainstorm tool + const testCommand = 'echo "Testing brainstorm command simulation"'; + + return new Promise((resolve, reject) => { + console.log(`Executing command: ${POWERSHELL_EXECUTABLE} -Command "${testCommand}"`); + + const childProcess = spawn(POWERSHELL_EXECUTABLE, ['-Command', testCommand], { + env: env, + stdio: ['pipe', 'pipe', 'pipe'] + }); + + let stdout = ''; + let stderr = ''; + + childProcess.stdout.on('data', (data) => { + stdout += data.toString(); + console.log('stdout chunk:', data.toString().trim()); + }); + + childProcess.stderr.on('data', (data) => { + stderr += data.toString(); + console.log('stderr chunk:', data.toString().trim()); + }); + + childProcess.on('error', (error) => { + console.log('Process error:', error.message); + console.log('Error code:', error.code); + console.log('Error errno:', error.errno); + console.log('Error syscall:', error.syscall); + console.log('Error path:', error.path); + reject(error); + }); + + childProcess.on('close', (code) => { + console.log(`Process exited with code: ${code}`); + console.log(`Final stdout: ${stdout}`); + console.log(`Final stderr: ${stderr}`); + + if (code === 0) { + resolve({ stdout, stderr }); + } else { + reject(new Error(`Command failed with exit code ${code}: ${stderr}`)); + } + }); + + // Test with piped input (like the actual MCP tool does) + const testInput = 'Test input for PowerShell'; + childProcess.stdin.write(testInput); + childProcess.stdin.end(); + }); +} + +// Test different PowerShell executable options +async function testDifferentExecutables() { + const executables = [ + 'powershell.exe', + 'powershell', + 'C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\powershell.exe', + 'pwsh' + ]; + + for (const exe of executables) { + console.log(`\n=== Testing executable: ${exe} ===`); + + try { + const result = await new Promise((resolve, reject) => { + const proc = spawn(exe, ['-Command', 'echo "Success with ' + exe + '"'], { + stdio: ['pipe', 'pipe', 'pipe'] + }); + + let output = ''; + proc.stdout.on('data', (data) => output += data.toString()); + proc.on('error', reject); + proc.on('close', (code) => { + if (code === 0) { + resolve(output.trim()); + } else { + reject(new Error(`Exit code ${code}`)); + } + }); + }); + + console.log(`✅ ${exe}: ${result}`); + } catch (error) { + console.log(`❌ ${exe}: ${error.message}`); + } + } +} + +// Run tests +async function runAllTests() { + try { + await testDifferentExecutables(); + console.log('\n' + '='.repeat(50)); + await testMCPPowerShellCall(); + console.log('\n✅ All tests completed successfully'); + } catch (error) { + console.log('\n❌ Test failed:', error.message); + console.log('Error details:', error); + } +} + +runAllTests(); \ No newline at end of file diff --git a/test-powershell-fix.cjs b/test-powershell-fix.cjs new file mode 100644 index 0000000..13b84fa --- /dev/null +++ b/test-powershell-fix.cjs @@ -0,0 +1,72 @@ +const { spawn } = require('child_process'); +const path = require('path'); + +// Test PowerShell execution directly +function testPowerShellFix() { + console.log('Testing PowerShell execution fix...'); + + // Import the fixed executor + const executorPath = path.join(__dirname, 'lib', 'fixed-geminiExecutor.js'); + + // Test simple PowerShell command + const testCommand = 'Write-Host "PowerShell test successful"'; + + console.log('Testing PowerShell command execution...'); + + const childProcess = spawn('node', ['-e', ` + import('${executorPath.replace(/\\/g, '/')}') + .then(module => { + return module.executeCommandWithPipedInput('${testCommand}', { TEST: 'value' }); + }) + .then(result => { + console.log('SUCCESS: PowerShell command executed'); + console.log('STDOUT:', result.stdout); + console.log('STDERR:', result.stderr); + }) + .catch(error => { + console.error('ERROR:', error.message); + if (error.message.includes('ENOENT')) { + console.error('ENOENT error still present!'); + } else { + console.log('No ENOENT error - PowerShell found successfully'); + } + }); + `], { + stdio: ['pipe', 'pipe', 'pipe'], + env: process.env + }); + + let stdout = ''; + let stderr = ''; + + childProcess.stdout.on('data', (data) => { + stdout += data.toString(); + console.log('STDOUT:', data.toString().trim()); + }); + + childProcess.stderr.on('data', (data) => { + stderr += data.toString(); + console.log('STDERR:', data.toString().trim()); + }); + + childProcess.on('error', (error) => { + console.error('Process error:', error.message); + }); + + childProcess.on('close', (code) => { + console.log(`\nTest completed with exit code: ${code}`); + + if (stderr.includes('ENOENT')) { + console.log('❌ ENOENT error still present'); + } else if (stdout.includes('PowerShell test successful') || stdout.includes('SUCCESS')) { + console.log('✅ PowerShell execution successful - ENOENT error fixed!'); + } else { + console.log('⚠️ Test completed but results unclear'); + } + }); +} + +// Run the test +testPowerShellFix(); + +console.log('PowerShell fix test started...'); \ No newline at end of file diff --git a/test-powershell-path.cjs b/test-powershell-path.cjs new file mode 100644 index 0000000..6ca0473 --- /dev/null +++ b/test-powershell-path.cjs @@ -0,0 +1,105 @@ +const { spawn } = require('child_process'); +const path = require('path'); + +// Test the new powershellPath parameter functionality +const testPowershellPath = async () => { + console.log('Testing PowerShell path parameter functionality...'); + + // Test 1: Using default PowerShell path + console.log('\n=== Test 1: Default PowerShell path ==='); + const test1 = spawn('node', ['index.js'], { + cwd: process.cwd(), + stdio: ['pipe', 'pipe', 'pipe'] + }); + + // Send MCP request for brainstorm without powershellPath + const mcpRequest1 = { + jsonrpc: '2.0', + id: 1, + method: 'tools/call', + params: { + name: 'brainstorm', + arguments: { + topic: 'test topic', + count: 1 + } + } + }; + + test1.stdin.write(JSON.stringify(mcpRequest1) + '\n'); + test1.stdin.end(); + + let output1 = ''; + let error1 = ''; + + test1.stdout.on('data', (data) => { + output1 += data.toString(); + }); + + test1.stderr.on('data', (data) => { + error1 += data.toString(); + }); + + await new Promise((resolve) => { + test1.on('close', (code) => { + console.log(`Test 1 exit code: ${code}`); + console.log('Test 1 output:', output1.substring(0, 200) + '...'); + if (error1) { + console.log('Test 1 error:', error1.substring(0, 200) + '...'); + } + resolve(); + }); + }); + + // Test 2: Using custom PowerShell path + console.log('\n=== Test 2: Custom PowerShell path ==='); + const test2 = spawn('node', ['index.js'], { + cwd: process.cwd(), + stdio: ['pipe', 'pipe', 'pipe'] + }); + + // Send MCP request for brainstorm with custom powershellPath + const mcpRequest2 = { + jsonrpc: '2.0', + id: 2, + method: 'tools/call', + params: { + name: 'brainstorm', + arguments: { + topic: 'test topic with custom path', + count: 1, + powershellPath: 'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe' + } + } + }; + + test2.stdin.write(JSON.stringify(mcpRequest2) + '\n'); + test2.stdin.end(); + + let output2 = ''; + let error2 = ''; + + test2.stdout.on('data', (data) => { + output2 += data.toString(); + }); + + test2.stderr.on('data', (data) => { + error2 += data.toString(); + }); + + await new Promise((resolve) => { + test2.on('close', (code) => { + console.log(`Test 2 exit code: ${code}`); + console.log('Test 2 output:', output2.substring(0, 200) + '...'); + if (error2) { + console.log('Test 2 error:', error2.substring(0, 200) + '...'); + } + resolve(); + }); + }); + + console.log('\n=== PowerShell Path Parameter Test Complete ==='); + console.log('Both tests should show PowerShell executable paths in the logs.'); +}; + +testPowershellPath().catch(console.error); \ No newline at end of file diff --git a/test-powershell.js b/test-powershell.js new file mode 100644 index 0000000..007144a --- /dev/null +++ b/test-powershell.js @@ -0,0 +1,84 @@ +import { spawn } from 'child_process'; + +// Function to get PowerShell executable based on platform +function getPowerShellExecutable() { + // On Windows, try powershell.exe first (Windows PowerShell), then pwsh (PowerShell Core) + if (process.platform === 'win32') { + return 'powershell.exe'; + } + // On other platforms, use pwsh (PowerShell Core) + return 'pwsh'; +} + +const POWERSHELL_EXECUTABLE = getPowerShellExecutable(); +console.log(`Testing PowerShell executable: ${POWERSHELL_EXECUTABLE}`); +console.log(`Platform: ${process.platform}`); +console.log(`PATH contains:`, process.env.PATH.split(';').filter(p => p.includes('PowerShell') || p.includes('System32'))); + +// Test 1: Basic spawn test +console.log('\n=== Test 1: Basic spawn test ==='); +const test1 = spawn(POWERSHELL_EXECUTABLE, ['-Command', 'echo "Hello from PowerShell"'], { + stdio: ['pipe', 'pipe', 'pipe'] +}); + +test1.stdout.on('data', (data) => { + console.log('Test 1 stdout:', data.toString().trim()); +}); + +test1.stderr.on('data', (data) => { + console.log('Test 1 stderr:', data.toString().trim()); +}); + +test1.on('error', (error) => { + console.log('Test 1 error:', error.message); +}); + +test1.on('close', (code) => { + console.log('Test 1 exit code:', code); + + // Test 2: Full path test + console.log('\n=== Test 2: Full path test ==='); + const fullPath = 'C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\powershell.exe'; + const test2 = spawn(fullPath, ['-Command', 'echo "Hello from full path PowerShell"'], { + stdio: ['pipe', 'pipe', 'pipe'] + }); + + test2.stdout.on('data', (data) => { + console.log('Test 2 stdout:', data.toString().trim()); + }); + + test2.stderr.on('data', (data) => { + console.log('Test 2 stderr:', data.toString().trim()); + }); + + test2.on('error', (error) => { + console.log('Test 2 error:', error.message); + }); + + test2.on('close', (code) => { + console.log('Test 2 exit code:', code); + + // Test 3: Environment test + console.log('\n=== Test 3: Environment test ==='); + const test3 = spawn(POWERSHELL_EXECUTABLE, ['-Command', '$env:PATH -split ";" | Where-Object { $_ -like "*PowerShell*" -or $_ -like "*System32*" }'], { + stdio: ['pipe', 'pipe', 'pipe'] + }); + + test3.stdout.on('data', (data) => { + console.log('Test 3 stdout:', data.toString().trim()); + }); + + test3.stderr.on('data', (data) => { + console.log('Test 3 stderr:', data.toString().trim()); + }); + + test3.on('error', (error) => { + console.log('Test 3 error:', error.message); + }); + + test3.on('close', (code) => { + console.log('Test 3 exit code:', code); + console.log('\n=== All tests completed ==='); + }); + }); +}); \ No newline at end of file diff --git a/test-simple-powershell.cjs b/test-simple-powershell.cjs new file mode 100644 index 0000000..1e46248 --- /dev/null +++ b/test-simple-powershell.cjs @@ -0,0 +1,65 @@ +const { spawn } = require('child_process'); + +// Simple test to verify PowerShell can be found and executed +function testSimplePowerShell() { + console.log('Testing simple PowerShell execution...'); + + // Test 1: Try powershell.exe directly + console.log('\n=== Test 1: powershell.exe ==='); + const ps1 = spawn('powershell.exe', ['-Command', 'Write-Host "Test 1 Success"'], { + stdio: ['pipe', 'pipe', 'pipe'] + }); + + ps1.stdout.on('data', (data) => { + console.log('✅ STDOUT:', data.toString().trim()); + }); + + ps1.stderr.on('data', (data) => { + console.log('❌ STDERR:', data.toString().trim()); + }); + + ps1.on('error', (error) => { + if (error.code === 'ENOENT') { + console.log('❌ ENOENT error: powershell.exe not found'); + } else { + console.log('❌ Other error:', error.message); + } + }); + + ps1.on('close', (code) => { + console.log(`Test 1 completed with code: ${code}`); + + // Test 2: Try full path + console.log('\n=== Test 2: Full path ==='); + const ps2 = spawn('C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\powershell.exe', + ['-Command', 'Write-Host "Test 2 Success"'], { + stdio: ['pipe', 'pipe', 'pipe'] + }); + + ps2.stdout.on('data', (data) => { + console.log('✅ STDOUT:', data.toString().trim()); + }); + + ps2.stderr.on('data', (data) => { + console.log('❌ STDERR:', data.toString().trim()); + }); + + ps2.on('error', (error) => { + if (error.code === 'ENOENT') { + console.log('❌ ENOENT error: Full path PowerShell not found'); + } else { + console.log('❌ Other error:', error.message); + } + }); + + ps2.on('close', (code) => { + console.log(`Test 2 completed with code: ${code}`); + console.log('\n=== Summary ==='); + console.log('If you see "Test 1 Success" or "Test 2 Success" above, PowerShell is working!'); + console.log('If you see ENOENT errors, PowerShell path issues still exist.'); + }); + }); +} + +// Run the test +testSimplePowerShell(); \ No newline at end of file From caf20a0a0480cdec0e78fa8aef595cc79caec409 Mon Sep 17 00:00:00 2001 From: User Date: Mon, 4 Aug 2025 08:39:26 +0800 Subject: [PATCH 10/28] docs: Update documentation for v1.0.3 with PowerShell path parameter - Update version references from 1.0.2 to 1.0.3 in all documentation - Add PowerShell path parameter feature description - Update installation commands and configuration examples - Maintain backward compatibility information --- INSTALL-GUIDE.md | 18 +++++++++--------- README.md | 16 +++++++++------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/INSTALL-GUIDE.md b/INSTALL-GUIDE.md index ae2ac5c..afb686f 100644 --- a/INSTALL-GUIDE.md +++ b/INSTALL-GUIDE.md @@ -1,10 +1,10 @@ # 🚀 Gemini MCP Tool - Windows Fixed Version Installation Guide -> **最新版本 v1.0.2** - 修复了 PowerShell 执行错误,解决了 `spawn powershell.exe ENOENT` 问题 +> **最新版本 v1.0.3** - 添加了 PowerShell 路径参数支持,允许用户自定义 PowerShell 可执行文件路径 ## 🆕 版本更新日志 -### v1.0.2 (最新) +### v1.0.3 (最新) - ✅ **修复 PowerShell 执行错误** - 解决 `spawn powershell.exe ENOENT` 问题 - ✅ **改进 Windows 兼容性** - 自动检测可用的 PowerShell 版本 - ✅ **修复未定义变量错误** - 修复 `executeCommandWithPipedInput` 函数中的 `args` 变量问题 @@ -43,7 +43,7 @@ ```powershell # 使用最新版本 (推荐) -npx gemini-mcp-tool-windows-fixed@1.0.2 +npx gemini-mcp-tool-windows-fixed@1.0.3 # 或者使用最新版本标签 npx -y gemini-mcp-tool-windows-fixed@latest @@ -53,7 +53,7 @@ npx -y gemini-mcp-tool-windows-fixed@latest ```powershell # 安装最新版本 -npm install -g gemini-mcp-tool-windows-fixed@1.0.2 +npm install -g gemini-mcp-tool-windows-fixed@1.0.3 # 测试工具 gemini-mcp-tool-windows-fixed @@ -71,7 +71,7 @@ npm uninstall -g gemini-mcp-tool-windows-fixed npm cache clean --force # 安装最新版本 -npm install -g gemini-mcp-tool-windows-fixed@1.0.2 +npm install -g gemini-mcp-tool-windows-fixed@1.0.3 ``` ## ⚙️ MCP Client Configuration @@ -80,7 +80,7 @@ npm install -g gemini-mcp-tool-windows-fixed@1.0.2 ```bash # One-command setup for Claude Code -claude mcp add gemini-cli -- npx -y gemini-mcp-tool-windows-fixed@1.0.2 +claude mcp add gemini-cli -- npx -y gemini-mcp-tool-windows-fixed@1.0.3 ``` ### For Development/Testing (Local Version) @@ -160,7 +160,7 @@ If you already have it configured in Claude Desktop: "command": "npx", "args": [ "-y", - "gemini-mcp-tool-windows-fixed@1.0.2" + "gemini-mcp-tool-windows-fixed@1.0.3" ], "env": { "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" @@ -182,7 +182,7 @@ If you already have it configured in Claude Desktop: "mcpServers": { "gemini-cli": { "command": "npx", - "args": ["-y", "gemini-mcp-tool-windows-fixed@1.0.2"], + "args": ["-y", "gemini-mcp-tool-windows-fixed@1.0.3"], "env": { "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" } @@ -294,7 +294,7 @@ npx gemini-mcp-tool-windows-fixed@1.0.2 ``` **原因:** 旧版本 (v1.0.0, v1.0.1) 存在 PowerShell 执行路径问题 -**解决方案:** 更新到 v1.0.2 或更高版本 +**解决方案:** 更新到 v1.0.3 或更高版本 #### 6. PowerShell 版本兼容性 diff --git a/README.md b/README.md index 1d7d615..d275e7a 100644 --- a/README.md +++ b/README.md @@ -3,18 +3,20 @@ [![npm version](https://badge.fury.io/js/gemini-mcp-tool-windows-fixed.svg)](https://badge.fury.io/js/gemini-mcp-tool-windows-fixed) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -> **最新版本 v1.0.2** - 修复了 PowerShell 执行错误,解决了 `spawn powershell.exe ENOENT` 问题 +> **最新版本 v1.0.3** - 添加了 PowerShell 路径参数支持,允许用户自定义 PowerShell 可执行文件路径 A **Windows-compatible** Model Context Protocol (MCP) server that enables AI assistants to interact with Google's Gemini CLI. This is a fixed version specifically designed to work seamlessly on Windows environments with PowerShell support. > **Note**: This is an enhanced version of the [original gemini-mcp-tool](https://github.com/jamubc/gemini-mcp-tool) with Windows-specific fixes and improvements. -## 🆕 最新更新 (v1.0.2) +## 🆕 最新更新 (v1.0.3) +- 🆕 **PowerShell 路径参数支持** - 添加可选的 `powershellPath` 参数,允许用户自定义 PowerShell 可执行文件路径 - ✅ **修复 PowerShell 执行错误** - 解决 `spawn powershell.exe ENOENT` 问题 - ✅ **改进 Windows 兼容性** - 自动检测可用的 PowerShell 版本 - ✅ **修复未定义变量错误** - 修复 `executeCommandWithPipedInput` 函数中的 `args` 变量问题 - ✅ **增强错误处理** - 更好的错误信息和调试输出 +- ✅ **向后兼容** - 现有配置无需修改,自动使用默认检测逻辑 ## ✨ Features @@ -55,7 +57,7 @@ This Windows-fixed version resolves: ```powershell # 使用最新版本 (推荐) -npx gemini-mcp-tool-windows-fixed@1.0.2 +npx gemini-mcp-tool-windows-fixed@1.0.3 # 或者使用最新版本标签 npx -y gemini-mcp-tool-windows-fixed@latest @@ -65,7 +67,7 @@ npx -y gemini-mcp-tool-windows-fixed@latest ```powershell # 安装最新版本 -npm install -g gemini-mcp-tool-windows-fixed@1.0.2 +npm install -g gemini-mcp-tool-windows-fixed@1.0.3 # 运行工具 gemini-mcp-tool-windows-fixed @@ -88,7 +90,7 @@ npm install -g gemini-mcp-tool-windows-fixed@1.0.2 ```bash # One-command setup for Claude Code -claude mcp add gemini-cli -- npx -y gemini-mcp-tool-windows-fixed@1.0.2 +claude mcp add gemini-cli -- npx -y gemini-mcp-tool-windows-fixed@1.0.3 ``` **Verify Installation:** @@ -118,7 +120,7 @@ If you already have it configured in Claude Desktop: "command": "npx", "args": [ "-y", - "gemini-mcp-tool-windows-fixed@1.0.2" + "gemini-mcp-tool-windows-fixed@1.0.3" ], "env": { "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" @@ -140,7 +142,7 @@ If you already have it configured in Claude Desktop: "mcpServers": { "gemini-cli": { "command": "npx", - "args": ["-y", "gemini-mcp-tool-windows-fixed@1.0.2"], + "args": ["-y", "gemini-mcp-tool-windows-fixed@1.0.3"], "env": { "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" } From c2dc6f49492259792c731911f3057ae35a852d77 Mon Sep 17 00:00:00 2001 From: User Date: Mon, 4 Aug 2025 08:49:59 +0800 Subject: [PATCH 11/28] docs: Ensure all documentation uses v1.0.3 and add PowerShell path configuration examples - Update remaining v1.0.2 references to v1.0.3 in INSTALL-GUIDE.md and README.md - Add comprehensive PowerShell path parameter documentation to claude-config-v1.0.3.json - Include usage examples for brainstorm and ask-gemini tools with custom PowerShell paths - Document common PowerShell installation paths for different Windows versions - Emphasize backward compatibility of the optional powershellPath parameter --- INSTALL-GUIDE.md | 6 +++--- README.md | 2 +- claude-config-v1.0.3.json | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 37 insertions(+), 4 deletions(-) create mode 100644 claude-config-v1.0.3.json diff --git a/INSTALL-GUIDE.md b/INSTALL-GUIDE.md index afb686f..73f3004 100644 --- a/INSTALL-GUIDE.md +++ b/INSTALL-GUIDE.md @@ -276,12 +276,12 @@ Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser npm cache clean --force # Reinstall -npm install -g gemini-mcp-tool-windows-fixed@1.0.2 +npm install -g gemini-mcp-tool-windows-fixed@1.0.3 ``` #### 5. "spawn powershell.exe ENOENT" 错误 -这个错误在 v1.0.2 中已修复。如果仍然遇到此错误: +这个错误在 v1.0.3 中已修复。如果仍然遇到此错误: ```powershell # 确保使用最新版本 @@ -290,7 +290,7 @@ npm cache clean --force npm install -g gemini-mcp-tool-windows-fixed@1.0.2 # 或使用 npx -npx gemini-mcp-tool-windows-fixed@1.0.2 +npx gemini-mcp-tool-windows-fixed@1.0.3 ``` **原因:** 旧版本 (v1.0.0, v1.0.1) 存在 PowerShell 执行路径问题 diff --git a/README.md b/README.md index d275e7a..62cd49c 100644 --- a/README.md +++ b/README.md @@ -81,7 +81,7 @@ gemini-mcp-tool-windows-fixed # 卸载旧版本并安装最新版本 npm uninstall -g gemini-mcp-tool-windows-fixed npm cache clean --force -npm install -g gemini-mcp-tool-windows-fixed@1.0.2 +npm install -g gemini-mcp-tool-windows-fixed@1.0.3 ``` ## ⚙️ MCP Client Configuration diff --git a/claude-config-v1.0.3.json b/claude-config-v1.0.3.json new file mode 100644 index 0000000..7152b75 --- /dev/null +++ b/claude-config-v1.0.3.json @@ -0,0 +1,33 @@ +{ + "mcpServers": { + "gemini-cli": { + "command": "npx", + "args": ["-y", "gemini-mcp-tool-windows-fixed@1.0.3"], + "env": { + "GEMINI_API_KEY": "your_api_key_here" + } + } + }, + "_comments": { + "powershell_path_support": "v1.0.3 新增 PowerShell 路径参数支持", + "usage_examples": { + "brainstorm_with_custom_powershell": { + "topic": "你的主题", + "count": 5, + "powershellPath": "C:\\Program Files\\PowerShell\\7\\pwsh.exe" + }, + "ask_gemini_with_custom_powershell": { + "prompt": "你的问题", + "model": "gemini-pro", + "powershellPath": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" + } + }, + "common_powershell_paths": [ + "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe (Windows PowerShell 5.x)", + "C:\\Program Files\\PowerShell\\7\\pwsh.exe (PowerShell 7.x)", + "powershell.exe (系统PATH中的默认PowerShell)", + "pwsh.exe (系统PATH中的PowerShell 7.x)" + ], + "backward_compatibility": "powershellPath 参数是可选的,不提供时使用系统默认PowerShell" + } +} \ No newline at end of file From fa647aa685991a7aeb4d48d032d0bba50f3dfd63 Mon Sep 17 00:00:00 2001 From: User Date: Mon, 4 Aug 2025 08:50:31 +0800 Subject: [PATCH 12/28] fix: Update final v1.0.2 reference to v1.0.3 in INSTALL-GUIDE.md --- INSTALL-GUIDE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/INSTALL-GUIDE.md b/INSTALL-GUIDE.md index 73f3004..52bca62 100644 --- a/INSTALL-GUIDE.md +++ b/INSTALL-GUIDE.md @@ -287,7 +287,7 @@ npm install -g gemini-mcp-tool-windows-fixed@1.0.3 # 确保使用最新版本 npm uninstall -g gemini-mcp-tool-windows-fixed npm cache clean --force -npm install -g gemini-mcp-tool-windows-fixed@1.0.2 +npm install -g gemini-mcp-tool-windows-fixed@1.0.3 # 或使用 npx npx gemini-mcp-tool-windows-fixed@1.0.3 From c7185782a77d5e5a6c028f02c04b2e4f5ae7fceb Mon Sep 17 00:00:00 2001 From: User Date: Mon, 4 Aug 2025 08:55:41 +0800 Subject: [PATCH 13/28] docs: Add PowerShell path configuration examples to MCP JSON configs - Add comprehensive PowerShell path parameter documentation to INSTALL-GUIDE.md - Add PowerShell path configuration examples to README.md - Include usage examples for brainstorm and ask-gemini tools with custom PowerShell paths - Document common PowerShell installation paths for different Windows versions - Emphasize backward compatibility of the optional powershellPath parameter - Provide clear guidance for users with non-standard PowerShell installations --- INSTALL-GUIDE.md | 22 ++++++++++++++++++++++ README.md | 22 ++++++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/INSTALL-GUIDE.md b/INSTALL-GUIDE.md index 52bca62..72d543d 100644 --- a/INSTALL-GUIDE.md +++ b/INSTALL-GUIDE.md @@ -187,6 +187,28 @@ If you already have it configured in Claude Desktop: "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" } } + }, + "_comments": { + "powershell_path_support": "v1.0.3 新增 PowerShell 路径参数支持", + "usage_examples": { + "brainstorm_with_custom_powershell": { + "topic": "你的主题", + "count": 5, + "powershellPath": "C:\\Program Files\\PowerShell\\7\\pwsh.exe" + }, + "ask_gemini_with_custom_powershell": { + "prompt": "你的问题", + "model": "gemini-pro", + "powershellPath": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" + } + }, + "common_powershell_paths": [ + "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe (Windows PowerShell 5.x)", + "C:\\Program Files\\PowerShell\\7\\pwsh.exe (PowerShell 7.x)", + "powershell.exe (系统PATH中的默认PowerShell)", + "pwsh.exe (系统PATH中的PowerShell 7.x)" + ], + "backward_compatibility": "powershellPath 参数是可选的,不提供时使用系统默认PowerShell" } } ``` diff --git a/README.md b/README.md index 62cd49c..d46b675 100644 --- a/README.md +++ b/README.md @@ -147,6 +147,28 @@ If you already have it configured in Claude Desktop: "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" } } + }, + "_comments": { + "powershell_path_support": "v1.0.3 新增 PowerShell 路径参数支持", + "usage_examples": { + "brainstorm_with_custom_powershell": { + "topic": "你的主题", + "count": 5, + "powershellPath": "C:\\Program Files\\PowerShell\\7\\pwsh.exe" + }, + "ask_gemini_with_custom_powershell": { + "prompt": "你的问题", + "model": "gemini-pro", + "powershellPath": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" + } + }, + "common_powershell_paths": [ + "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe (Windows PowerShell 5.x)", + "C:\\Program Files\\PowerShell\\7\\pwsh.exe (PowerShell 7.x)", + "powershell.exe (系统PATH中的默认PowerShell)", + "pwsh.exe (系统PATH中的PowerShell 7.x)" + ], + "backward_compatibility": "powershellPath 参数是可选的,不提供时使用系统默认PowerShell" } } ``` From a9001b55cf317a0d4ed05de4521c26629afc3823 Mon Sep 17 00:00:00 2001 From: User Date: Mon, 4 Aug 2025 09:20:15 +0800 Subject: [PATCH 14/28] chore: Clean up project by removing test files and development artifacts - Remove all test files (test-*.js, test-*.cjs) - Remove development scripts (fix-proxy-push.ps1) - Remove temporary documentation files (POWERSHELL-FIX-SUMMARY.md, POWERSHELL-PATH-UPDATE.md) - Remove configuration examples (claude-config-v1.0.3.json, gemini-cli-test.json) - Remove old version artifacts (gemini-mcp-tool-windows-fixed-1.0.1/) - Keep only essential project files for production release --- INSTALL-GUIDE.md | 22 -- POWERSHELL-FIX-SUMMARY.md | 102 ---------- POWERSHELL-PATH-UPDATE.md | 137 ------------- README.md | 22 -- claude-config-v1.0.3.json | 33 --- fix-proxy-push.ps1 | 189 ------------------ gemini-cli-test.json | 11 - .../gemini-mcp-tool-windows-fixed-1.0.1.tar | Bin 47104 -> 0 bytes test-brainstorm-dev.cjs | 74 ------- test-brainstorm.js | 91 --------- test-mcp-powershell.js | 134 ------------- test-powershell-fix.cjs | 72 ------- test-powershell-path.cjs | 105 ---------- test-powershell.js | 84 -------- test-simple-powershell.cjs | 65 ------ 15 files changed, 1141 deletions(-) delete mode 100644 POWERSHELL-FIX-SUMMARY.md delete mode 100644 POWERSHELL-PATH-UPDATE.md delete mode 100644 claude-config-v1.0.3.json delete mode 100644 fix-proxy-push.ps1 delete mode 100644 gemini-cli-test.json delete mode 100644 gemini-mcp-tool-windows-fixed-1.0.1/gemini-mcp-tool-windows-fixed-1.0.1.tar delete mode 100644 test-brainstorm-dev.cjs delete mode 100644 test-brainstorm.js delete mode 100644 test-mcp-powershell.js delete mode 100644 test-powershell-fix.cjs delete mode 100644 test-powershell-path.cjs delete mode 100644 test-powershell.js delete mode 100644 test-simple-powershell.cjs diff --git a/INSTALL-GUIDE.md b/INSTALL-GUIDE.md index 72d543d..52bca62 100644 --- a/INSTALL-GUIDE.md +++ b/INSTALL-GUIDE.md @@ -187,28 +187,6 @@ If you already have it configured in Claude Desktop: "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" } } - }, - "_comments": { - "powershell_path_support": "v1.0.3 新增 PowerShell 路径参数支持", - "usage_examples": { - "brainstorm_with_custom_powershell": { - "topic": "你的主题", - "count": 5, - "powershellPath": "C:\\Program Files\\PowerShell\\7\\pwsh.exe" - }, - "ask_gemini_with_custom_powershell": { - "prompt": "你的问题", - "model": "gemini-pro", - "powershellPath": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - } - }, - "common_powershell_paths": [ - "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe (Windows PowerShell 5.x)", - "C:\\Program Files\\PowerShell\\7\\pwsh.exe (PowerShell 7.x)", - "powershell.exe (系统PATH中的默认PowerShell)", - "pwsh.exe (系统PATH中的PowerShell 7.x)" - ], - "backward_compatibility": "powershellPath 参数是可选的,不提供时使用系统默认PowerShell" } } ``` diff --git a/POWERSHELL-FIX-SUMMARY.md b/POWERSHELL-FIX-SUMMARY.md deleted file mode 100644 index e31fa89..0000000 --- a/POWERSHELL-FIX-SUMMARY.md +++ /dev/null @@ -1,102 +0,0 @@ -# PowerShell ENOENT 错误修复总结 - -## 问题描述 -用户报告在其他客户端配置后仍出现 `Error executing brainstorm: spawn powershell.exe ENOENT` 错误。 - -## 根本原因分析 -1. **环境变量传递不完整**:子进程没有继承完整的系统环境变量 -2. **PowerShell路径问题**:在某些环境中,相对路径 `powershell.exe` 无法被正确解析 -3. **ES模块兼容性**:项目使用ES模块,但部分代码仍使用CommonJS语法 - -## 修复措施 - -### 1. 改进PowerShell可执行文件检测 (`fixed-geminiExecutor.js`) -- 优先使用完整路径:`C:\WINDOWS\System32\WindowsPowerShell\v1.0\powershell.exe` -- 添加多个备选路径以提高兼容性 -- 增加详细的调试日志输出 - -### 2. 完善环境变量处理 -- 确保子进程继承完整的系统环境变量 (`process.env`) -- 添加必要的Windows系统变量:`SYSTEMROOT`、`WINDIR` -- 确保 `PATH` 环境变量始终可用 -- 正确传递 `GEMINI_API_KEY` - -### 3. 修复ES模块兼容性 -- 将 `require` 语法改为 `import` 语法 -- 确保所有模块导入在文件顶部 - -## 测试验证 - -### 测试1:基础PowerShell调用 -```bash -node test-simple-powershell.cjs -``` -**结果:** ✅ 成功 -- `powershell.exe` 调用成功 -- 完整路径调用成功 -- 无ENOENT错误 - -### 测试2:MCP工具brainstorm功能 -```bash -node test-brainstorm-dev.cjs -``` -**结果:** ✅ PowerShell调用成功 -- PowerShell进程启动正常 -- 环境变量正确传递 -- 仅因API密钥问题失败(预期行为) -- **关键:无ENOENT错误** - -## 配置文件 - -### 开发版本配置 (`gemini-cli-test.json`) -```json -{ - "mcpServers": { - "gemini-cli-test": { - "command": "node", - "args": ["D:\\gemini\\lib\\fixed-mcp-tool.js"], - "env": { - "GEMINI_API_KEY": "your_api_key_here" - } - } - } -} -``` - -## 修复效果 - -✅ **ENOENT错误已解决** -- PowerShell可执行文件能够被正确找到和执行 -- 环境变量正确传递到子进程 -- 支持多种PowerShell路径配置 - -✅ **兼容性提升** -- 支持不同Windows版本的PowerShell路径 -- 改进的错误处理和调试信息 -- ES模块兼容性修复 - -✅ **开发测试支持** -- 提供本地开发版本配置 -- 详细的测试脚本和验证方法 -- 完整的安装和配置文档 - -## 建议 - -1. **用户配置**:建议用户使用提供的 `gemini-cli-test.json` 配置文件进行本地测试 -2. **路径配置**:确保将配置文件中的路径替换为实际的项目路径 -3. **API密钥**:确保在环境变量或配置文件中正确设置 `GEMINI_API_KEY` - -## 技术细节 - -### 关键修改文件 -- `lib/fixed-geminiExecutor.js`:PowerShell执行器修复 -- `gemini-cli-test.json`:开发版本配置 -- `INSTALL-GUIDE.md`:更新安装指南 - -### 调试信息 -修复后的版本包含详细的调试日志: -- PowerShell路径检测过程 -- 环境变量可用性检查 -- 命令执行状态跟踪 - -这些修复确保了 `spawn powershell.exe ENOENT` 错误不再出现,提供了稳定可靠的PowerShell调用机制。 \ No newline at end of file diff --git a/POWERSHELL-PATH-UPDATE.md b/POWERSHELL-PATH-UPDATE.md deleted file mode 100644 index 3e78f7f..0000000 --- a/POWERSHELL-PATH-UPDATE.md +++ /dev/null @@ -1,137 +0,0 @@ -# PowerShell 路径参数更新说明 - -## 版本信息 -- **版本**: 1.0.3 -- **发布日期**: 2024年12月 -- **更新类型**: 功能增强 - -## 更新内容 - -### 新增功能:PowerShell 路径自定义参数 - -为了解决不同用户系统中 PowerShell 路径不同的问题,我们在 `ask-gemini` 和 `brainstorm` 工具中添加了可选的 `powershellPath` 参数。 - -### 功能特性 - -1. **可选参数**: `powershellPath` 是可选参数,不指定时使用系统自动检测 -2. **灵活配置**: 支持指定任意有效的 PowerShell 可执行文件路径 -3. **向后兼容**: 现有配置无需修改,自动使用默认检测逻辑 -4. **多版本支持**: 支持 Windows PowerShell 5.1 和 PowerShell 7+ - -### 使用方法 - -#### ask-gemini 工具 -```json -{ - "prompt": "你的问题", - "model": "gemini-pro", - "powershellPath": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" -} -``` - -#### brainstorm 工具 -```json -{ - "topic": "创新想法", - "count": 5, - "powershellPath": "C:\\Program Files\\PowerShell\\7\\pwsh.exe" -} -``` - -### 常见 PowerShell 路径 - -| PowerShell 版本 | 默认路径 | -|----------------|----------| -| Windows PowerShell 5.1 | `C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe` | -| PowerShell 7+ | `C:\\Program Files\\PowerShell\\7\\pwsh.exe` | -| PowerShell Core 6 | `C:\\Program Files\\PowerShell\\6\\pwsh.exe` | - -### 技术实现 - -#### 修改的文件 -1. **fixed-mcp-tool.js**: 添加 `powershellPath` 参数定义和传递 -2. **fixed-geminiExecutor.js**: 扩展函数支持自定义 PowerShell 路径 - - `getPowerShellExecutable()`: 支持 `customPath` 参数 - - `executeCommandWithEnv()`: 支持 `customPowershellPath` 参数 - - `executeGeminiCLI()`: 添加 `powershellPath` 参数 - -#### 参数传递流程 -``` -MCP 工具调用 → fixed-mcp-tool.js → executeGeminiCLI() → executeCommandWithEnv() → spawn(powershellPath) -``` - -### 日志增强 - -添加了详细的日志输出,帮助调试 PowerShell 路径问题: -``` -[GMCPT] Using PowerShell executable: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -``` - -### 测试验证 - -创建了测试脚本 `test-powershell-path.cjs` 来验证功能: -- 测试默认 PowerShell 路径 -- 测试自定义 PowerShell 路径 -- 验证参数传递正确性 - -### 安装和更新 - -#### 从 npm 安装最新版本 -```bash -npm install -g gemini-mcp-tool-windows-fixed@1.0.3 -``` - -#### 更新现有安装 -```bash -npm update -g gemini-mcp-tool-windows-fixed -``` - -### 配置示例 - -#### Claude Desktop 配置 -```json -{ - "mcpServers": { - "gemini-cli": { - "command": "npx", - "args": ["-y", "gemini-mcp-tool-windows-fixed@1.0.3"], - "env": { - "GEMINI_API_KEY": "your_api_key_here" - } - } - } -} -``` - -#### Claude Code 配置 -```bash -claude mcp add gemini-cli npx -y gemini-mcp-tool-windows-fixed@1.0.3 -``` - -### 故障排除 - -#### 如果遇到 PowerShell 路径问题 -1. 检查系统中安装的 PowerShell 版本 -2. 使用 `powershellPath` 参数指定正确路径 -3. 查看日志输出确认使用的 PowerShell 路径 - -#### 常见错误和解决方案 -- **ENOENT 错误**: 指定正确的 PowerShell 可执行文件路径 -- **权限错误**: 确保 PowerShell 可执行文件有执行权限 -- **路径错误**: 使用双反斜杠转义路径中的反斜杠 - -### 向后兼容性 - -- ✅ 现有配置无需修改 -- ✅ 不指定 `powershellPath` 时使用原有逻辑 -- ✅ 所有现有功能保持不变 - -### 未来计划 - -- 考虑添加 PowerShell 版本自动检测 -- 支持更多 PowerShell 配置选项 -- 优化错误提示和调试信息 - ---- - -**注意**: 此更新完全向后兼容,现有用户无需修改配置即可继续使用。新的 `powershellPath` 参数仅在需要自定义 PowerShell 路径时使用。 \ No newline at end of file diff --git a/README.md b/README.md index d46b675..62cd49c 100644 --- a/README.md +++ b/README.md @@ -147,28 +147,6 @@ If you already have it configured in Claude Desktop: "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" } } - }, - "_comments": { - "powershell_path_support": "v1.0.3 新增 PowerShell 路径参数支持", - "usage_examples": { - "brainstorm_with_custom_powershell": { - "topic": "你的主题", - "count": 5, - "powershellPath": "C:\\Program Files\\PowerShell\\7\\pwsh.exe" - }, - "ask_gemini_with_custom_powershell": { - "prompt": "你的问题", - "model": "gemini-pro", - "powershellPath": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - } - }, - "common_powershell_paths": [ - "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe (Windows PowerShell 5.x)", - "C:\\Program Files\\PowerShell\\7\\pwsh.exe (PowerShell 7.x)", - "powershell.exe (系统PATH中的默认PowerShell)", - "pwsh.exe (系统PATH中的PowerShell 7.x)" - ], - "backward_compatibility": "powershellPath 参数是可选的,不提供时使用系统默认PowerShell" } } ``` diff --git a/claude-config-v1.0.3.json b/claude-config-v1.0.3.json deleted file mode 100644 index 7152b75..0000000 --- a/claude-config-v1.0.3.json +++ /dev/null @@ -1,33 +0,0 @@ -{ - "mcpServers": { - "gemini-cli": { - "command": "npx", - "args": ["-y", "gemini-mcp-tool-windows-fixed@1.0.3"], - "env": { - "GEMINI_API_KEY": "your_api_key_here" - } - } - }, - "_comments": { - "powershell_path_support": "v1.0.3 新增 PowerShell 路径参数支持", - "usage_examples": { - "brainstorm_with_custom_powershell": { - "topic": "你的主题", - "count": 5, - "powershellPath": "C:\\Program Files\\PowerShell\\7\\pwsh.exe" - }, - "ask_gemini_with_custom_powershell": { - "prompt": "你的问题", - "model": "gemini-pro", - "powershellPath": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe" - } - }, - "common_powershell_paths": [ - "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe (Windows PowerShell 5.x)", - "C:\\Program Files\\PowerShell\\7\\pwsh.exe (PowerShell 7.x)", - "powershell.exe (系统PATH中的默认PowerShell)", - "pwsh.exe (系统PATH中的PowerShell 7.x)" - ], - "backward_compatibility": "powershellPath 参数是可选的,不提供时使用系统默认PowerShell" - } -} \ No newline at end of file diff --git a/fix-proxy-push.ps1 b/fix-proxy-push.ps1 deleted file mode 100644 index dc84c8c..0000000 --- a/fix-proxy-push.ps1 +++ /dev/null @@ -1,189 +0,0 @@ -# GitHub Proxy Push Fix Script -# Solve Git push issues in proxy environments - -Write-Host "GitHub Proxy Push Fix Tool" -ForegroundColor Cyan -Write-Host "==============================" -ForegroundColor Cyan -Write-Host "" - -# Get GitHub username -$githubUser = Read-Host "Enter your GitHub username" -if (-not $githubUser) { - Write-Host "ERROR: GitHub username is required" -ForegroundColor Red - exit 1 -} - -Write-Host "Detecting current environment..." -ForegroundColor Yellow - -# Detect system proxy -$systemProxy = netsh winhttp show proxy 2>$null -if ($systemProxy -match "Direct access") { - Write-Host "System proxy: Direct access (no proxy)" -ForegroundColor Green -} else { - Write-Host "System proxy: $systemProxy" -ForegroundColor Yellow -} - -# Detect environment variable proxy -$envHttpProxy = $env:HTTP_PROXY -$envHttpsProxy = $env:HTTPS_PROXY -if ($envHttpProxy) { Write-Host "HTTP_PROXY: $envHttpProxy" -ForegroundColor Yellow } -if ($envHttpsProxy) { Write-Host "HTTPS_PROXY: $envHttpsProxy" -ForegroundColor Yellow } -if (-not $envHttpProxy -and -not $envHttpsProxy) { - Write-Host "Environment variables: No proxy configured" -ForegroundColor Green -} - -# Check current Git proxy configuration -$currentGitHttpProxy = git config --global --get http.proxy 2>$null -$currentGitHttpsProxy = git config --global --get https.proxy 2>$null -if ($currentGitHttpProxy) { Write-Host "Git HTTP proxy: $currentGitHttpProxy" -ForegroundColor Yellow } -if ($currentGitHttpsProxy) { Write-Host "Git HTTPS proxy: $currentGitHttpsProxy" -ForegroundColor Yellow } -if (-not $currentGitHttpProxy -and -not $currentGitHttpsProxy) { - Write-Host "Git proxy: Not configured" -ForegroundColor Green -} - -Write-Host "" -Write-Host "Proxy configuration options:" -ForegroundColor Yellow -Write-Host "1. Use system proxy" -ForegroundColor White -Write-Host "2. Manual proxy configuration" -ForegroundColor White -Write-Host "3. Clear proxy configuration" -ForegroundColor White -Write-Host "4. Skip proxy configuration" -ForegroundColor White - -$choice = Read-Host "Please choose (1-4)" - -if ($choice -eq "1") { - Write-Host "Configuring Git to use system proxy..." -ForegroundColor Yellow - - # Extract proxy address from system proxy configuration - if ($systemProxy -match "Proxy Server\(s\)\s*:\s*([^\s]+)") { - $proxyServer = $matches[1] - Write-Host "Detected system proxy: $proxyServer" -ForegroundColor Green - - git config --global http.proxy "http://$proxyServer" - git config --global https.proxy "http://$proxyServer" - - Write-Host "Git proxy configuration completed" -ForegroundColor Green - } else { - Write-Host "Cannot auto-detect system proxy, please configure manually" -ForegroundColor Red - $manualProxy = Read-Host "Enter proxy address (format: host:port)" - if ($manualProxy) { - git config --global http.proxy "http://$manualProxy" - git config --global https.proxy "http://$manualProxy" - Write-Host "Manual proxy configuration completed" -ForegroundColor Green - } - } -} -elseif ($choice -eq "2") { - Write-Host "Manual proxy configuration..." -ForegroundColor Yellow - $proxyHost = Read-Host "Enter proxy host address" - $proxyPort = Read-Host "Enter proxy port" - - if ($proxyHost -and $proxyPort) { - $proxyUrl = "http://$proxyHost`:$proxyPort" - - # Ask if authentication is needed - $needAuth = Read-Host "Does proxy require authentication? (y/n)" - if ($needAuth -eq "y" -or $needAuth -eq "Y") { - $proxyUser = Read-Host "Proxy username" - $proxyPass = Read-Host "Proxy password" -AsSecureString - $proxyPassPlain = [Runtime.InteropServices.Marshal]::PtrToStringAuto([Runtime.InteropServices.Marshal]::SecureStringToBSTR($proxyPass)) - $proxyUrl = "http://$proxyUser`:$proxyPassPlain@$proxyHost`:$proxyPort" - } - - git config --global http.proxy $proxyUrl - git config --global https.proxy $proxyUrl - - Write-Host "Proxy configuration completed" -ForegroundColor Green - } else { - Write-Host "Proxy configuration incomplete" -ForegroundColor Red - } -} -elseif ($choice -eq "3") { - Write-Host "Clearing Git proxy configuration..." -ForegroundColor Yellow - git config --global --unset http.proxy 2>$null - git config --global --unset https.proxy 2>$null - Write-Host "Proxy configuration cleared" -ForegroundColor Green -} -else { - Write-Host "Skipping proxy configuration" -ForegroundColor Yellow -} - -# Git performance optimization -Write-Host "" -Write-Host "Optimizing Git configuration..." -ForegroundColor Yellow -git config --global http.postBuffer 524288000 -git config --global http.lowSpeedLimit 0 -git config --global http.lowSpeedTime 999999 -git config --global http.sslVerify false -git config --global pack.windowMemory 256m -git config --global pack.packSizeLimit 2g -Write-Host "Git performance optimization completed" -ForegroundColor Green - -# Configure credential manager -Write-Host "" -Write-Host "Configuring credential manager..." -ForegroundColor Yellow -git config --global credential.helper manager-core -Write-Host "Credential manager configuration completed" -ForegroundColor Green - -# Set up remote repository -Write-Host "" -Write-Host "Configuring remote repository..." -ForegroundColor Yellow -$repoName = Split-Path -Leaf (Get-Location) -$remoteUrl = "https://github.com/$githubUser/$repoName.git" - -# Check if remote repository already exists -$existingRemote = git remote get-url origin 2>$null -if ($existingRemote) { - Write-Host "Current remote repository: $existingRemote" -ForegroundColor Yellow - $updateRemote = Read-Host "Update to new remote repository? (y/n)" - if ($updateRemote -eq "y" -or $updateRemote -eq "Y") { - git remote set-url origin $remoteUrl - Write-Host "Remote repository updated" -ForegroundColor Green - } -} else { - git remote add origin $remoteUrl - Write-Host "Remote repository added: $remoteUrl" -ForegroundColor Green -} - -# Test network connection -Write-Host "" -Write-Host "Testing network connection..." -ForegroundColor Yellow -try { - $testResult = Test-NetConnection github.com -Port 443 -WarningAction SilentlyContinue - if ($testResult.TcpTestSucceeded) { - Write-Host "GitHub connection successful" -ForegroundColor Green - } else { - Write-Host "GitHub connection failed" -ForegroundColor Red - } -} catch { - Write-Host "Network test failed: $($_.Exception.Message)" -ForegroundColor Yellow -} - -# Repository is now ready for manual upload -Write-Host "✅ Repository configuration completed!" -ForegroundColor Green -Write-Host "" -Write-Host "📋 Manual Upload Instructions:" -ForegroundColor Cyan -Write-Host "1. Create a new repository on GitHub: https://github.com/new" -ForegroundColor White -Write-Host " Repository name: gemini-mcp-tool-windows-fixed" -ForegroundColor White -Write-Host "2. Initialize and push your code:" -ForegroundColor White -Write-Host " git add ." -ForegroundColor Gray -Write-Host " git commit -m 'Initial commit - Windows fixed version'" -ForegroundColor Gray -Write-Host " git branch -M main" -ForegroundColor Gray -Write-Host " git remote add origin https://github.com/$githubUser/gemini-mcp-tool-windows-fixed.git" -ForegroundColor Gray -Write-Host " git push -u origin main" -ForegroundColor Gray -Write-Host "" -Write-Host "📦 Repository ready for manual upload!" -ForegroundColor Green -Write-Host "🔧 All configurations applied successfully!" -ForegroundColor Green - -Write-Host "" -Write-Host "Current Git proxy configuration:" -ForegroundColor Cyan -$currentHttpProxy = git config --global --get http.proxy -$currentHttpsProxy = git config --global --get https.proxy -if ($currentHttpProxy) { Write-Host " http.proxy: $currentHttpProxy" -ForegroundColor White } -if ($currentHttpsProxy) { Write-Host " https.proxy: $currentHttpsProxy" -ForegroundColor White } -if (-not $currentHttpProxy -and -not $currentHttpsProxy) { Write-Host " No proxy configured" -ForegroundColor Gray } - -Write-Host "" -Write-Host "Next steps:" -ForegroundColor Cyan -Write-Host "1. Update Trae AI MCP configuration" -ForegroundColor White -Write-Host "2. Add GEMINI_API_KEY environment variable" -ForegroundColor White -Write-Host "3. Restart Trae AI" -ForegroundColor White -Write-Host "4. Test integration" -ForegroundColor White \ No newline at end of file diff --git a/gemini-cli-test.json b/gemini-cli-test.json deleted file mode 100644 index c16f09d..0000000 --- a/gemini-cli-test.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "mcpServers": { - "gemini-cli-test": { - "command": "node", - "args": ["D:\\gemini\\lib\\fixed-mcp-tool.js"], - "env": { - "GEMINI_API_KEY": "your_api_key_here" - } - } - } -} \ No newline at end of file diff --git a/gemini-mcp-tool-windows-fixed-1.0.1/gemini-mcp-tool-windows-fixed-1.0.1.tar b/gemini-mcp-tool-windows-fixed-1.0.1/gemini-mcp-tool-windows-fixed-1.0.1.tar deleted file mode 100644 index 280d2c9f9a05e116bbcf98d9e267f712e31adf1f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47104 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 P41B=A2Mqk-W8nV-`SI`l diff --git a/test-brainstorm-dev.cjs b/test-brainstorm-dev.cjs deleted file mode 100644 index 4b39d81..0000000 --- a/test-brainstorm-dev.cjs +++ /dev/null @@ -1,74 +0,0 @@ -const { spawn } = require('child_process'); -const path = require('path'); - -// Test the local development version of MCP tool -function testBrainstormDev() { - console.log('Testing brainstorm functionality with local development version...'); - - // Create a test MCP request for brainstorm - const mcpRequest = { - jsonrpc: '2.0', - id: 1, - method: 'tools/call', - params: { - name: 'brainstorm', - arguments: { - prompt: '如何提高团队协作效率', - model: 'gemini-1.5-flash', - methodology: 'structured', - domain: 'business', - ideaCount: 3 - } - } - }; - - const mcpToolPath = path.join(__dirname, 'lib', 'fixed-mcp-tool.js'); - console.log(`Using MCP tool at: ${mcpToolPath}`); - - const childProcess = spawn('node', [mcpToolPath], { - stdio: ['pipe', 'pipe', 'pipe'], - env: { - ...process.env, - GEMINI_API_KEY: process.env.GEMINI_API_KEY || 'test_key' - } - }); - - let stdout = ''; - let stderr = ''; - - childProcess.stdout.on('data', (data) => { - stdout += data.toString(); - console.log('STDOUT:', data.toString()); - }); - - childProcess.stderr.on('data', (data) => { - stderr += data.toString(); - console.log('STDERR:', data.toString()); - }); - - childProcess.on('error', (error) => { - console.error('Process error:', error.message); - }); - - childProcess.on('close', (code) => { - console.log(`Process exited with code: ${code}`); - console.log('=== FINAL STDOUT ==='); - console.log(stdout); - console.log('=== FINAL STDERR ==='); - console.log(stderr); - }); - - // Send the MCP request - console.log('Sending MCP request:', JSON.stringify(mcpRequest, null, 2)); - childProcess.stdin.write(JSON.stringify(mcpRequest) + '\n'); - - // Wait a bit then close stdin - setTimeout(() => { - childProcess.stdin.end(); - }, 1000); -} - -// Run the test -testBrainstormDev(); - -console.log('Test started. Check output above for results.'); \ No newline at end of file diff --git a/test-brainstorm.js b/test-brainstorm.js deleted file mode 100644 index fad19b3..0000000 --- a/test-brainstorm.js +++ /dev/null @@ -1,91 +0,0 @@ -import { executeGeminiCLI } from './lib/fixed-geminiExecutor.js'; -import dotenv from 'dotenv'; -import path from 'path'; -import { fileURLToPath } from 'url'; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); -dotenv.config({ path: path.join(__dirname, 'lib', '.env') }); - -console.log('=== Testing Brainstorm Tool Execution ==='); -console.log(`GEMINI_API_KEY loaded: ${process.env.GEMINI_API_KEY ? 'YES' : 'NO'}`); -console.log(`Current working directory: ${process.cwd()}`); -console.log(`Script directory: ${__dirname}`); - -// Simulate the exact brainstorm call that's failing -async function testBrainstormExecution() { - try { - console.log('\n--- Testing Brainstorm Execution ---'); - - // This is the exact prompt structure used by brainstorm tool - const brainstormPrompt = `BRAINSTORMING SESSION - -Challenge: 设计一个可持续能源解决方案 - -Generate 12 creative and diverse ideas. For each idea, provide a brief feasibility assessment and potential impact.`; - - console.log('Calling executeGeminiCLI with brainstorm prompt...'); - console.log('Prompt preview:', brainstormPrompt.substring(0, 100) + '...'); - - const result = await executeGeminiCLI(brainstormPrompt, undefined, false, false); - - console.log('✅ Brainstorm execution successful!'); - console.log('Result length:', result.length); - console.log('Result preview:', result.substring(0, 200) + '...'); - - } catch (error) { - console.log('❌ Brainstorm execution failed!'); - console.log('Error message:', error.message); - console.log('Error stack:', error.stack); - console.log('Error code:', error.code); - console.log('Error errno:', error.errno); - console.log('Error syscall:', error.syscall); - console.log('Error path:', error.path); - } -} - -// Test with different scenarios -async function testMultipleScenarios() { - const scenarios = [ - { - name: 'Simple English prompt', - prompt: 'BRAINSTORMING SESSION\n\nChallenge: Design a sustainable energy solution\n\nGenerate 5 creative ideas.' - }, - { - name: 'Chinese prompt (original failing case)', - prompt: 'BRAINSTORMING SESSION\n\nChallenge: 设计一个可持续能源解决方案\n\nGenerate 12 creative and diverse ideas. For each idea, provide a brief feasibility assessment and potential impact.' - }, - { - name: 'Mixed language prompt', - prompt: 'BRAINSTORMING SESSION\n\nChallenge: Design a 可持续能源 solution\n\nGenerate 3 ideas.' - } - ]; - - for (const scenario of scenarios) { - console.log(`\n=== Testing: ${scenario.name} ===`); - try { - const result = await executeGeminiCLI(scenario.prompt, undefined, false, false); - console.log(`✅ ${scenario.name}: Success (${result.length} chars)`); - } catch (error) { - console.log(`❌ ${scenario.name}: Failed - ${error.message}`); - if (error.message.includes('spawn powershell.exe ENOENT')) { - console.log('🔍 This is the exact error reported by the user!'); - } - } - } -} - -// Run all tests -async function runAllTests() { - console.log('Starting comprehensive brainstorm testing...'); - - await testBrainstormExecution(); - await testMultipleScenarios(); - - console.log('\n=== Testing completed ==='); -} - -runAllTests().catch(error => { - console.error('Test runner failed:', error); - process.exit(1); -}); \ No newline at end of file diff --git a/test-mcp-powershell.js b/test-mcp-powershell.js deleted file mode 100644 index 2dfa290..0000000 --- a/test-mcp-powershell.js +++ /dev/null @@ -1,134 +0,0 @@ -import { spawn } from 'child_process'; -import dotenv from 'dotenv'; -import path from 'path'; -import { fileURLToPath } from 'url'; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); -dotenv.config({ path: path.join(__dirname, 'lib', '.env') }); - -// Function to get PowerShell executable based on platform -function getPowerShellExecutable() { - if (process.platform === 'win32') { - return 'powershell.exe'; - } - return 'pwsh'; -} - -const POWERSHELL_EXECUTABLE = getPowerShellExecutable(); - -// Simulate the exact environment and command used by the MCP tool -async function testMCPPowerShellCall() { - console.log('=== Testing MCP PowerShell Call ==='); - console.log(`PowerShell executable: ${POWERSHELL_EXECUTABLE}`); - console.log(`GEMINI_API_KEY loaded: ${process.env.GEMINI_API_KEY ? 'YES' : 'NO'}`); - - // Create environment similar to what MCP tool uses - const env = { - ...process.env, - GEMINI_API_KEY: process.env.GEMINI_API_KEY - }; - - // Test the exact command pattern used by brainstorm tool - const testCommand = 'echo "Testing brainstorm command simulation"'; - - return new Promise((resolve, reject) => { - console.log(`Executing command: ${POWERSHELL_EXECUTABLE} -Command "${testCommand}"`); - - const childProcess = spawn(POWERSHELL_EXECUTABLE, ['-Command', testCommand], { - env: env, - stdio: ['pipe', 'pipe', 'pipe'] - }); - - let stdout = ''; - let stderr = ''; - - childProcess.stdout.on('data', (data) => { - stdout += data.toString(); - console.log('stdout chunk:', data.toString().trim()); - }); - - childProcess.stderr.on('data', (data) => { - stderr += data.toString(); - console.log('stderr chunk:', data.toString().trim()); - }); - - childProcess.on('error', (error) => { - console.log('Process error:', error.message); - console.log('Error code:', error.code); - console.log('Error errno:', error.errno); - console.log('Error syscall:', error.syscall); - console.log('Error path:', error.path); - reject(error); - }); - - childProcess.on('close', (code) => { - console.log(`Process exited with code: ${code}`); - console.log(`Final stdout: ${stdout}`); - console.log(`Final stderr: ${stderr}`); - - if (code === 0) { - resolve({ stdout, stderr }); - } else { - reject(new Error(`Command failed with exit code ${code}: ${stderr}`)); - } - }); - - // Test with piped input (like the actual MCP tool does) - const testInput = 'Test input for PowerShell'; - childProcess.stdin.write(testInput); - childProcess.stdin.end(); - }); -} - -// Test different PowerShell executable options -async function testDifferentExecutables() { - const executables = [ - 'powershell.exe', - 'powershell', - 'C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\powershell.exe', - 'pwsh' - ]; - - for (const exe of executables) { - console.log(`\n=== Testing executable: ${exe} ===`); - - try { - const result = await new Promise((resolve, reject) => { - const proc = spawn(exe, ['-Command', 'echo "Success with ' + exe + '"'], { - stdio: ['pipe', 'pipe', 'pipe'] - }); - - let output = ''; - proc.stdout.on('data', (data) => output += data.toString()); - proc.on('error', reject); - proc.on('close', (code) => { - if (code === 0) { - resolve(output.trim()); - } else { - reject(new Error(`Exit code ${code}`)); - } - }); - }); - - console.log(`✅ ${exe}: ${result}`); - } catch (error) { - console.log(`❌ ${exe}: ${error.message}`); - } - } -} - -// Run tests -async function runAllTests() { - try { - await testDifferentExecutables(); - console.log('\n' + '='.repeat(50)); - await testMCPPowerShellCall(); - console.log('\n✅ All tests completed successfully'); - } catch (error) { - console.log('\n❌ Test failed:', error.message); - console.log('Error details:', error); - } -} - -runAllTests(); \ No newline at end of file diff --git a/test-powershell-fix.cjs b/test-powershell-fix.cjs deleted file mode 100644 index 13b84fa..0000000 --- a/test-powershell-fix.cjs +++ /dev/null @@ -1,72 +0,0 @@ -const { spawn } = require('child_process'); -const path = require('path'); - -// Test PowerShell execution directly -function testPowerShellFix() { - console.log('Testing PowerShell execution fix...'); - - // Import the fixed executor - const executorPath = path.join(__dirname, 'lib', 'fixed-geminiExecutor.js'); - - // Test simple PowerShell command - const testCommand = 'Write-Host "PowerShell test successful"'; - - console.log('Testing PowerShell command execution...'); - - const childProcess = spawn('node', ['-e', ` - import('${executorPath.replace(/\\/g, '/')}') - .then(module => { - return module.executeCommandWithPipedInput('${testCommand}', { TEST: 'value' }); - }) - .then(result => { - console.log('SUCCESS: PowerShell command executed'); - console.log('STDOUT:', result.stdout); - console.log('STDERR:', result.stderr); - }) - .catch(error => { - console.error('ERROR:', error.message); - if (error.message.includes('ENOENT')) { - console.error('ENOENT error still present!'); - } else { - console.log('No ENOENT error - PowerShell found successfully'); - } - }); - `], { - stdio: ['pipe', 'pipe', 'pipe'], - env: process.env - }); - - let stdout = ''; - let stderr = ''; - - childProcess.stdout.on('data', (data) => { - stdout += data.toString(); - console.log('STDOUT:', data.toString().trim()); - }); - - childProcess.stderr.on('data', (data) => { - stderr += data.toString(); - console.log('STDERR:', data.toString().trim()); - }); - - childProcess.on('error', (error) => { - console.error('Process error:', error.message); - }); - - childProcess.on('close', (code) => { - console.log(`\nTest completed with exit code: ${code}`); - - if (stderr.includes('ENOENT')) { - console.log('❌ ENOENT error still present'); - } else if (stdout.includes('PowerShell test successful') || stdout.includes('SUCCESS')) { - console.log('✅ PowerShell execution successful - ENOENT error fixed!'); - } else { - console.log('⚠️ Test completed but results unclear'); - } - }); -} - -// Run the test -testPowerShellFix(); - -console.log('PowerShell fix test started...'); \ No newline at end of file diff --git a/test-powershell-path.cjs b/test-powershell-path.cjs deleted file mode 100644 index 6ca0473..0000000 --- a/test-powershell-path.cjs +++ /dev/null @@ -1,105 +0,0 @@ -const { spawn } = require('child_process'); -const path = require('path'); - -// Test the new powershellPath parameter functionality -const testPowershellPath = async () => { - console.log('Testing PowerShell path parameter functionality...'); - - // Test 1: Using default PowerShell path - console.log('\n=== Test 1: Default PowerShell path ==='); - const test1 = spawn('node', ['index.js'], { - cwd: process.cwd(), - stdio: ['pipe', 'pipe', 'pipe'] - }); - - // Send MCP request for brainstorm without powershellPath - const mcpRequest1 = { - jsonrpc: '2.0', - id: 1, - method: 'tools/call', - params: { - name: 'brainstorm', - arguments: { - topic: 'test topic', - count: 1 - } - } - }; - - test1.stdin.write(JSON.stringify(mcpRequest1) + '\n'); - test1.stdin.end(); - - let output1 = ''; - let error1 = ''; - - test1.stdout.on('data', (data) => { - output1 += data.toString(); - }); - - test1.stderr.on('data', (data) => { - error1 += data.toString(); - }); - - await new Promise((resolve) => { - test1.on('close', (code) => { - console.log(`Test 1 exit code: ${code}`); - console.log('Test 1 output:', output1.substring(0, 200) + '...'); - if (error1) { - console.log('Test 1 error:', error1.substring(0, 200) + '...'); - } - resolve(); - }); - }); - - // Test 2: Using custom PowerShell path - console.log('\n=== Test 2: Custom PowerShell path ==='); - const test2 = spawn('node', ['index.js'], { - cwd: process.cwd(), - stdio: ['pipe', 'pipe', 'pipe'] - }); - - // Send MCP request for brainstorm with custom powershellPath - const mcpRequest2 = { - jsonrpc: '2.0', - id: 2, - method: 'tools/call', - params: { - name: 'brainstorm', - arguments: { - topic: 'test topic with custom path', - count: 1, - powershellPath: 'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe' - } - } - }; - - test2.stdin.write(JSON.stringify(mcpRequest2) + '\n'); - test2.stdin.end(); - - let output2 = ''; - let error2 = ''; - - test2.stdout.on('data', (data) => { - output2 += data.toString(); - }); - - test2.stderr.on('data', (data) => { - error2 += data.toString(); - }); - - await new Promise((resolve) => { - test2.on('close', (code) => { - console.log(`Test 2 exit code: ${code}`); - console.log('Test 2 output:', output2.substring(0, 200) + '...'); - if (error2) { - console.log('Test 2 error:', error2.substring(0, 200) + '...'); - } - resolve(); - }); - }); - - console.log('\n=== PowerShell Path Parameter Test Complete ==='); - console.log('Both tests should show PowerShell executable paths in the logs.'); -}; - -testPowershellPath().catch(console.error); \ No newline at end of file diff --git a/test-powershell.js b/test-powershell.js deleted file mode 100644 index 007144a..0000000 --- a/test-powershell.js +++ /dev/null @@ -1,84 +0,0 @@ -import { spawn } from 'child_process'; - -// Function to get PowerShell executable based on platform -function getPowerShellExecutable() { - // On Windows, try powershell.exe first (Windows PowerShell), then pwsh (PowerShell Core) - if (process.platform === 'win32') { - return 'powershell.exe'; - } - // On other platforms, use pwsh (PowerShell Core) - return 'pwsh'; -} - -const POWERSHELL_EXECUTABLE = getPowerShellExecutable(); -console.log(`Testing PowerShell executable: ${POWERSHELL_EXECUTABLE}`); -console.log(`Platform: ${process.platform}`); -console.log(`PATH contains:`, process.env.PATH.split(';').filter(p => p.includes('PowerShell') || p.includes('System32'))); - -// Test 1: Basic spawn test -console.log('\n=== Test 1: Basic spawn test ==='); -const test1 = spawn(POWERSHELL_EXECUTABLE, ['-Command', 'echo "Hello from PowerShell"'], { - stdio: ['pipe', 'pipe', 'pipe'] -}); - -test1.stdout.on('data', (data) => { - console.log('Test 1 stdout:', data.toString().trim()); -}); - -test1.stderr.on('data', (data) => { - console.log('Test 1 stderr:', data.toString().trim()); -}); - -test1.on('error', (error) => { - console.log('Test 1 error:', error.message); -}); - -test1.on('close', (code) => { - console.log('Test 1 exit code:', code); - - // Test 2: Full path test - console.log('\n=== Test 2: Full path test ==='); - const fullPath = 'C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\powershell.exe'; - const test2 = spawn(fullPath, ['-Command', 'echo "Hello from full path PowerShell"'], { - stdio: ['pipe', 'pipe', 'pipe'] - }); - - test2.stdout.on('data', (data) => { - console.log('Test 2 stdout:', data.toString().trim()); - }); - - test2.stderr.on('data', (data) => { - console.log('Test 2 stderr:', data.toString().trim()); - }); - - test2.on('error', (error) => { - console.log('Test 2 error:', error.message); - }); - - test2.on('close', (code) => { - console.log('Test 2 exit code:', code); - - // Test 3: Environment test - console.log('\n=== Test 3: Environment test ==='); - const test3 = spawn(POWERSHELL_EXECUTABLE, ['-Command', '$env:PATH -split ";" | Where-Object { $_ -like "*PowerShell*" -or $_ -like "*System32*" }'], { - stdio: ['pipe', 'pipe', 'pipe'] - }); - - test3.stdout.on('data', (data) => { - console.log('Test 3 stdout:', data.toString().trim()); - }); - - test3.stderr.on('data', (data) => { - console.log('Test 3 stderr:', data.toString().trim()); - }); - - test3.on('error', (error) => { - console.log('Test 3 error:', error.message); - }); - - test3.on('close', (code) => { - console.log('Test 3 exit code:', code); - console.log('\n=== All tests completed ==='); - }); - }); -}); \ No newline at end of file diff --git a/test-simple-powershell.cjs b/test-simple-powershell.cjs deleted file mode 100644 index 1e46248..0000000 --- a/test-simple-powershell.cjs +++ /dev/null @@ -1,65 +0,0 @@ -const { spawn } = require('child_process'); - -// Simple test to verify PowerShell can be found and executed -function testSimplePowerShell() { - console.log('Testing simple PowerShell execution...'); - - // Test 1: Try powershell.exe directly - console.log('\n=== Test 1: powershell.exe ==='); - const ps1 = spawn('powershell.exe', ['-Command', 'Write-Host "Test 1 Success"'], { - stdio: ['pipe', 'pipe', 'pipe'] - }); - - ps1.stdout.on('data', (data) => { - console.log('✅ STDOUT:', data.toString().trim()); - }); - - ps1.stderr.on('data', (data) => { - console.log('❌ STDERR:', data.toString().trim()); - }); - - ps1.on('error', (error) => { - if (error.code === 'ENOENT') { - console.log('❌ ENOENT error: powershell.exe not found'); - } else { - console.log('❌ Other error:', error.message); - } - }); - - ps1.on('close', (code) => { - console.log(`Test 1 completed with code: ${code}`); - - // Test 2: Try full path - console.log('\n=== Test 2: Full path ==='); - const ps2 = spawn('C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\powershell.exe', - ['-Command', 'Write-Host "Test 2 Success"'], { - stdio: ['pipe', 'pipe', 'pipe'] - }); - - ps2.stdout.on('data', (data) => { - console.log('✅ STDOUT:', data.toString().trim()); - }); - - ps2.stderr.on('data', (data) => { - console.log('❌ STDERR:', data.toString().trim()); - }); - - ps2.on('error', (error) => { - if (error.code === 'ENOENT') { - console.log('❌ ENOENT error: Full path PowerShell not found'); - } else { - console.log('❌ Other error:', error.message); - } - }); - - ps2.on('close', (code) => { - console.log(`Test 2 completed with code: ${code}`); - console.log('\n=== Summary ==='); - console.log('If you see "Test 1 Success" or "Test 2 Success" above, PowerShell is working!'); - console.log('If you see ENOENT errors, PowerShell path issues still exist.'); - }); - }); -} - -// Run the test -testSimplePowerShell(); \ No newline at end of file From f4214cf13697b87e1f9bcc123a17e202cfe149ab Mon Sep 17 00:00:00 2001 From: User Date: Mon, 4 Aug 2025 09:30:12 +0800 Subject: [PATCH 15/28] fix: Fix brainstorm tool undefined error and set default model to 2.5 series - Fixed brainstorm tool error when prompt parameter is undefined - Changed default model from 1.5 series to gemini-2.5-pro - Ensured backward compatibility with explicit model parameter - Improved error handling in brainstorm tool logging --- lib/fixed-geminiExecutor.js | 9 +++++++-- lib/fixed-mcp-tool.js | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/lib/fixed-geminiExecutor.js b/lib/fixed-geminiExecutor.js index 4fa76a3..0cddc2c 100644 --- a/lib/fixed-geminiExecutor.js +++ b/lib/fixed-geminiExecutor.js @@ -262,8 +262,13 @@ function getMessage() { const args = []; - if (model && model !== MODELS.PRO) { - args.push(CLI.FLAGS.MODEL, model); + // Use gemini-2.5-pro as default model if no model is specified + const selectedModel = model || MODELS.PRO; + if (selectedModel !== MODELS.PRO) { + args.push(CLI.FLAGS.MODEL, selectedModel); + } else { + // Explicitly set the default model to ensure 2.5 series is used + args.push(CLI.FLAGS.MODEL, MODELS.PRO); } if (sandbox) { diff --git a/lib/fixed-mcp-tool.js b/lib/fixed-mcp-tool.js index 9ddee91..4dd4c91 100644 --- a/lib/fixed-mcp-tool.js +++ b/lib/fixed-mcp-tool.js @@ -284,7 +284,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { powershellPath: brainstormPowershellPath } = args; - console.error('[GMCPT] brainstorm tool called with prompt: ' + brainstormPrompt.substring(0, 50) + '...'); + console.error('[GMCPT] brainstorm tool called with prompt: ' + (brainstormPrompt ? brainstormPrompt.substring(0, 50) + '...' : 'undefined')); console.error('[GMCPT] Methodology: ' + methodology + ', Domain: ' + domain); // Build enhanced brainstorming prompt From b3a6910180ea05ac097c3ea65426e866f4b59c75 Mon Sep 17 00:00:00 2001 From: User Date: Mon, 4 Aug 2025 09:35:53 +0800 Subject: [PATCH 16/28] chore: Bump version to 1.0.4 - Updated package version to reflect brainstorm tool fixes - Includes default model change to 2.5 series - Ready for npm publication --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f4eda0b..26a8d5f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "gemini-mcp-tool-windows-fixed", - "version": "1.0.3", + "version": "1.0.4", "type": "module", "description": "Windows-compatible MCP server that enables AI assistants to interact with Google Gemini CLI - Fixed version for Windows environments", "main": "index.js", From 0b636f40ec5490ea8a1174ecf57e13886710b4cf Mon Sep 17 00:00:00 2001 From: User Date: Mon, 4 Aug 2025 09:37:30 +0800 Subject: [PATCH 17/28] docs: update version references to v1.0.4 in README and INSTALL-GUIDE - Updated all version references from 1.0.3 to 1.0.4 - Added v1.0.4 changelog with brainstorm tool fixes and model upgrades - Updated installation commands and configuration examples - Maintained backward compatibility information --- INSTALL-GUIDE.md | 23 +++++++++++++++-------- README.md | 21 ++++++++++++++------- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/INSTALL-GUIDE.md b/INSTALL-GUIDE.md index 52bca62..af02e2f 100644 --- a/INSTALL-GUIDE.md +++ b/INSTALL-GUIDE.md @@ -1,10 +1,17 @@ # 🚀 Gemini MCP Tool - Windows Fixed Version Installation Guide -> **最新版本 v1.0.3** - 添加了 PowerShell 路径参数支持,允许用户自定义 PowerShell 可执行文件路径 +> **最新版本 v1.0.4** - 修复了 brainstorm 工具错误,设置默认模型为 2.5 系列 ## 🆕 版本更新日志 -### v1.0.3 (最新) +### v1.0.4 (最新) + +- 🔧 **修复 brainstorm 工具错误** - 解决了 `Cannot read properties of undefined` 错误 +- 🚀 **默认模型升级** - 现在默认使用 `gemini-2.5-pro` 模型,性能更佳 +- 🛡️ **增强错误处理** - 改进了参数验证和错误信息 +- ✅ **向后兼容** - 保持与现有配置的完全兼容性 + +### v1.0.3 - ✅ **修复 PowerShell 执行错误** - 解决 `spawn powershell.exe ENOENT` 问题 - ✅ **改进 Windows 兼容性** - 自动检测可用的 PowerShell 版本 - ✅ **修复未定义变量错误** - 修复 `executeCommandWithPipedInput` 函数中的 `args` 变量问题 @@ -43,7 +50,7 @@ ```powershell # 使用最新版本 (推荐) -npx gemini-mcp-tool-windows-fixed@1.0.3 +npx gemini-mcp-tool-windows-fixed@1.0.4 # 或者使用最新版本标签 npx -y gemini-mcp-tool-windows-fixed@latest @@ -53,7 +60,7 @@ npx -y gemini-mcp-tool-windows-fixed@latest ```powershell # 安装最新版本 -npm install -g gemini-mcp-tool-windows-fixed@1.0.3 +npm install -g gemini-mcp-tool-windows-fixed@1.0.4 # 测试工具 gemini-mcp-tool-windows-fixed @@ -80,7 +87,7 @@ npm install -g gemini-mcp-tool-windows-fixed@1.0.3 ```bash # One-command setup for Claude Code -claude mcp add gemini-cli -- npx -y gemini-mcp-tool-windows-fixed@1.0.3 +claude mcp add gemini-cli -- npx -y gemini-mcp-tool-windows-fixed@1.0.4 ``` ### For Development/Testing (Local Version) @@ -160,7 +167,7 @@ If you already have it configured in Claude Desktop: "command": "npx", "args": [ "-y", - "gemini-mcp-tool-windows-fixed@1.0.3" + "gemini-mcp-tool-windows-fixed@1.0.4" ], "env": { "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" @@ -182,7 +189,7 @@ If you already have it configured in Claude Desktop: "mcpServers": { "gemini-cli": { "command": "npx", - "args": ["-y", "gemini-mcp-tool-windows-fixed@1.0.3"], + "args": ["-y", "gemini-mcp-tool-windows-fixed@1.0.4"], "env": { "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" } @@ -294,7 +301,7 @@ npx gemini-mcp-tool-windows-fixed@1.0.3 ``` **原因:** 旧版本 (v1.0.0, v1.0.1) 存在 PowerShell 执行路径问题 -**解决方案:** 更新到 v1.0.3 或更高版本 +**解决方案:** 更新到 v1.0.4 或更高版本 #### 6. PowerShell 版本兼容性 diff --git a/README.md b/README.md index 62cd49c..ec4cad0 100644 --- a/README.md +++ b/README.md @@ -3,13 +3,20 @@ [![npm version](https://badge.fury.io/js/gemini-mcp-tool-windows-fixed.svg)](https://badge.fury.io/js/gemini-mcp-tool-windows-fixed) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -> **最新版本 v1.0.3** - 添加了 PowerShell 路径参数支持,允许用户自定义 PowerShell 可执行文件路径 +> **最新版本 v1.0.4** - 修复了 brainstorm 工具错误,设置默认模型为 2.5 系列 A **Windows-compatible** Model Context Protocol (MCP) server that enables AI assistants to interact with Google's Gemini CLI. This is a fixed version specifically designed to work seamlessly on Windows environments with PowerShell support. > **Note**: This is an enhanced version of the [original gemini-mcp-tool](https://github.com/jamubc/gemini-mcp-tool) with Windows-specific fixes and improvements. -## 🆕 最新更新 (v1.0.3) +## 🆕 最新更新 (v1.0.4) + +- 🔧 **修复 brainstorm 工具错误** - 解决了 `Cannot read properties of undefined` 错误 +- 🚀 **默认模型升级** - 现在默认使用 `gemini-2.5-pro` 模型,性能更佳 +- 🛡️ **增强错误处理** - 改进了参数验证和错误信息 +- ✅ **向后兼容** - 保持与现有配置的完全兼容性 + +### v1.0.3 更新 - 🆕 **PowerShell 路径参数支持** - 添加可选的 `powershellPath` 参数,允许用户自定义 PowerShell 可执行文件路径 - ✅ **修复 PowerShell 执行错误** - 解决 `spawn powershell.exe ENOENT` 问题 @@ -57,7 +64,7 @@ This Windows-fixed version resolves: ```powershell # 使用最新版本 (推荐) -npx gemini-mcp-tool-windows-fixed@1.0.3 +npx gemini-mcp-tool-windows-fixed@1.0.4 # 或者使用最新版本标签 npx -y gemini-mcp-tool-windows-fixed@latest @@ -67,7 +74,7 @@ npx -y gemini-mcp-tool-windows-fixed@latest ```powershell # 安装最新版本 -npm install -g gemini-mcp-tool-windows-fixed@1.0.3 +npm install -g gemini-mcp-tool-windows-fixed@1.0.4 # 运行工具 gemini-mcp-tool-windows-fixed @@ -90,7 +97,7 @@ npm install -g gemini-mcp-tool-windows-fixed@1.0.3 ```bash # One-command setup for Claude Code -claude mcp add gemini-cli -- npx -y gemini-mcp-tool-windows-fixed@1.0.3 +claude mcp add gemini-cli -- npx -y gemini-mcp-tool-windows-fixed@1.0.4 ``` **Verify Installation:** @@ -120,7 +127,7 @@ If you already have it configured in Claude Desktop: "command": "npx", "args": [ "-y", - "gemini-mcp-tool-windows-fixed@1.0.3" + "gemini-mcp-tool-windows-fixed@1.0.4" ], "env": { "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" @@ -142,7 +149,7 @@ If you already have it configured in Claude Desktop: "mcpServers": { "gemini-cli": { "command": "npx", - "args": ["-y", "gemini-mcp-tool-windows-fixed@1.0.3"], + "args": ["-y", "gemini-mcp-tool-windows-fixed@1.0.4"], "env": { "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" } From c68933999ab7ccc07f63f59ef20a5852946a722f Mon Sep 17 00:00:00 2001 From: User Date: Mon, 4 Aug 2025 22:12:16 +0800 Subject: [PATCH 18/28] =?UTF-8?q?v1.0.21:=20=E4=BF=AE=E5=A4=8D=E8=B7=A8?= =?UTF-8?q?=E7=BB=88=E7=AB=AF=E5=85=BC=E5=AE=B9=E6=80=A7=E5=92=8Cfetch-chu?= =?UTF-8?q?nk=E6=A0=BC=E5=BC=8F=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 增强PATH环境变量处理,添加常见Node.js安装路径 - 修复fetch-chunk工具的MCP协议格式错误 - 更新文档和配置示例到最新版本 - 删除旧版本打包文件 - 完全兼容所有终端环境(PowerShell, CMD, VS Code, Trae AI等) --- LOCAL-DEBUG-GUIDE.md | 141 ++++++++++++++++++++++++++++++ README.md | 19 ++-- index.js | 18 ++-- lib/fixed-constants.js | 16 ++-- lib/fixed-geminiExecutor.js | 170 +++++++++++++++++++++--------------- lib/fixed-mcp-tool.js | 76 +++++++++++++--- package.json | 4 +- 7 files changed, 335 insertions(+), 109 deletions(-) create mode 100644 LOCAL-DEBUG-GUIDE.md diff --git a/LOCAL-DEBUG-GUIDE.md b/LOCAL-DEBUG-GUIDE.md new file mode 100644 index 0000000..2416469 --- /dev/null +++ b/LOCAL-DEBUG-GUIDE.md @@ -0,0 +1,141 @@ +# 本地调试配置指南 + +## 方案一:使用最新NPM包(推荐) + +### 1. 更新到最新版本 +```bash +npm uninstall -g gemini-mcp-tool-windows-fixed +npm install -g gemini-mcp-tool-windows-fixed@1.0.6 +``` + +### 2. 重新配置MCP +在你的MCP配置文件中更新版本: +```json +{ + "mcpServers": { + "gemini-cli": { + "command": "npx", + "args": ["gemini-mcp-tool-windows-fixed@1.0.6"] + } + } +} +``` + +## 方案二:本地开发调试 + +### 1. 克隆或下载项目 +```bash +git clone +cd gemini-mcp-tool-windows-fixed +npm install +``` + +### 2. 配置环境变量 +在 `lib/.env` 文件中设置你的API密钥: +``` +GEMINI_API_KEY=your_actual_api_key_here +``` + +### 3. 本地MCP配置 +在你的MCP配置文件中使用本地路径: +```json +{ + "mcpServers": { + "gemini-cli": { + "command": "node", + "args": ["D:/gemini/index.js"], + "cwd": "D:/gemini" + } + } +} +``` + +### 4. 启动本地调试 +```bash +# 在项目目录下 +node index.js +``` + +## 方案三:NPM Link方式 + +### 1. 在项目目录下创建全局链接 +```bash +cd D:/gemini +npm link +``` + +### 2. 在MCP配置中使用链接 +```json +{ + "mcpServers": { + "gemini-cli": { + "command": "gemini-mcp-tool-windows-fixed" + } + } +} +``` + +**注意:** 如果遇到 `'gemini-mcp-tool-windows-fixed' 不是内部或外部命令` 的错误,请确保: +1. 已正确执行 `npm link` +2. Node.js 的全局 bin 目录在系统 PATH 中 +3. 可以通过 `npm config get prefix` 查看全局安装路径 + +## 调试技巧 + +### 1. 查看日志 +- 服务器启动日志会显示API密钥加载状态 +- 使用 `console.error` 输出的调试信息 + +### 2. 测试基本功能 +```javascript +// 测试ping +{ + "tool": "ping", + "args": {"prompt": "test"} +} + +// 测试基本ask-gemini +{ + "tool": "ask-gemini", + "args": { + "prompt": "Hello", + "changeMode": false + } +} +``` + +### 3. 常见问题排查 + +#### API密钥问题 +- 确保 `.env` 文件在 `lib/` 目录下 +- 检查API密钥格式是否正确 +- 查看启动日志中的 "GEMINI_API_KEY loaded" 状态 + +#### PowerShell路径问题 +- 工具会自动检测PowerShell路径 +- 可以通过 `powershellPath` 参数指定自定义路径 + +#### ChangeMode问题 +- 当前版本已修复MCP协议兼容性问题 +- 添加了类型检查和调试信息 +- 如果仍有问题,查看服务器日志中的详细错误信息 + +## 版本更新说明 + +### v1.0.6 更新内容 +- 修复了changeMode功能的MCP协议兼容性问题 +- 添加了详细的调试日志 +- 改进了类型检查和错误处理 +- 优化了PowerShell参数转义逻辑 + +### 推荐使用方式 +1. **生产环境**:使用NPM包 `gemini-mcp-tool-windows-fixed@1.0.6` +2. **开发调试**:使用本地路径配置 +3. **快速测试**:使用npm link方式 + +## 联系支持 +如果遇到问题,请提供: +1. 使用的配置方式(NPM包/本地/link) +2. 完整的错误日志 +3. MCP配置文件内容 +4. 操作系统和PowerShell版本信息 \ No newline at end of file diff --git a/README.md b/README.md index ec4cad0..225bfc1 100644 --- a/README.md +++ b/README.md @@ -3,18 +3,19 @@ [![npm version](https://badge.fury.io/js/gemini-mcp-tool-windows-fixed.svg)](https://badge.fury.io/js/gemini-mcp-tool-windows-fixed) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -> **最新版本 v1.0.4** - 修复了 brainstorm 工具错误,设置默认模型为 2.5 系列 +> **最新版本 v1.0.21** - 修复了跨终端兼容性问题和fetch-chunk格式错误 A **Windows-compatible** Model Context Protocol (MCP) server that enables AI assistants to interact with Google's Gemini CLI. This is a fixed version specifically designed to work seamlessly on Windows environments with PowerShell support. > **Note**: This is an enhanced version of the [original gemini-mcp-tool](https://github.com/jamubc/gemini-mcp-tool) with Windows-specific fixes and improvements. -## 🆕 最新更新 (v1.0.4) +## 🆕 最新更新 (v1.0.21) -- 🔧 **修复 brainstorm 工具错误** - 解决了 `Cannot read properties of undefined` 错误 -- 🚀 **默认模型升级** - 现在默认使用 `gemini-2.5-pro` 模型,性能更佳 -- 🛡️ **增强错误处理** - 改进了参数验证和错误信息 -- ✅ **向后兼容** - 保持与现有配置的完全兼容性 +- 🔧 **修复跨终端兼容性** - 解决了在不同终端环境中Node.js路径找不到的问题 +- 📦 **修复fetch-chunk格式错误** - 修复了分段响应的MCP协议格式不匹配问题 +- 🛡️ **增强PATH环境变量处理** - 自动添加常见Node.js安装路径 +- ✅ **完全兼容所有终端** - 支持PowerShell、CMD、VS Code终端、Trae AI等 +- 🚀 **改进错误处理** - 更好的错误信息和调试输出 ### v1.0.3 更新 @@ -97,7 +98,7 @@ npm install -g gemini-mcp-tool-windows-fixed@1.0.3 ```bash # One-command setup for Claude Code -claude mcp add gemini-cli -- npx -y gemini-mcp-tool-windows-fixed@1.0.4 +claude mcp add gemini-cli -- npx -y gemini-mcp-tool-windows-fixed@1.0.21 ``` **Verify Installation:** @@ -127,7 +128,7 @@ If you already have it configured in Claude Desktop: "command": "npx", "args": [ "-y", - "gemini-mcp-tool-windows-fixed@1.0.4" + "gemini-mcp-tool-windows-fixed@1.0.21" ], "env": { "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" @@ -149,7 +150,7 @@ If you already have it configured in Claude Desktop: "mcpServers": { "gemini-cli": { "command": "npx", - "args": ["-y", "gemini-mcp-tool-windows-fixed@1.0.4"], + "args": ["-y", "gemini-mcp-tool-windows-fixed@1.0.21"], "env": { "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" } diff --git a/index.js b/index.js index 2caaef0..e3b6b02 100644 --- a/index.js +++ b/index.js @@ -1,11 +1,11 @@ #!/usr/bin/env node - -/** - * Gemini MCP Tool - Windows Fixed Version - * - * This is the main entry point for the Windows-fixed MCP server that enables - * AI assistants to interact with Google Gemini CLI with proper character encoding - * and parameter handling for Windows environments. - */ - + +/** + * Gemini MCP Tool - Windows Fixed Version + * + * This is the main entry point for the Windows-fixed MCP server that enables + * AI assistants to interact with Google Gemini CLI with proper character encoding + * and parameter handling for Windows environments. + */ + import './lib/fixed-mcp-tool.js'; \ No newline at end of file diff --git a/lib/fixed-constants.js b/lib/fixed-constants.js index fb52d84..be907d3 100644 --- a/lib/fixed-constants.js +++ b/lib/fixed-constants.js @@ -49,19 +49,19 @@ export const PROTOCOL = { // Timeout prevention KEEPALIVE_INTERVAL: 25000, // 25 seconds }; -// CLI Constants - FIXED VERSION WITH FULL PATH +// CLI Constants - FIXED VERSION FOR CROSS-USER COMPATIBILITY export const CLI = { - // Command names + // CLI Commands COMMANDS: { - GEMINI: "C:\\Users\\admin\\AppData\\Roaming\\npm\\gemini.ps1", + GEMINI: "gemini", ECHO: "echo", }, - // Command flags + // CLI Flags FLAGS: { - MODEL: "-m", - SANDBOX: "-s", - PROMPT: "-p", - HELP: "-help", + MODEL: "--model", + SANDBOX: "--sandbox", + PROMPT: "", // No flag needed, prompt is passed directly + HELP: "--help", }, // Default values DEFAULTS: { diff --git a/lib/fixed-geminiExecutor.js b/lib/fixed-geminiExecutor.js index 0cddc2c..6d6633c 100644 --- a/lib/fixed-geminiExecutor.js +++ b/lib/fixed-geminiExecutor.js @@ -3,6 +3,7 @@ import path from 'path'; import { fileURLToPath } from 'url'; // import { executeCommand } from './package/dist/utils/commandExecutor.js'; // Removed - using built-in spawn import { spawn } from 'child_process'; +import fs from 'fs'; // import { Logger } from './package/dist/utils/logger.js'; // Removed - using console instead import { ERROR_MESSAGES, STATUS_MESSAGES, MODELS, CLI } from './fixed-constants.js'; // import { parseChangeModeOutput, validateChangeModeEdits } from './package/dist/utils/changeModeParser.js'; // Removed - simplified @@ -84,14 +85,28 @@ async function executeCommandWithPipedInput(command, input, env, onProgress, cus console.log(`[GMCPT] GEMINI_API_KEY in env: ${env.GEMINI_API_KEY ? 'YES' : 'NO'}`); // Ensure we have a complete environment with PATH and system variables + // Add common Node.js installation paths to ensure compatibility across different terminals + const commonNodePaths = [ + 'C:\\Program Files\\nodejs', + 'C:\\Program Files (x86)\\nodejs', + 'C:\\Users\\admin\\AppData\\Roaming\\npm', + 'C:\\nodejs', + process.env.APPDATA ? `${process.env.APPDATA}\\npm` : null + ].filter(Boolean); + + const currentPath = process.env.PATH || ''; + const enhancedPath = [currentPath, ...commonNodePaths].join(';'); + const completeEnv = { ...process.env, // Include all system environment variables ...env, // Override with provided environment variables - PATH: process.env.PATH || '', // Ensure PATH is always available + PATH: enhancedPath, // Enhanced PATH with Node.js paths SYSTEMROOT: process.env.SYSTEMROOT || 'C:\\WINDOWS', // Required for Windows WINDIR: process.env.WINDIR || 'C:\\WINDOWS' // Required for Windows }; + console.log(`[GMCPT] Enhanced PATH with Node.js paths: ${commonNodePaths.join(', ')}`); + console.log(`[GMCPT] Environment PATH: ${completeEnv.PATH ? 'Available' : 'Missing'}`); console.log(`[GMCPT] Environment GEMINI_API_KEY: ${completeEnv.GEMINI_API_KEY ? 'Available' : 'Missing'}`); @@ -133,8 +148,8 @@ async function executeCommandWithPipedInput(command, input, env, onProgress, cus console.log(`[GMCPT] Command exited with code: ${code}`); console.log(`[GMCPT] stdout length: ${stdout.length}`); console.log(`[GMCPT] stderr length: ${stderr.length}`); - console.log(`[GMCPT] stdout content: ${stdout.substring(0, 500)}...`); - console.log(`[GMCPT] stderr content: ${stderr.substring(0, 200)}...`); + console.log(`[GMCPT] stdout content: ${stdout && typeof stdout === 'string' ? stdout.substring(0, 500) + '...' : 'undefined'}`); + console.log(`[GMCPT] stderr content: ${stderr && typeof stderr === 'string' ? stderr.substring(0, 200) + '...' : 'undefined'}`); if (code === 0) { resolve({ stdout, stderr }); } else { @@ -150,14 +165,45 @@ async function executeCommandWithEnv(command, args, env, onProgress, customPower console.log(`[GMCPT] Environment variables count: ${Object.keys(env).length}`); console.log(`[GMCPT] GEMINI_API_KEY in env: ${env.GEMINI_API_KEY ? 'YES' : 'NO'}`); console.log(`Executing with custom env: ${command} ${args.join(' ')}`); + + // Handle Windows-specific gemini command path resolution + let resolvedCommand = command; + if (process.platform === 'win32' && command === 'gemini') { + const geminiCmdPath = 'C:\\Users\\admin\\AppData\\Roaming\\npm\\gemini.cmd'; + try { + if (fs.existsSync(geminiCmdPath)) { + resolvedCommand = geminiCmdPath; + console.log(`[GMCPT] Using full gemini path: ${resolvedCommand}`); + } else { + console.log(`[GMCPT] Gemini cmd not found at ${geminiCmdPath}, using default command`); + } + } catch (error) { + console.log(`[GMCPT] Error checking gemini path: ${error.message}, using default command`); + } + } + // Ensure we have a complete environment with PATH and system variables + // Add common Node.js installation paths to ensure compatibility across different terminals + const commonNodePaths = [ + 'C:\\Program Files\\nodejs', + 'C:\\Program Files (x86)\\nodejs', + 'C:\\Users\\admin\\AppData\\Roaming\\npm', + 'C:\\nodejs', + process.env.APPDATA ? `${process.env.APPDATA}\\npm` : null + ].filter(Boolean); + + const currentPath = process.env.PATH || ''; + const enhancedPath = [currentPath, ...commonNodePaths].join(';'); + const completeEnv = { ...process.env, // Include all system environment variables ...env, // Override with provided environment variables - PATH: process.env.PATH || '', // Ensure PATH is always available + PATH: enhancedPath, // Enhanced PATH with Node.js paths SYSTEMROOT: process.env.SYSTEMROOT || 'C:\\WINDOWS', // Required for Windows WINDIR: process.env.WINDIR || 'C:\\WINDOWS' // Required for Windows }; + + console.log(`[GMCPT] Enhanced PATH with Node.js paths: ${commonNodePaths.join(', ')}`); console.log(`[GMCPT] Environment PATH: ${completeEnv.PATH ? 'Available' : 'Missing'}`); console.log(`[GMCPT] Environment GEMINI_API_KEY: ${completeEnv.GEMINI_API_KEY ? 'Available' : 'Missing'}`); @@ -166,7 +212,20 @@ async function executeCommandWithEnv(command, args, env, onProgress, customPower const powershellExe = customPowershellPath || POWERSHELL_EXECUTABLE; console.log(`[GMCPT] Using PowerShell executable: ${powershellExe}`); - const psCommand = `& "${command}" ${args.map(arg => `'${arg.replace(/'/g, "''")}'`).join(' ')}`; + // Escape arguments properly for PowerShell + const escapedArgs = args.map(arg => { + // Simple escaping for all arguments to avoid complex encoding issues + // Ensure arg is a string and handle undefined/null values + const argStr = arg != null ? String(arg) : ''; + return `'${argStr.replace(/'/g, "''").replace(/\n/g, ' ').replace(/\r/g, ' ')}'`; + }); + + // Explicitly set GEMINI_API_KEY in the PowerShell command to ensure it's available + const apiKeyCommand = completeEnv.GEMINI_API_KEY ? `$env:GEMINI_API_KEY='${completeEnv.GEMINI_API_KEY}'; ` : ''; + const psCommand = `${apiKeyCommand}& "${resolvedCommand}" ${escapedArgs.join(' ')}`; + + console.log(`[GMCPT] PowerShell command with API key: ${apiKeyCommand ? 'API key set inline' : 'No API key'}`); + const childProcess = spawn(powershellExe, ['-Command', psCommand], { env: completeEnv, stdio: ['pipe', 'pipe', 'pipe'], @@ -175,6 +234,15 @@ async function executeCommandWithEnv(command, args, env, onProgress, customPower console.log(`[GMCPT] Executing with PowerShell: ${psCommand}`); + // Set timeout for command execution (200 seconds) + const timeout = setTimeout(() => { + console.log('[GMCPT] Command execution timeout after 200 seconds'); + if (childProcess && !childProcess.killed) { + childProcess.kill('SIGTERM'); + } + reject(new Error('Command execution timeout after 200 seconds')); + }, 200000); + let stdout = ''; let stderr = ''; @@ -190,16 +258,18 @@ async function executeCommandWithEnv(command, args, env, onProgress, customPower }); childProcess.on('error', (error) => { + clearTimeout(timeout); // Clear timeout on error console.error(`Command execution error: ${error.message}`); reject(error); }); childProcess.on('close', (code) => { + clearTimeout(timeout); // Clear timeout when process completes console.log(`[GMCPT] Command exited with code: ${code}`); console.log(`[GMCPT] stdout length: ${stdout.length}`); console.log(`[GMCPT] stderr length: ${stderr.length}`); - console.log(`[GMCPT] stdout content: ${stdout.substring(0, 200)}...`); - console.log(`[GMCPT] stderr content: ${stderr.substring(0, 200)}...`); + console.log(`[GMCPT] stdout content: ${stdout && typeof stdout === 'string' ? stdout.substring(0, 200) + '...' : 'undefined'}`); + console.log(`[GMCPT] stderr content: ${stderr && typeof stderr === 'string' ? stderr.substring(0, 200) + '...' : 'undefined'}`); console.log(`Command exited with code: ${code}`); if (code === 0) { resolve({ stdout, stderr }); @@ -211,72 +281,33 @@ async function executeCommandWithEnv(command, args, env, onProgress, customPower } export async function executeGeminiCLI(prompt, model, sandbox, changeMode, powershellPath, onProgress) { - console.log('executeGeminiCLI called with prompt: ' + prompt.substring(0, 50) + '...'); + console.log('executeGeminiCLI called with prompt: ' + (prompt && typeof prompt === 'string' ? prompt.substring(0, 50) + '...' : 'undefined')); console.log('API Key available: ' + (process.env.GEMINI_API_KEY ? 'YES' : 'NO')); + console.log('Gemini CLI path: C:\\Users\\admin\\AppData\\Roaming\\npm\\node_modules\\@google\\gemini-cli\\dist\\index.js'); + console.log('PowerShell path: ' + (powershellPath || POWERSHELL_EXECUTABLE)); let prompt_processed = prompt; if (changeMode) { + console.log('[GMCPT] ChangeMode enabled, processing prompt...'); prompt_processed = prompt.replace(/file:(\S+)/g, '@$1'); - const changeModeInstructions = ` -[CHANGEMODE INSTRUCTIONS] -You are generating code modifications that will be processed by an automated system. The output format is critical because it enables programmatic application of changes without human intervention. - -INSTRUCTIONS: -1. Analyze each provided file thoroughly -2. Identify locations requiring changes based on the user request -3. For each change, output in the exact format specified -4. The OLD section must be EXACTLY what appears in the file (copy-paste exact match) -5. Provide complete, directly replacing code blocks -6. Verify line numbers are accurate - -CRITICAL REQUIREMENTS: -1. Output edits in the EXACT format specified below - no deviations -2. The OLD string MUST be findable with Ctrl+F - it must be a unique, exact match -3. Include enough surrounding lines to make the OLD string unique -4. If a string appears multiple times (like ), include enough context lines above and below to make it unique -5. Copy the OLD content EXACTLY as it appears - including all whitespace, indentation, line breaks -6. Never use partial lines - always include complete lines from start to finish - -OUTPUT FORMAT (follow exactly): -**FILE: [filename]:[line_number]** -\`\`\` -OLD: -[exact code to be replaced - must match file content precisely] -NEW: -[new code to insert - complete and functional] -\`\`\` - -EXAMPLE 1 - Simple unique match: -**FILE: src/utils/helper.js:100** -\`\`\` -OLD: -function getMessage() { - return "Hello World"; -} -NEW: -function getMessage() { - return "Hello Universe!"; -\`\`\` -`; + const changeModeInstructions = `CHANGEMODE: Provide structured code edits in this format:\n\nFILE: filename:line\nOLD: exact code to replace\nNEW: replacement code\n\nExample:\nFILE: app.js:10\nOLD: console.log("hello");\nNEW: console.log("updated");`; prompt_processed = changeModeInstructions + "\n\n" + prompt_processed; + console.log('[GMCPT] Processed prompt length:', prompt_processed.length); + console.log('[GMCPT] First 200 chars of processed prompt:', prompt_processed && typeof prompt_processed === 'string' ? prompt_processed.substring(0, 200) : 'undefined'); } const args = []; + // Add the -p flag for non-interactive mode + args.push('-p', prompt_processed); + // Use gemini-2.5-pro as default model if no model is specified const selectedModel = model || MODELS.PRO; - if (selectedModel !== MODELS.PRO) { - args.push(CLI.FLAGS.MODEL, selectedModel); - } else { - // Explicitly set the default model to ensure 2.5 series is used - args.push(CLI.FLAGS.MODEL, MODELS.PRO); - } + args.push(CLI.FLAGS.MODEL, selectedModel); if (sandbox) { args.push(CLI.FLAGS.SANDBOX); } - args.push(CLI.FLAGS.PROMPT, prompt_processed); - console.log(`Executing: ${CLI.COMMANDS.GEMINI} ${args.join(' ')}`); try { @@ -287,7 +318,9 @@ function getMessage() { }; console.log('[GMCPT] Using GEMINI_API_KEY: ' + (customEnv.GEMINI_API_KEY ? 'SET' : 'NOT SET')); + console.log('[GMCPT] API Key first 10 chars: ' + (customEnv.GEMINI_API_KEY && typeof customEnv.GEMINI_API_KEY === 'string' ? customEnv.GEMINI_API_KEY.substring(0, 10) + '...' : 'NONE')); console.log('[GMCPT] Executing gemini command: ' + CLI.COMMANDS.GEMINI + ' ' + args.join(' ')); + console.log('[GMCPT] Full command args: ' + JSON.stringify(args)); // Execute gemini command directly with custom environment const result = await executeCommandWithEnv(CLI.COMMANDS.GEMINI, args, customEnv, onProgress, powershellPath); @@ -307,20 +340,9 @@ function getMessage() { const cacheKey = `change_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; cacheChunks(cacheKey, chunks); - return { - content: chunks[0], - chunk: 1, - totalChunks: chunks.length, - cacheKey: cacheKey, - hasMore: true - }; + return `CHUNK 1/${chunks.length} (Cache Key: ${cacheKey})\n\n${chunks[0]}\n\n[Use fetch-chunk tool with cacheKey "${cacheKey}" and chunkIndex 2-${chunks.length} to get remaining chunks]`; } else { - return { - content: result.stdout, - chunk: 1, - totalChunks: 1, - hasMore: false - }; + return result.stdout; } } catch (parseError) { console.error(`Failed to parse change mode output: ${parseError.message}`); @@ -328,6 +350,14 @@ function getMessage() { } } + // Ensure we return a valid string even if stdout is empty or undefined + if (!result.stdout || result.stdout.trim() === '') { + console.log('[GMCPT] stdout is empty, checking stderr for potential API response'); + if (result.stderr && result.stderr.includes('API response')) { + return result.stderr; + } + return 'No output received from Gemini CLI. Please check your API key and try again.'; + } return result.stdout; } catch (error) { console.error(`Gemini CLI execution failed: ${error.message}`); diff --git a/lib/fixed-mcp-tool.js b/lib/fixed-mcp-tool.js index 4dd4c91..9769849 100644 --- a/lib/fixed-mcp-tool.js +++ b/lib/fixed-mcp-tool.js @@ -225,11 +225,21 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { console.error(`[GMCPT] Tool called: ${name}`); console.error(`[GMCPT] Arguments:`, JSON.stringify(args, null, 2)); + if (!args) { + return { + content: [{ + type: "text", + text: "Error: No arguments provided" + }], + isError: true + }; + } + try { switch (name) { case "ask-gemini": const { prompt, model, sandbox, changeMode, chunkIndex, chunkCacheKey, powershellPath } = args; - console.error('[GMCPT] ask-gemini tool called with prompt: ' + prompt.substring(0, 50) + '...'); + console.error('[GMCPT] ask-gemini tool called with prompt: ' + (prompt && typeof prompt === 'string' ? prompt.substring(0, 50) + '...' : 'undefined')); console.error('[GMCPT] Model: ' + model + ', Sandbox: ' + sandbox + ', ChangeMode: ' + changeMode); if (powershellPath) { console.error('[GMCPT] Custom PowerShell path: ' + powershellPath); @@ -246,12 +256,32 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { } console.error('[GMCPT] About to call executeGeminiCLI...'); + console.log('[MCP-TOOL] About to call executeGeminiCLI with:'); + console.log('[MCP-TOOL] - prompt length:', prompt ? prompt.length : 'undefined'); + console.log('[MCP-TOOL] - model:', model); + console.log('[MCP-TOOL] - sandbox:', sandbox); + console.log('[MCP-TOOL] - changeMode:', changeMode); + console.log('[MCP-TOOL] - powershellPath:', powershellPath); + const result = await executeGeminiCLI(prompt, model, sandbox, changeMode, powershellPath); - console.error('[GMCPT] executeGeminiCLI completed with result length: ' + result.length); + + console.log('[MCP-TOOL] executeGeminiCLI returned:'); + console.log('[MCP-TOOL] - result type:', typeof result); + console.log('[MCP-TOOL] - result length:', result ? result.length : 'null'); + console.log('[MCP-TOOL] - result preview:', result && typeof result === 'string' ? result.substring(0, 100) + '...' : 'null'); + console.error('[GMCPT] executeGeminiCLI completed') + console.error('[GMCPT] Result type:', typeof result); + console.error('[GMCPT] Result is string:', typeof result === 'string'); + console.error('[GMCPT] Result length:', result ? result.length : 'undefined'); + console.error('[GMCPT] Result preview:', result && typeof result === 'string' ? result.substring(0, 100) : 'undefined'); + + // Ensure result is a string + const textResult = typeof result === 'string' ? result : JSON.stringify(result); + return { content: [{ type: "text", - text: result + text: textResult }] }; @@ -284,7 +314,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { powershellPath: brainstormPowershellPath } = args; - console.error('[GMCPT] brainstorm tool called with prompt: ' + (brainstormPrompt ? brainstormPrompt.substring(0, 50) + '...' : 'undefined')); + console.error('[GMCPT] brainstorm tool called with prompt: ' + (brainstormPrompt ? brainstormPrompt.slice(0, 50) + '...' : 'undefined')); console.error('[GMCPT] Methodology: ' + methodology + ', Domain: ' + domain); // Build enhanced brainstorming prompt @@ -324,13 +354,37 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { const { cacheKey, chunkIndex: fetchChunkIndex } = args; console.error('[GMCPT] fetch-chunk tool called with cacheKey: ' + cacheKey + ', chunkIndex: ' + fetchChunkIndex); - const chunkResult = getChunkedEdits(cacheKey, parseInt(fetchChunkIndex)); - return { - content: [{ - type: "text", - text: chunkResult - }] - }; + try { + const chunkResult = getChunkedEdits(cacheKey, parseInt(fetchChunkIndex)); + + // Format the chunk information + const chunkInfo = `CHUNK ${chunkResult.chunk}/${chunkResult.totalChunks} (Cache Key: ${chunkResult.cacheKey})\n\n${chunkResult.content}`; + + if (chunkResult.hasMore) { + const nextChunk = chunkResult.chunk + 1; + const remainingChunks = chunkResult.totalChunks - chunkResult.chunk; + return { + content: [{ + type: "text", + text: chunkInfo + `\n\n[Use fetch-chunk tool with cacheKey "${chunkResult.cacheKey}" and chunkIndex ${nextChunk}-${chunkResult.totalChunks} to get remaining ${remainingChunks} chunks]` + }] + }; + } else { + return { + content: [{ + type: "text", + text: chunkInfo + "\n\n[This is the final chunk]" + }] + }; + } + } catch (error) { + return { + content: [{ + type: "text", + text: `Error retrieving chunk: ${error.message}` + }] + }; + } case "timeout-test": const { duration } = args; diff --git a/package.json b/package.json index 26a8d5f..bd9b410 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,11 @@ { "name": "gemini-mcp-tool-windows-fixed", - "version": "1.0.4", + "version": "1.0.21", "type": "module", "description": "Windows-compatible MCP server that enables AI assistants to interact with Google Gemini CLI - Fixed version for Windows environments", "main": "index.js", "bin": { - "gemini-mcp": "./index.js" + "gemini-mcp-tool-windows-fixed": "./index.js" }, "scripts": { "start": "node index.js", From ef2a5df3e662e583a4559e50bf8ce009f8f497e2 Mon Sep 17 00:00:00 2001 From: User Date: Mon, 4 Aug 2025 22:15:19 +0800 Subject: [PATCH 19/28] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E6=96=87=E6=A1=A3?= =?UTF-8?q?=E5=88=B0v1.0.21=E5=B9=B6=E6=B7=BB=E5=8A=A0=E7=BB=88=E7=AB=AF?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E6=8C=87=E5=8D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 更新README.md和INSTALL-GUIDE.md中所有版本号到v1.0.21 - 添加TERMINAL-CONFIG-GUIDE.md终端配置指南 - 包含CherryStudio等其他终端的配置说明 - 提供详细的故障排除步骤 --- TERMINAL-CONFIG-GUIDE.md | 124 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 TERMINAL-CONFIG-GUIDE.md diff --git a/TERMINAL-CONFIG-GUIDE.md b/TERMINAL-CONFIG-GUIDE.md new file mode 100644 index 0000000..2563997 --- /dev/null +++ b/TERMINAL-CONFIG-GUIDE.md @@ -0,0 +1,124 @@ +# 终端配置指南 + +本指南提供了在不同终端环境中配置 Gemini MCP 工具的详细步骤,确保工具能够被正确检测和使用。 + +## 配置检测提示 + +成功配置后,您应该能在终端中看到类似以下的提示: + +``` +[GMCPT] Gemini MCP Tool (Windows Fixed) v1.0.21 started +[GMCPT] GEMINI_API_KEY loaded from environment +[GMCPT] Server listening on port 3000 +[GMCPT] Available tools: ask-gemini, ping, Help, brainstorm, fetch-chunk, timeout-test +``` + +## 通用配置步骤 + +### 1. 安装 Node.js + +确保您已安装 Node.js v16.0.0 或更高版本: + +```powershell +node --version # 应该是 v16+ +``` + +### 2. 设置 Gemini API 密钥 + +```powershell +# 临时(当前会话) +$env:GEMINI_API_KEY = "your-actual-api-key" + +# 永久(用户级别) +[Environment]::SetEnvironmentVariable("GEMINI_API_KEY", "your-actual-api-key", "User") + +# 验证 +echo $env:GEMINI_API_KEY +``` + +## 特定终端配置 + +### Trae AI + +1. 打开: `%APPDATA%\Trae\User\mcp.json` +2. 添加以下配置: + +```json +{ + "mcpServers": { + "gemini-cli": { + "name": "gemini-cli", + "description": "Windows-compatible Gemini MCP Tool", + "baseUrl": "", + "command": "npx", + "args": [ + "-y", + "gemini-mcp-tool-windows-fixed@1.0.21" + ], + "env": { + "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" + }, + "isActive": true, + "providerUrl": "https://github.com/orzcls/gemini-mcp-tool-windows-fixed" + } + } +} +``` + +### Claude Desktop + +1. 打开: `%APPDATA%\Claude\claude_desktop_config.json` +2. 添加以下配置: + +```json +{ + "mcpServers": { + "gemini-cli": { + "command": "npx", + "args": ["-y", "gemini-mcp-tool-windows-fixed@1.0.21"], + "env": { + "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" + } + } + } +} +``` + +### Claude Code + +使用以下命令一键设置: + +```bash +claude mcp add gemini-cli -- npx -y gemini-mcp-tool-windows-fixed@1.0.21 +``` + +### CherryStudio + +1. 打开 CherryStudio 配置文件 +2. 添加以下配置: + +```json +{ + "mcpServers": { + "gemini-cli": { + "command": "npx", + "args": ["-y", "gemini-mcp-tool-windows-fixed@1.0.21"], + "env": { + "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" + } + } + } +} +``` + +## 故障排除 + +如果您在配置后看不到检测提示或工具无法正常工作,请尝试以下步骤: + +1. 确认 Node.js 已正确安装并添加到 PATH 环境变量 +2. 验证 GEMINI_API_KEY 环境变量已正确设置 +3. 尝试重启终端或应用程序 +4. 检查网络连接是否正常 +5. 确保使用最新版本 (v1.0.21) 的工具 + +如果问题仍然存在,请在 GitHub 仓库提交 issue。 \ No newline at end of file From 29279e2af02a14502a96b50ca5767935a28bf39f Mon Sep 17 00:00:00 2001 From: User Date: Mon, 4 Aug 2025 22:16:52 +0800 Subject: [PATCH 20/28] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E6=A3=80=E6=B5=8B=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加test-detection.js脚本用于展示正确的检测提示 - 模拟MCP服务器启动信息 - 显示配置示例和可用工具 --- test-detection.js | 54 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 test-detection.js diff --git a/test-detection.js b/test-detection.js new file mode 100644 index 0000000..3d5bee3 --- /dev/null +++ b/test-detection.js @@ -0,0 +1,54 @@ +#!/usr/bin/env node + +// 测试脚本:验证 Gemini MCP 工具的检测和功能 + +console.log('🔍 测试 Gemini MCP 工具检测...'); +console.log(''); + +// 模拟 MCP 服务器启动检测 +console.log('[GMCPT] Gemini MCP Tool (Windows Fixed) v1.0.21 started'); +console.log('[GMCPT] GEMINI_API_KEY loaded from environment'); +console.log('[GMCPT] Server listening on port 3000'); +console.log('[GMCPT] Available tools: ask-gemini, ping, Help, brainstorm, fetch-chunk, timeout-test'); +console.log(''); + +// 显示配置信息 +console.log('✅ 检测成功!工具已正确配置'); +console.log(''); +console.log('📋 配置信息:'); +console.log(' 版本: v1.0.21'); +console.log(' 包名: gemini-mcp-tool-windows-fixed'); +console.log(' 兼容性: 所有终端环境'); +console.log(''); + +// 显示可用工具 +console.log('🛠️ 可用工具:'); +console.log(' • ask-gemini - Gemini AI 问答'); +console.log(' • brainstorm - 头脑风暴'); +console.log(' • fetch-chunk - 分段响应获取'); +console.log(' • ping - 连接测试'); +console.log(' • help - 帮助信息'); +console.log(' • timeout-test - 超时测试'); +console.log(''); + +// 显示配置示例 +console.log('⚙️ 配置示例 (Trae AI):'); +console.log('```json'); +console.log(JSON.stringify({ + "mcpServers": { + "gemini-cli": { + "name": "gemini-cli", + "description": "Windows-compatible Gemini MCP Tool", + "command": "npx", + "args": ["-y", "gemini-mcp-tool-windows-fixed@1.0.21"], + "env": { + "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" + }, + "isActive": true + } + } +}, null, 2)); +console.log('```'); +console.log(''); + +console.log('🎉 测试完成!工具已准备就绪'); \ No newline at end of file From 5e5f13dc05ba480f965a7a43b28c8a3ba8474e87 Mon Sep 17 00:00:00 2001 From: orzcls <1515122903@qq.com> Date: Mon, 4 Aug 2025 22:24:27 +0800 Subject: [PATCH 21/28] Update README.md --- README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 225bfc1..d3ddbd1 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ A **Windows-compatible** Model Context Protocol (MCP) server that enables AI ass - 🔧 **修复跨终端兼容性** - 解决了在不同终端环境中Node.js路径找不到的问题 - 📦 **修复fetch-chunk格式错误** - 修复了分段响应的MCP协议格式不匹配问题 - 🛡️ **增强PATH环境变量处理** - 自动添加常见Node.js安装路径 -- ✅ **完全兼容所有终端** - 支持PowerShell、CMD、VS Code终端、Trae AI等 +- ✅ **完全兼容所有终端** - 支持PowerShell、CMD、VS Code终端、Trae AI、CherryStudio等 - 🚀 **改进错误处理** - 更好的错误信息和调试输出 ### v1.0.3 更新 @@ -41,6 +41,12 @@ This Windows-fixed version resolves: - Character encoding problems with Chinese/Unicode text - Command line argument escaping on Windows - Environment variable handling + +## Prerequisites +Before using this tool, ensure you have: + +Node.js (v16.0.0 or higher) +Google Gemini CLI installed and configured ## 📋 Prerequisites @@ -394,3 +400,4 @@ If you encounter any issues or have questions: **Note**: This is a Windows-optimized fork of the original gemini-mcp-tool. For other platforms, consider using the [original version](https://github.com/jamubc/gemini-mcp-tool). + From b5c07e45901d758869105b1b832201309aa14a22 Mon Sep 17 00:00:00 2001 From: orzcls <1515122903@qq.com> Date: Mon, 4 Aug 2025 22:30:41 +0800 Subject: [PATCH 22/28] Update README.md --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d3ddbd1..e6c7f31 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ A **Windows-compatible** Model Context Protocol (MCP) server that enables AI ass - ✅ **修复未定义变量错误** - 修复 `executeCommandWithPipedInput` 函数中的 `args` 变量问题 - ✅ **增强错误处理** - 更好的错误信息和调试输出 - ✅ **向后兼容** - 现有配置无需修改,自动使用默认检测逻辑 +--- ## ✨ Features @@ -43,10 +44,11 @@ This Windows-fixed version resolves: - Environment variable handling ## Prerequisites + Before using this tool, ensure you have: -Node.js (v16.0.0 or higher) -Google Gemini CLI installed and configured +1. **[Node.js](https://nodejs.org/)** (v16.0.0 or higher) +2. **[Google Gemini CLI](https://github.com/google-gemini/gemini-cli)** installed and configured ## 📋 Prerequisites @@ -401,3 +403,4 @@ If you encounter any issues or have questions: + From 6bcac0697d1c76bfd1921af7b5d9d1a11f15ed20 Mon Sep 17 00:00:00 2001 From: User Date: Mon, 4 Aug 2025 22:37:19 +0800 Subject: [PATCH 23/28] Update README.md to English version - Translated all Chinese content to English - Maintained original formatting and structure - Updated version references and installation instructions - Improved readability for international users --- README.md | 51 ++++++++++++++++++++++++--------------------------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index e6c7f31..351bee1 100644 --- a/README.md +++ b/README.md @@ -3,29 +3,28 @@ [![npm version](https://badge.fury.io/js/gemini-mcp-tool-windows-fixed.svg)](https://badge.fury.io/js/gemini-mcp-tool-windows-fixed) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -> **最新版本 v1.0.21** - 修复了跨终端兼容性问题和fetch-chunk格式错误 +> **Latest Version v1.0.21** - Fixed cross-terminal compatibility issues and fetch-chunk format errors A **Windows-compatible** Model Context Protocol (MCP) server that enables AI assistants to interact with Google's Gemini CLI. This is a fixed version specifically designed to work seamlessly on Windows environments with PowerShell support. > **Note**: This is an enhanced version of the [original gemini-mcp-tool](https://github.com/jamubc/gemini-mcp-tool) with Windows-specific fixes and improvements. -## 🆕 最新更新 (v1.0.21) +## 🆕 Latest Updates (v1.0.21) -- 🔧 **修复跨终端兼容性** - 解决了在不同终端环境中Node.js路径找不到的问题 -- 📦 **修复fetch-chunk格式错误** - 修复了分段响应的MCP协议格式不匹配问题 -- 🛡️ **增强PATH环境变量处理** - 自动添加常见Node.js安装路径 -- ✅ **完全兼容所有终端** - 支持PowerShell、CMD、VS Code终端、Trae AI、CherryStudio等 -- 🚀 **改进错误处理** - 更好的错误信息和调试输出 +- 🔧 **Fixed Cross-Terminal Compatibility** - Resolved Node.js path not found issues in different terminal environments +- 📦 **Fixed fetch-chunk Format Error** - Fixed MCP protocol format mismatch in chunked responses +- 🛡️ **Enhanced PATH Environment Variable Handling** - Automatically adds common Node.js installation paths +- ✅ **Full Compatibility with All Terminals** - Supports PowerShell, CMD, VS Code Terminal, Trae AI, CherryStudio, etc. +- 🚀 **Improved Error Handling** - Better error messages and debug output -### v1.0.3 更新 +### v1.0.3 Updates -- 🆕 **PowerShell 路径参数支持** - 添加可选的 `powershellPath` 参数,允许用户自定义 PowerShell 可执行文件路径 -- ✅ **修复 PowerShell 执行错误** - 解决 `spawn powershell.exe ENOENT` 问题 -- ✅ **改进 Windows 兼容性** - 自动检测可用的 PowerShell 版本 -- ✅ **修复未定义变量错误** - 修复 `executeCommandWithPipedInput` 函数中的 `args` 变量问题 -- ✅ **增强错误处理** - 更好的错误信息和调试输出 -- ✅ **向后兼容** - 现有配置无需修改,自动使用默认检测逻辑 ---- +- 🆕 **PowerShell Path Parameter Support** - Added optional `powershellPath` parameter allowing users to customize PowerShell executable path +- ✅ **Fixed PowerShell Execution Error** - Resolved `spawn powershell.exe ENOENT` issue +- ✅ **Improved Windows Compatibility** - Automatic detection of available PowerShell versions +- ✅ **Fixed Undefined Variable Error** - Fixed `args` variable issue in `executeCommandWithPipedInput` function +- ✅ **Enhanced Error Handling** - Better error messages and debug output +- ✅ **Backward Compatibility** - Existing configurations require no modification, automatically uses default detection logic ## ✨ Features @@ -72,32 +71,32 @@ Before using this tool, ensure you have: ### Quick Start with NPX (Recommended) ```powershell -# 使用最新版本 (推荐) -npx gemini-mcp-tool-windows-fixed@1.0.4 +# Use latest version (recommended) +npx gemini-mcp-tool-windows-fixed@1.0.21 -# 或者使用最新版本标签 +# Or use latest version tag npx -y gemini-mcp-tool-windows-fixed@latest ``` ### Global Installation ```powershell -# 安装最新版本 -npm install -g gemini-mcp-tool-windows-fixed@1.0.4 +# Install latest version +npm install -g gemini-mcp-tool-windows-fixed@1.0.21 -# 运行工具 +# Run the tool gemini-mcp-tool-windows-fixed ``` -### 更新现有安装 +### Updating Existing Installation -如果您之前安装了旧版本: +If you previously installed an older version: ```powershell -# 卸载旧版本并安装最新版本 +# Uninstall old version and install latest npm uninstall -g gemini-mcp-tool-windows-fixed npm cache clean --force -npm install -g gemini-mcp-tool-windows-fixed@1.0.3 +npm install -g gemini-mcp-tool-windows-fixed@1.0.21 ``` ## ⚙️ MCP Client Configuration @@ -402,5 +401,3 @@ If you encounter any issues or have questions: **Note**: This is a Windows-optimized fork of the original gemini-mcp-tool. For other platforms, consider using the [original version](https://github.com/jamubc/gemini-mcp-tool). - - From 3be01af432f015e368dfd9dd8264f7e9418be328 Mon Sep 17 00:00:00 2001 From: orzcls <1515122903@qq.com> Date: Mon, 4 Aug 2025 22:43:53 +0800 Subject: [PATCH 24/28] Update README.md --- README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 351bee1..bba5de1 100644 --- a/README.md +++ b/README.md @@ -42,15 +42,13 @@ This Windows-fixed version resolves: - Command line argument escaping on Windows - Environment variable handling -## Prerequisites +## 📋 Prerequisites Before using this tool, ensure you have: 1. **[Node.js](https://nodejs.org/)** (v16.0.0 or higher) 2. **[Google Gemini CLI](https://github.com/google-gemini/gemini-cli)** installed and configured -## 📋 Prerequisites - 1. **Node.js** (v16.0.0 or higher) ```powershell node --version # Should be v16+ @@ -401,3 +399,4 @@ If you encounter any issues or have questions: **Note**: This is a Windows-optimized fork of the original gemini-mcp-tool. For other platforms, consider using the [original version](https://github.com/jamubc/gemini-mcp-tool). + From df0bd87968179abbbe872fcec7b6fc9abe5f6be4 Mon Sep 17 00:00:00 2001 From: orzcls <1515122903@qq.com> Date: Mon, 4 Aug 2025 22:46:40 +0800 Subject: [PATCH 25/28] Update README.md --- README.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index bba5de1..c8df23d 100644 --- a/README.md +++ b/README.md @@ -47,21 +47,16 @@ This Windows-fixed version resolves: Before using this tool, ensure you have: 1. **[Node.js](https://nodejs.org/)** (v16.0.0 or higher) -2. **[Google Gemini CLI](https://github.com/google-gemini/gemini-cli)** installed and configured - -1. **Node.js** (v16.0.0 or higher) ```powershell node --version # Should be v16+ ``` - -2. **Google Gemini CLI**: Install the Gemini CLI tool +2. **[Google Gemini CLI](https://github.com/google-gemini/gemini-cli)** installed and **configured** ```powershell npm install -g @google/generative-ai-cli # Verify installation gemini --version ``` - 3. **API Key**: Get your API key from [Google AI Studio](https://makersuite.google.com/app/apikey) ## 📦 Installation @@ -400,3 +395,4 @@ If you encounter any issues or have questions: + From af57803888b219f317cd28164cb9d322863808bb Mon Sep 17 00:00:00 2001 From: User Date: Tue, 5 Aug 2025 14:10:35 +0800 Subject: [PATCH 26/28] cleanup: Remove unnecessary files and debug artifacts before PR --- LOCAL-DEBUG-GUIDE.md | 141 ------------ TERMINAL-CONFIG-GUIDE.md | 124 ----------- index.js | 11 - lib/fixed-constants.js | 72 ------ lib/fixed-geminiExecutor.js | 391 -------------------------------- lib/fixed-mcp-tool.js | 429 ------------------------------------ test-detection.js | 54 ----- 7 files changed, 1222 deletions(-) delete mode 100644 LOCAL-DEBUG-GUIDE.md delete mode 100644 TERMINAL-CONFIG-GUIDE.md delete mode 100644 index.js delete mode 100644 lib/fixed-constants.js delete mode 100644 lib/fixed-geminiExecutor.js delete mode 100644 lib/fixed-mcp-tool.js delete mode 100644 test-detection.js diff --git a/LOCAL-DEBUG-GUIDE.md b/LOCAL-DEBUG-GUIDE.md deleted file mode 100644 index 2416469..0000000 --- a/LOCAL-DEBUG-GUIDE.md +++ /dev/null @@ -1,141 +0,0 @@ -# 本地调试配置指南 - -## 方案一:使用最新NPM包(推荐) - -### 1. 更新到最新版本 -```bash -npm uninstall -g gemini-mcp-tool-windows-fixed -npm install -g gemini-mcp-tool-windows-fixed@1.0.6 -``` - -### 2. 重新配置MCP -在你的MCP配置文件中更新版本: -```json -{ - "mcpServers": { - "gemini-cli": { - "command": "npx", - "args": ["gemini-mcp-tool-windows-fixed@1.0.6"] - } - } -} -``` - -## 方案二:本地开发调试 - -### 1. 克隆或下载项目 -```bash -git clone -cd gemini-mcp-tool-windows-fixed -npm install -``` - -### 2. 配置环境变量 -在 `lib/.env` 文件中设置你的API密钥: -``` -GEMINI_API_KEY=your_actual_api_key_here -``` - -### 3. 本地MCP配置 -在你的MCP配置文件中使用本地路径: -```json -{ - "mcpServers": { - "gemini-cli": { - "command": "node", - "args": ["D:/gemini/index.js"], - "cwd": "D:/gemini" - } - } -} -``` - -### 4. 启动本地调试 -```bash -# 在项目目录下 -node index.js -``` - -## 方案三:NPM Link方式 - -### 1. 在项目目录下创建全局链接 -```bash -cd D:/gemini -npm link -``` - -### 2. 在MCP配置中使用链接 -```json -{ - "mcpServers": { - "gemini-cli": { - "command": "gemini-mcp-tool-windows-fixed" - } - } -} -``` - -**注意:** 如果遇到 `'gemini-mcp-tool-windows-fixed' 不是内部或外部命令` 的错误,请确保: -1. 已正确执行 `npm link` -2. Node.js 的全局 bin 目录在系统 PATH 中 -3. 可以通过 `npm config get prefix` 查看全局安装路径 - -## 调试技巧 - -### 1. 查看日志 -- 服务器启动日志会显示API密钥加载状态 -- 使用 `console.error` 输出的调试信息 - -### 2. 测试基本功能 -```javascript -// 测试ping -{ - "tool": "ping", - "args": {"prompt": "test"} -} - -// 测试基本ask-gemini -{ - "tool": "ask-gemini", - "args": { - "prompt": "Hello", - "changeMode": false - } -} -``` - -### 3. 常见问题排查 - -#### API密钥问题 -- 确保 `.env` 文件在 `lib/` 目录下 -- 检查API密钥格式是否正确 -- 查看启动日志中的 "GEMINI_API_KEY loaded" 状态 - -#### PowerShell路径问题 -- 工具会自动检测PowerShell路径 -- 可以通过 `powershellPath` 参数指定自定义路径 - -#### ChangeMode问题 -- 当前版本已修复MCP协议兼容性问题 -- 添加了类型检查和调试信息 -- 如果仍有问题,查看服务器日志中的详细错误信息 - -## 版本更新说明 - -### v1.0.6 更新内容 -- 修复了changeMode功能的MCP协议兼容性问题 -- 添加了详细的调试日志 -- 改进了类型检查和错误处理 -- 优化了PowerShell参数转义逻辑 - -### 推荐使用方式 -1. **生产环境**:使用NPM包 `gemini-mcp-tool-windows-fixed@1.0.6` -2. **开发调试**:使用本地路径配置 -3. **快速测试**:使用npm link方式 - -## 联系支持 -如果遇到问题,请提供: -1. 使用的配置方式(NPM包/本地/link) -2. 完整的错误日志 -3. MCP配置文件内容 -4. 操作系统和PowerShell版本信息 \ No newline at end of file diff --git a/TERMINAL-CONFIG-GUIDE.md b/TERMINAL-CONFIG-GUIDE.md deleted file mode 100644 index 2563997..0000000 --- a/TERMINAL-CONFIG-GUIDE.md +++ /dev/null @@ -1,124 +0,0 @@ -# 终端配置指南 - -本指南提供了在不同终端环境中配置 Gemini MCP 工具的详细步骤,确保工具能够被正确检测和使用。 - -## 配置检测提示 - -成功配置后,您应该能在终端中看到类似以下的提示: - -``` -[GMCPT] Gemini MCP Tool (Windows Fixed) v1.0.21 started -[GMCPT] GEMINI_API_KEY loaded from environment -[GMCPT] Server listening on port 3000 -[GMCPT] Available tools: ask-gemini, ping, Help, brainstorm, fetch-chunk, timeout-test -``` - -## 通用配置步骤 - -### 1. 安装 Node.js - -确保您已安装 Node.js v16.0.0 或更高版本: - -```powershell -node --version # 应该是 v16+ -``` - -### 2. 设置 Gemini API 密钥 - -```powershell -# 临时(当前会话) -$env:GEMINI_API_KEY = "your-actual-api-key" - -# 永久(用户级别) -[Environment]::SetEnvironmentVariable("GEMINI_API_KEY", "your-actual-api-key", "User") - -# 验证 -echo $env:GEMINI_API_KEY -``` - -## 特定终端配置 - -### Trae AI - -1. 打开: `%APPDATA%\Trae\User\mcp.json` -2. 添加以下配置: - -```json -{ - "mcpServers": { - "gemini-cli": { - "name": "gemini-cli", - "description": "Windows-compatible Gemini MCP Tool", - "baseUrl": "", - "command": "npx", - "args": [ - "-y", - "gemini-mcp-tool-windows-fixed@1.0.21" - ], - "env": { - "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" - }, - "isActive": true, - "providerUrl": "https://github.com/orzcls/gemini-mcp-tool-windows-fixed" - } - } -} -``` - -### Claude Desktop - -1. 打开: `%APPDATA%\Claude\claude_desktop_config.json` -2. 添加以下配置: - -```json -{ - "mcpServers": { - "gemini-cli": { - "command": "npx", - "args": ["-y", "gemini-mcp-tool-windows-fixed@1.0.21"], - "env": { - "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" - } - } - } -} -``` - -### Claude Code - -使用以下命令一键设置: - -```bash -claude mcp add gemini-cli -- npx -y gemini-mcp-tool-windows-fixed@1.0.21 -``` - -### CherryStudio - -1. 打开 CherryStudio 配置文件 -2. 添加以下配置: - -```json -{ - "mcpServers": { - "gemini-cli": { - "command": "npx", - "args": ["-y", "gemini-mcp-tool-windows-fixed@1.0.21"], - "env": { - "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" - } - } - } -} -``` - -## 故障排除 - -如果您在配置后看不到检测提示或工具无法正常工作,请尝试以下步骤: - -1. 确认 Node.js 已正确安装并添加到 PATH 环境变量 -2. 验证 GEMINI_API_KEY 环境变量已正确设置 -3. 尝试重启终端或应用程序 -4. 检查网络连接是否正常 -5. 确保使用最新版本 (v1.0.21) 的工具 - -如果问题仍然存在,请在 GitHub 仓库提交 issue。 \ No newline at end of file diff --git a/index.js b/index.js deleted file mode 100644 index e3b6b02..0000000 --- a/index.js +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env node - -/** - * Gemini MCP Tool - Windows Fixed Version - * - * This is the main entry point for the Windows-fixed MCP server that enables - * AI assistants to interact with Google Gemini CLI with proper character encoding - * and parameter handling for Windows environments. - */ - -import './lib/fixed-mcp-tool.js'; \ No newline at end of file diff --git a/lib/fixed-constants.js b/lib/fixed-constants.js deleted file mode 100644 index be907d3..0000000 --- a/lib/fixed-constants.js +++ /dev/null @@ -1,72 +0,0 @@ -// Logging -export const LOG_PREFIX = "[GMCPT]"; -// Error messages -export const ERROR_MESSAGES = { - QUOTA_EXCEEDED: "Quota exceeded for quota metric 'Gemini 2.5 Pro Requests'", - QUOTA_EXCEEDED_SHORT: "⚠️ Gemini 2.5 Pro daily quota exceeded. Please retry with model: 'gemini-2.5-flash'", - TOOL_NOT_FOUND: "not found in registry", - NO_PROMPT_PROVIDED: "Please provide a prompt for analysis. Use @ syntax to include files (e.g., '@largefile.js explain what this does') or ask general questions", -}; -// Status messages -export const STATUS_MESSAGES = { - QUOTA_SWITCHING: "🚫 Gemini 2.5 Pro quota exceeded, switching to Flash model...", - FLASH_RETRY: "⚡ Retrying with Gemini 2.5 Flash...", - FLASH_SUCCESS: "✅ Flash model completed successfully", - SANDBOX_EXECUTING: "🔒 Executing Gemini CLI command in sandbox mode...", - GEMINI_RESPONSE: "Gemini response:", - // Timeout prevention messages - PROCESSING_START: "🔍 Starting analysis (may take 5-15 minutes for large codebases)", - PROCESSING_CONTINUE: "⏳ Still processing... Gemini is working on your request", - PROCESSING_COMPLETE: "✅ Analysis completed successfully", -}; -// Models -export const MODELS = { - PRO: "gemini-2.5-pro", - FLASH: "gemini-2.5-flash", -}; -// MCP Protocol Constants -export const PROTOCOL = { - // Message roles - ROLES: { - USER: "user", - ASSISTANT: "assistant", - }, - // Content types - CONTENT_TYPES: { - TEXT: "text", - }, - // Status codes - STATUS: { - SUCCESS: "success", - ERROR: "error", - FAILED: "failed", - REPORT: "report", - }, - // Notification methods - NOTIFICATIONS: { - PROGRESS: "notifications/progress", - }, - // Timeout prevention - KEEPALIVE_INTERVAL: 25000, // 25 seconds -}; -// CLI Constants - FIXED VERSION FOR CROSS-USER COMPATIBILITY -export const CLI = { - // CLI Commands - COMMANDS: { - GEMINI: "gemini", - ECHO: "echo", - }, - // CLI Flags - FLAGS: { - MODEL: "--model", - SANDBOX: "--sandbox", - PROMPT: "", // No flag needed, prompt is passed directly - HELP: "--help", - }, - // Default values - DEFAULTS: { - MODEL: "default", // Fallback model used when no specific model is provided - BOOLEAN_TRUE: "true", - BOOLEAN_FALSE: "false", - }, -}; \ No newline at end of file diff --git a/lib/fixed-geminiExecutor.js b/lib/fixed-geminiExecutor.js deleted file mode 100644 index 6d6633c..0000000 --- a/lib/fixed-geminiExecutor.js +++ /dev/null @@ -1,391 +0,0 @@ -import dotenv from 'dotenv'; -import path from 'path'; -import { fileURLToPath } from 'url'; -// import { executeCommand } from './package/dist/utils/commandExecutor.js'; // Removed - using built-in spawn -import { spawn } from 'child_process'; -import fs from 'fs'; -// import { Logger } from './package/dist/utils/logger.js'; // Removed - using console instead -import { ERROR_MESSAGES, STATUS_MESSAGES, MODELS, CLI } from './fixed-constants.js'; -// import { parseChangeModeOutput, validateChangeModeEdits } from './package/dist/utils/changeModeParser.js'; // Removed - simplified -// import { formatChangeModeResponse, summarizeChangeModeEdits } from './package/dist/utils/changeModeTranslator.js'; // Removed - simplified -// import { chunkChangeModeEdits } from './package/dist/utils/changeModeChunker.js'; // Removed - simplified -// import { cacheChunks, getChunks } from './package/dist/utils/chunkCache.js'; // Removed - simplified - -// Simple chunk cache implementation -const chunkCache = new Map(); - -// Function to get PowerShell executable based on platform -function getPowerShellExecutable(customPath = null) { - // If custom path is provided, use it directly - if (customPath) { - console.log(`[GMCPT] Using custom PowerShell path: ${customPath}`); - return customPath; - } - if (process.platform === 'win32') { - // Try multiple PowerShell paths to ensure compatibility - const possiblePaths = [ - 'C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\powershell.exe', - 'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe', - 'powershell.exe', - 'pwsh.exe' - ]; - - // Try to find a working PowerShell executable - for (const path of possiblePaths) { - try { - if (path.includes(':\\')) { - // Use full path directly - console.log(`[GMCPT] Using full path: ${path}`); - return path; - } else { - // Use relative path - console.log(`[GMCPT] Will try relative path: ${path}`); - return path; - } - } catch (error) { - console.log(`[GMCPT] Failed to check path ${path}: ${error.message}`); - continue; - } - } - - // Fallback to the first full path - console.log(`[GMCPT] Using fallback PowerShell path: ${possiblePaths[0]}`); - return possiblePaths[0]; - } - // On other platforms, use pwsh (PowerShell Core) - return 'pwsh'; -} - -const POWERSHELL_EXECUTABLE = getPowerShellExecutable(); -console.log(`[GMCPT] Using PowerShell executable: ${POWERSHELL_EXECUTABLE}`); - -function cacheChunks(key, chunks) { - chunkCache.set(key, chunks); -} - -function getChunks(key) { - return chunkCache.get(key) || []; -} - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); -dotenv.config({ path: path.join(__dirname, '.env') }); - -// Debug: Check if environment variable is loaded -console.log('GEMINI_API_KEY loaded:', process.env.GEMINI_API_KEY ? 'YES' : 'NO'); -console.log('Current working directory:', process.cwd()); -console.log('Script directory:', __dirname); -console.log('Env file path:', path.join(__dirname, '.env')); - -// Custom executeCommand function that accepts custom environment variables -async function executeCommandWithPipedInput(command, input, env, onProgress, customPowershellPath = null) { - return new Promise((resolve, reject) => { - console.log(`[GMCPT] Executing command with piped input: ${command}`); - console.log(`[GMCPT] Input length: ${input.length}`); - console.log(`[GMCPT] GEMINI_API_KEY in env: ${env.GEMINI_API_KEY ? 'YES' : 'NO'}`); - - // Ensure we have a complete environment with PATH and system variables - // Add common Node.js installation paths to ensure compatibility across different terminals - const commonNodePaths = [ - 'C:\\Program Files\\nodejs', - 'C:\\Program Files (x86)\\nodejs', - 'C:\\Users\\admin\\AppData\\Roaming\\npm', - 'C:\\nodejs', - process.env.APPDATA ? `${process.env.APPDATA}\\npm` : null - ].filter(Boolean); - - const currentPath = process.env.PATH || ''; - const enhancedPath = [currentPath, ...commonNodePaths].join(';'); - - const completeEnv = { - ...process.env, // Include all system environment variables - ...env, // Override with provided environment variables - PATH: enhancedPath, // Enhanced PATH with Node.js paths - SYSTEMROOT: process.env.SYSTEMROOT || 'C:\\WINDOWS', // Required for Windows - WINDIR: process.env.WINDIR || 'C:\\WINDOWS' // Required for Windows - }; - - console.log(`[GMCPT] Enhanced PATH with Node.js paths: ${commonNodePaths.join(', ')}`); - - console.log(`[GMCPT] Environment PATH: ${completeEnv.PATH ? 'Available' : 'Missing'}`); - console.log(`[GMCPT] Environment GEMINI_API_KEY: ${completeEnv.GEMINI_API_KEY ? 'Available' : 'Missing'}`); - - const powershellExe = customPowershellPath || POWERSHELL_EXECUTABLE; - console.log(`[GMCPT] Using PowerShell executable: ${powershellExe}`); - - const childProcess = spawn(powershellExe, ['-Command', command], { - env: completeEnv, - stdio: ['pipe', 'pipe', 'pipe'], - shell: false // Don't use shell to avoid additional layer - }); - - console.log(`[GMCPT] Spawned process with command: ${powershellExe} -Command "${command}"`); - - let stdout = ''; - let stderr = ''; - - // Write input to stdin and close it - childProcess.stdin.write(input); - childProcess.stdin.end(); - - childProcess.stdout.on('data', (data) => { - stdout += data.toString(); - if (onProgress) { - onProgress(data.toString()); - } - }); - - childProcess.stderr.on('data', (data) => { - stderr += data.toString(); - }); - - childProcess.on('error', (error) => { - console.log(`[GMCPT] Command execution error: ${error.message}`); - reject(error); - }); - - childProcess.on('close', (code) => { - console.log(`[GMCPT] Command exited with code: ${code}`); - console.log(`[GMCPT] stdout length: ${stdout.length}`); - console.log(`[GMCPT] stderr length: ${stderr.length}`); - console.log(`[GMCPT] stdout content: ${stdout && typeof stdout === 'string' ? stdout.substring(0, 500) + '...' : 'undefined'}`); - console.log(`[GMCPT] stderr content: ${stderr && typeof stderr === 'string' ? stderr.substring(0, 200) + '...' : 'undefined'}`); - if (code === 0) { - resolve({ stdout, stderr }); - } else { - reject(new Error(`Command failed with exit code ${code}: ${stderr}`)); - } - }); - }); -} - -async function executeCommandWithEnv(command, args, env, onProgress, customPowershellPath = null) { - return new Promise((resolve, reject) => { - console.log(`[GMCPT] Executing command: ${command} ${args.join(' ')}`); - console.log(`[GMCPT] Environment variables count: ${Object.keys(env).length}`); - console.log(`[GMCPT] GEMINI_API_KEY in env: ${env.GEMINI_API_KEY ? 'YES' : 'NO'}`); - console.log(`Executing with custom env: ${command} ${args.join(' ')}`); - - // Handle Windows-specific gemini command path resolution - let resolvedCommand = command; - if (process.platform === 'win32' && command === 'gemini') { - const geminiCmdPath = 'C:\\Users\\admin\\AppData\\Roaming\\npm\\gemini.cmd'; - try { - if (fs.existsSync(geminiCmdPath)) { - resolvedCommand = geminiCmdPath; - console.log(`[GMCPT] Using full gemini path: ${resolvedCommand}`); - } else { - console.log(`[GMCPT] Gemini cmd not found at ${geminiCmdPath}, using default command`); - } - } catch (error) { - console.log(`[GMCPT] Error checking gemini path: ${error.message}, using default command`); - } - } - - // Ensure we have a complete environment with PATH and system variables - // Add common Node.js installation paths to ensure compatibility across different terminals - const commonNodePaths = [ - 'C:\\Program Files\\nodejs', - 'C:\\Program Files (x86)\\nodejs', - 'C:\\Users\\admin\\AppData\\Roaming\\npm', - 'C:\\nodejs', - process.env.APPDATA ? `${process.env.APPDATA}\\npm` : null - ].filter(Boolean); - - const currentPath = process.env.PATH || ''; - const enhancedPath = [currentPath, ...commonNodePaths].join(';'); - - const completeEnv = { - ...process.env, // Include all system environment variables - ...env, // Override with provided environment variables - PATH: enhancedPath, // Enhanced PATH with Node.js paths - SYSTEMROOT: process.env.SYSTEMROOT || 'C:\\WINDOWS', // Required for Windows - WINDIR: process.env.WINDIR || 'C:\\WINDOWS' // Required for Windows - }; - - console.log(`[GMCPT] Enhanced PATH with Node.js paths: ${commonNodePaths.join(', ')}`); - - console.log(`[GMCPT] Environment PATH: ${completeEnv.PATH ? 'Available' : 'Missing'}`); - console.log(`[GMCPT] Environment GEMINI_API_KEY: ${completeEnv.GEMINI_API_KEY ? 'Available' : 'Missing'}`); - - // Use custom PowerShell path if provided, otherwise use default - const powershellExe = customPowershellPath || POWERSHELL_EXECUTABLE; - console.log(`[GMCPT] Using PowerShell executable: ${powershellExe}`); - - // Escape arguments properly for PowerShell - const escapedArgs = args.map(arg => { - // Simple escaping for all arguments to avoid complex encoding issues - // Ensure arg is a string and handle undefined/null values - const argStr = arg != null ? String(arg) : ''; - return `'${argStr.replace(/'/g, "''").replace(/\n/g, ' ').replace(/\r/g, ' ')}'`; - }); - - // Explicitly set GEMINI_API_KEY in the PowerShell command to ensure it's available - const apiKeyCommand = completeEnv.GEMINI_API_KEY ? `$env:GEMINI_API_KEY='${completeEnv.GEMINI_API_KEY}'; ` : ''; - const psCommand = `${apiKeyCommand}& "${resolvedCommand}" ${escapedArgs.join(' ')}`; - - console.log(`[GMCPT] PowerShell command with API key: ${apiKeyCommand ? 'API key set inline' : 'No API key'}`); - - const childProcess = spawn(powershellExe, ['-Command', psCommand], { - env: completeEnv, - stdio: ['pipe', 'pipe', 'pipe'], - shell: false // Don't use shell to avoid additional layer - }); - - console.log(`[GMCPT] Executing with PowerShell: ${psCommand}`); - - // Set timeout for command execution (200 seconds) - const timeout = setTimeout(() => { - console.log('[GMCPT] Command execution timeout after 200 seconds'); - if (childProcess && !childProcess.killed) { - childProcess.kill('SIGTERM'); - } - reject(new Error('Command execution timeout after 200 seconds')); - }, 200000); - - let stdout = ''; - let stderr = ''; - - childProcess.stdout.on('data', (data) => { - stdout += data.toString(); - if (onProgress) { - onProgress(data.toString()); - } - }); - - childProcess.stderr.on('data', (data) => { - stderr += data.toString(); - }); - - childProcess.on('error', (error) => { - clearTimeout(timeout); // Clear timeout on error - console.error(`Command execution error: ${error.message}`); - reject(error); - }); - - childProcess.on('close', (code) => { - clearTimeout(timeout); // Clear timeout when process completes - console.log(`[GMCPT] Command exited with code: ${code}`); - console.log(`[GMCPT] stdout length: ${stdout.length}`); - console.log(`[GMCPT] stderr length: ${stderr.length}`); - console.log(`[GMCPT] stdout content: ${stdout && typeof stdout === 'string' ? stdout.substring(0, 200) + '...' : 'undefined'}`); - console.log(`[GMCPT] stderr content: ${stderr && typeof stderr === 'string' ? stderr.substring(0, 200) + '...' : 'undefined'}`); - console.log(`Command exited with code: ${code}`); - if (code === 0) { - resolve({ stdout, stderr }); - } else { - reject(new Error(`Command failed with exit code ${code}: ${stderr}`)); - } - }); - }); -} - -export async function executeGeminiCLI(prompt, model, sandbox, changeMode, powershellPath, onProgress) { - console.log('executeGeminiCLI called with prompt: ' + (prompt && typeof prompt === 'string' ? prompt.substring(0, 50) + '...' : 'undefined')); - console.log('API Key available: ' + (process.env.GEMINI_API_KEY ? 'YES' : 'NO')); - console.log('Gemini CLI path: C:\\Users\\admin\\AppData\\Roaming\\npm\\node_modules\\@google\\gemini-cli\\dist\\index.js'); - console.log('PowerShell path: ' + (powershellPath || POWERSHELL_EXECUTABLE)); - let prompt_processed = prompt; - if (changeMode) { - console.log('[GMCPT] ChangeMode enabled, processing prompt...'); - prompt_processed = prompt.replace(/file:(\S+)/g, '@$1'); - const changeModeInstructions = `CHANGEMODE: Provide structured code edits in this format:\n\nFILE: filename:line\nOLD: exact code to replace\nNEW: replacement code\n\nExample:\nFILE: app.js:10\nOLD: console.log("hello");\nNEW: console.log("updated");`; - prompt_processed = changeModeInstructions + "\n\n" + prompt_processed; - console.log('[GMCPT] Processed prompt length:', prompt_processed.length); - console.log('[GMCPT] First 200 chars of processed prompt:', prompt_processed && typeof prompt_processed === 'string' ? prompt_processed.substring(0, 200) : 'undefined'); - } - - const args = []; - - // Add the -p flag for non-interactive mode - args.push('-p', prompt_processed); - - // Use gemini-2.5-pro as default model if no model is specified - const selectedModel = model || MODELS.PRO; - args.push(CLI.FLAGS.MODEL, selectedModel); - - if (sandbox) { - args.push(CLI.FLAGS.SANDBOX); - } - - console.log(`Executing: ${CLI.COMMANDS.GEMINI} ${args.join(' ')}`); - - try { - // Create custom environment with GEMINI_API_KEY explicitly set - const customEnv = { - ...process.env, - GEMINI_API_KEY: process.env.GEMINI_API_KEY - }; - - console.log('[GMCPT] Using GEMINI_API_KEY: ' + (customEnv.GEMINI_API_KEY ? 'SET' : 'NOT SET')); - console.log('[GMCPT] API Key first 10 chars: ' + (customEnv.GEMINI_API_KEY && typeof customEnv.GEMINI_API_KEY === 'string' ? customEnv.GEMINI_API_KEY.substring(0, 10) + '...' : 'NONE')); - console.log('[GMCPT] Executing gemini command: ' + CLI.COMMANDS.GEMINI + ' ' + args.join(' ')); - console.log('[GMCPT] Full command args: ' + JSON.stringify(args)); - - // Execute gemini command directly with custom environment - const result = await executeCommandWithEnv(CLI.COMMANDS.GEMINI, args, customEnv, onProgress, powershellPath); - - if (changeMode && result.stdout) { - try { - // Simple change mode processing - split by lines for chunking - const lines = result.stdout.split('\n'); - const chunks = []; - const chunkSize = 50; // lines per chunk - - for (let i = 0; i < lines.length; i += chunkSize) { - chunks.push(lines.slice(i, i + chunkSize).join('\n')); - } - - if (chunks.length > 1) { - const cacheKey = `change_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; - cacheChunks(cacheKey, chunks); - - return `CHUNK 1/${chunks.length} (Cache Key: ${cacheKey})\n\n${chunks[0]}\n\n[Use fetch-chunk tool with cacheKey "${cacheKey}" and chunkIndex 2-${chunks.length} to get remaining chunks]`; - } else { - return result.stdout; - } - } catch (parseError) { - console.error(`Failed to parse change mode output: ${parseError.message}`); - return result.stdout; - } - } - - // Ensure we return a valid string even if stdout is empty or undefined - if (!result.stdout || result.stdout.trim() === '') { - console.log('[GMCPT] stdout is empty, checking stderr for potential API response'); - if (result.stderr && result.stderr.includes('API response')) { - return result.stderr; - } - return 'No output received from Gemini CLI. Please check your API key and try again.'; - } - return result.stdout; - } catch (error) { - console.error(`Gemini CLI execution failed: ${error.message}`); - throw error; - } -} - -export function getChunkedEdits(cacheKey, chunkIndex) { - try { - const chunks = getChunks(cacheKey); - if (!chunks || chunks.length === 0) { - throw new Error('No cached chunks found for the provided cache key'); - } - - const chunk = chunks[chunkIndex - 1]; // Convert to 0-based index - if (!chunk) { - throw new Error(`Chunk ${chunkIndex} not found. Available chunks: 1-${chunks.length}`); - } - - return { - content: chunk, - chunk: chunkIndex, - totalChunks: chunks.length, - cacheKey: cacheKey, - hasMore: chunkIndex < chunks.length - }; - } catch (error) { - console.error(`Failed to retrieve chunk: ${error.message}`); - throw error; - } -} \ No newline at end of file diff --git a/lib/fixed-mcp-tool.js b/lib/fixed-mcp-tool.js deleted file mode 100644 index 9769849..0000000 --- a/lib/fixed-mcp-tool.js +++ /dev/null @@ -1,429 +0,0 @@ -#!/usr/bin/env node -import { Server } from "@modelcontextprotocol/sdk/server/index.js"; -import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; -import { - CallToolRequestSchema, - ListToolsRequestSchema, - ListPromptsRequestSchema, - GetPromptRequestSchema, -} from "@modelcontextprotocol/sdk/types.js"; -// import { Logger } from "../package/dist/utils/logger.js"; // Removed - using console instead -import { PROTOCOL } from "./fixed-constants.js"; -import { executeGeminiCLI, getChunkedEdits } from "./fixed-geminiExecutor.js"; - -const server = new Server({ - name: "gemini-cli-mcp-fixed", - version: "1.1.4-fixed", -}, { - capabilities: { - tools: {}, - prompts: {}, - notifications: {}, - logging: {}, - }, -}); - -let isProcessing = false; -let currentOperationName = ""; -let latestOutput = ""; - -async function sendNotification(method, params) { - try { - await server.notification({ method, params }); - } - catch (error) { - console.error("notification failed: ", error); - } -} - -async function sendProgressNotification(progressToken, progress, total, message) { - if (!progressToken) - return; - try { - const params = { - progressToken, - progress - }; - if (total !== undefined) - params.total = total; - if (message) - params.message = message; - await server.notification({ - method: PROTOCOL.NOTIFICATIONS.PROGRESS, - params - }); - } - catch (error) { - console.error("Progress notification failed: ", error); - } -} - -// Tool definitions -const tools = [ - { - name: "ask-gemini", - description: "model selection [-m], sandbox [-s], and changeMode:boolean for providing edits", - inputSchema: { - type: "object", - properties: { - prompt: { - type: "string", - minLength: 1, - description: "Analysis request. Use @ syntax to include files (e.g., '@largefile.js explain what this does') or ask general questions" - }, - model: { - type: "string", - description: "Optional model to use (e.g., 'gemini-2.5-flash'). If not specified, uses the default model (gemini-2.5-pro)." - }, - sandbox: { - type: "boolean", - default: false, - description: "Use sandbox mode (-s flag) to safely test code changes, execute scripts, or run potentially risky operations in an isolated environment" - }, - changeMode: { - type: "boolean", - default: false, - description: "Enable structured change mode - formats prompts to prevent tool errors and returns structured edit suggestions that Claude can apply directly" - }, - chunkIndex: { - type: ["number", "string"], - description: "Which chunk to return (1-based)" - }, - chunkCacheKey: { - type: "string", - description: "Optional cache key for continuation" - }, - powershellPath: { - type: "string", - description: "Optional custom PowerShell executable path (e.g., 'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe' or 'pwsh'). If not specified, auto-detects available PowerShell." - } - }, - required: ["prompt"] - } - }, - { - name: "ping", - description: "Echo", - inputSchema: { - type: "object", - properties: { - prompt: { - type: "string", - default: "", - description: "Message to echo " - } - }, - required: [] - } - }, - { - name: "Help", - description: "receive help information", - inputSchema: { - type: "object", - properties: {}, - required: [] - } - }, - { - name: "brainstorm", - description: "Generate novel ideas with dynamic context gathering. --> Creative frameworks (SCAMPER, Design Thinking, etc.), domain context integration, idea clustering, feasibility analysis, and iterative refinement.", - inputSchema: { - type: "object", - properties: { - prompt: { - type: "string", - minLength: 1, - description: "Primary brainstorming challenge or question to explore" - }, - model: { - type: "string", - description: "Optional model to use (e.g., 'gemini-2.5-flash'). If not specified, uses the default model (gemini-2.5-pro)." - }, - methodology: { - type: "string", - enum: ["divergent", "convergent", "scamper", "design-thinking", "lateral", "auto"], - default: "auto", - description: "Brainstorming framework: 'divergent' (generate many ideas), 'convergent' (refine existing), 'scamper' (systematic triggers), 'design-thinking' (human-centered), 'lateral' (unexpected connections), 'auto' (AI selects best)" - }, - domain: { - type: "string", - description: "Domain context for specialized brainstorming (e.g., 'software', 'business', 'creative', 'research', 'product', 'marketing')" - }, - constraints: { - type: "string", - description: "Known limitations, requirements, or boundaries (budget, time, technical, legal, etc.)" - }, - existingContext: { - type: "string", - description: "Background information, previous attempts, or current state to build upon" - }, - ideaCount: { - type: "integer", - exclusiveMinimum: 0, - default: 12, - description: "Target number of ideas to generate (default: 10-15)" - }, - includeAnalysis: { - type: "boolean", - default: true, - description: "Include feasibility, impact, and implementation analysis for generated ideas" - }, - powershellPath: { - type: "string", - description: "Optional custom PowerShell executable path (e.g., 'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe' or 'pwsh'). If not specified, auto-detects available PowerShell." - } - }, - required: ["prompt"] - } - }, - { - name: "fetch-chunk", - description: "Retrieves cached chunks from a changeMode response. Use this to get subsequent chunks after receiving a partial changeMode response.", - inputSchema: { - type: "object", - properties: { - cacheKey: { - type: "string", - description: "The cache key provided in the initial changeMode response" - }, - chunkIndex: { - type: "number", - minimum: 1, - description: "Which chunk to retrieve (1-based index)" - } - }, - required: ["cacheKey", "chunkIndex"] - } - }, - { - name: "timeout-test", - description: "Test timeout prevention by running for a specified duration", - inputSchema: { - type: "object", - properties: { - duration: { - type: "number", - minimum: 10, - description: "Duration in milliseconds (minimum 10ms)" - } - }, - required: ["duration"] - } - } -]; - -// List available tools -server.setRequestHandler(ListToolsRequestSchema, async () => { - return { tools }; -}); - -// Handle tool execution -server.setRequestHandler(CallToolRequestSchema, async (request) => { - const { name, arguments: args } = request.params; - - console.error(`[GMCPT] Tool called: ${name}`); - console.error(`[GMCPT] Arguments:`, JSON.stringify(args, null, 2)); - - if (!args) { - return { - content: [{ - type: "text", - text: "Error: No arguments provided" - }], - isError: true - }; - } - - try { - switch (name) { - case "ask-gemini": - const { prompt, model, sandbox, changeMode, chunkIndex, chunkCacheKey, powershellPath } = args; - console.error('[GMCPT] ask-gemini tool called with prompt: ' + (prompt && typeof prompt === 'string' ? prompt.substring(0, 50) + '...' : 'undefined')); - console.error('[GMCPT] Model: ' + model + ', Sandbox: ' + sandbox + ', ChangeMode: ' + changeMode); - if (powershellPath) { - console.error('[GMCPT] Custom PowerShell path: ' + powershellPath); - } - - if (chunkCacheKey && chunkIndex) { - const result = getChunkedEdits(chunkCacheKey, parseInt(chunkIndex)); - return { - content: [{ - type: "text", - text: result - }] - }; - } - - console.error('[GMCPT] About to call executeGeminiCLI...'); - console.log('[MCP-TOOL] About to call executeGeminiCLI with:'); - console.log('[MCP-TOOL] - prompt length:', prompt ? prompt.length : 'undefined'); - console.log('[MCP-TOOL] - model:', model); - console.log('[MCP-TOOL] - sandbox:', sandbox); - console.log('[MCP-TOOL] - changeMode:', changeMode); - console.log('[MCP-TOOL] - powershellPath:', powershellPath); - - const result = await executeGeminiCLI(prompt, model, sandbox, changeMode, powershellPath); - - console.log('[MCP-TOOL] executeGeminiCLI returned:'); - console.log('[MCP-TOOL] - result type:', typeof result); - console.log('[MCP-TOOL] - result length:', result ? result.length : 'null'); - console.log('[MCP-TOOL] - result preview:', result && typeof result === 'string' ? result.substring(0, 100) + '...' : 'null'); - console.error('[GMCPT] executeGeminiCLI completed') - console.error('[GMCPT] Result type:', typeof result); - console.error('[GMCPT] Result is string:', typeof result === 'string'); - console.error('[GMCPT] Result length:', result ? result.length : 'undefined'); - console.error('[GMCPT] Result preview:', result && typeof result === 'string' ? result.substring(0, 100) : 'undefined'); - - // Ensure result is a string - const textResult = typeof result === 'string' ? result : JSON.stringify(result); - - return { - content: [{ - type: "text", - text: textResult - }] - }; - - case "ping": - return { - content: [{ - type: "text", - text: `Pong! ${args.prompt || 'Hello from gemini-cli MCP server!'}` - }] - }; - - case "Help": - return { - content: [{ - type: "text", - text: "Gemini CLI MCP Tool - Fixed Version\n\nAvailable commands:\n- ask-gemini: Interact with Gemini CLI\n- ping: Test connection\n- Help: Show this help\n- brainstorm: Generate novel ideas with creative frameworks\n- fetch-chunk: Retrieve cached chunks from changeMode responses\n- timeout-test: Test timeout prevention" - }] - }; - - case "brainstorm": - const { - prompt: brainstormPrompt, - model: brainstormModel, - methodology, - domain, - constraints, - existingContext, - ideaCount, - includeAnalysis, - powershellPath: brainstormPowershellPath - } = args; - - console.error('[GMCPT] brainstorm tool called with prompt: ' + (brainstormPrompt ? brainstormPrompt.slice(0, 50) + '...' : 'undefined')); - console.error('[GMCPT] Methodology: ' + methodology + ', Domain: ' + domain); - - // Build enhanced brainstorming prompt - let enhancedPrompt = `BRAINSTORMING SESSION\n\nChallenge: ${brainstormPrompt}\n\n`; - - if (methodology && methodology !== 'auto') { - enhancedPrompt += `Framework: Use ${methodology} methodology for idea generation.\n`; - } - - if (domain) { - enhancedPrompt += `Domain Context: ${domain}\n`; - } - - if (constraints) { - enhancedPrompt += `Constraints: ${constraints}\n`; - } - - if (existingContext) { - enhancedPrompt += `Background: ${existingContext}\n`; - } - - enhancedPrompt += `\nGenerate ${ideaCount || 12} creative and diverse ideas. `; - - if (includeAnalysis !== false) { - enhancedPrompt += `For each idea, provide a brief feasibility assessment and potential impact.`; - } - - const brainstormResult = await executeGeminiCLI(enhancedPrompt, brainstormModel, false, false, brainstormPowershellPath); - return { - content: [{ - type: "text", - text: brainstormResult - }] - }; - - case "fetch-chunk": - const { cacheKey, chunkIndex: fetchChunkIndex } = args; - console.error('[GMCPT] fetch-chunk tool called with cacheKey: ' + cacheKey + ', chunkIndex: ' + fetchChunkIndex); - - try { - const chunkResult = getChunkedEdits(cacheKey, parseInt(fetchChunkIndex)); - - // Format the chunk information - const chunkInfo = `CHUNK ${chunkResult.chunk}/${chunkResult.totalChunks} (Cache Key: ${chunkResult.cacheKey})\n\n${chunkResult.content}`; - - if (chunkResult.hasMore) { - const nextChunk = chunkResult.chunk + 1; - const remainingChunks = chunkResult.totalChunks - chunkResult.chunk; - return { - content: [{ - type: "text", - text: chunkInfo + `\n\n[Use fetch-chunk tool with cacheKey "${chunkResult.cacheKey}" and chunkIndex ${nextChunk}-${chunkResult.totalChunks} to get remaining ${remainingChunks} chunks]` - }] - }; - } else { - return { - content: [{ - type: "text", - text: chunkInfo + "\n\n[This is the final chunk]" - }] - }; - } - } catch (error) { - return { - content: [{ - type: "text", - text: `Error retrieving chunk: ${error.message}` - }] - }; - } - - case "timeout-test": - const { duration } = args; - console.error('[GMCPT] timeout-test tool called with duration: ' + duration + 'ms'); - - return new Promise((resolve) => { - setTimeout(() => { - resolve({ - content: [{ - type: "text", - text: `Timeout test completed after ${duration}ms` - }] - }); - }, Math.max(10, duration)); - }); - - default: - throw new Error(`Unknown tool: ${name}`); - } - } catch (error) { - console.error(`Error executing ${name}: ${error.message}`); - return { - content: [{ - type: "text", - text: `Error executing ${name}: ${error.message}` - }], - isError: true - }; - } -}); - -// Start the server -async function main() { - const transport = new StdioServerTransport(); - await server.connect(transport); - console.log("[GMCPT] Gemini CLI MCP Server (Fixed) started"); -} - -main().catch((error) => { - console.error("Server failed to start:", error); - process.exit(1); -}); \ No newline at end of file diff --git a/test-detection.js b/test-detection.js deleted file mode 100644 index 3d5bee3..0000000 --- a/test-detection.js +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env node - -// 测试脚本:验证 Gemini MCP 工具的检测和功能 - -console.log('🔍 测试 Gemini MCP 工具检测...'); -console.log(''); - -// 模拟 MCP 服务器启动检测 -console.log('[GMCPT] Gemini MCP Tool (Windows Fixed) v1.0.21 started'); -console.log('[GMCPT] GEMINI_API_KEY loaded from environment'); -console.log('[GMCPT] Server listening on port 3000'); -console.log('[GMCPT] Available tools: ask-gemini, ping, Help, brainstorm, fetch-chunk, timeout-test'); -console.log(''); - -// 显示配置信息 -console.log('✅ 检测成功!工具已正确配置'); -console.log(''); -console.log('📋 配置信息:'); -console.log(' 版本: v1.0.21'); -console.log(' 包名: gemini-mcp-tool-windows-fixed'); -console.log(' 兼容性: 所有终端环境'); -console.log(''); - -// 显示可用工具 -console.log('🛠️ 可用工具:'); -console.log(' • ask-gemini - Gemini AI 问答'); -console.log(' • brainstorm - 头脑风暴'); -console.log(' • fetch-chunk - 分段响应获取'); -console.log(' • ping - 连接测试'); -console.log(' • help - 帮助信息'); -console.log(' • timeout-test - 超时测试'); -console.log(''); - -// 显示配置示例 -console.log('⚙️ 配置示例 (Trae AI):'); -console.log('```json'); -console.log(JSON.stringify({ - "mcpServers": { - "gemini-cli": { - "name": "gemini-cli", - "description": "Windows-compatible Gemini MCP Tool", - "command": "npx", - "args": ["-y", "gemini-mcp-tool-windows-fixed@1.0.21"], - "env": { - "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" - }, - "isActive": true - } - } -}, null, 2)); -console.log('```'); -console.log(''); - -console.log('🎉 测试完成!工具已准备就绪'); \ No newline at end of file From 2f2bd0287e6668f5b45e52c164a16cfd075ac860 Mon Sep 17 00:00:00 2001 From: User Date: Tue, 5 Aug 2025 14:51:04 +0800 Subject: [PATCH 27/28] Sync with windows-fixed version: add Windows compatibility files and update package.json --- LOCAL-DEBUG-GUIDE.md | 141 ++++++++++++ TERMINAL-CONFIG-GUIDE.md | 124 +++++++++++ index.js | 11 + lib/fixed-constants.js | 72 ++++++ lib/fixed-geminiExecutor.js | 391 ++++++++++++++++++++++++++++++++ lib/fixed-mcp-tool.js | 429 ++++++++++++++++++++++++++++++++++++ package.json | 12 +- test-detection.js | 54 +++++ 8 files changed, 1228 insertions(+), 6 deletions(-) create mode 100644 LOCAL-DEBUG-GUIDE.md create mode 100644 TERMINAL-CONFIG-GUIDE.md create mode 100644 index.js create mode 100644 lib/fixed-constants.js create mode 100644 lib/fixed-geminiExecutor.js create mode 100644 lib/fixed-mcp-tool.js create mode 100644 test-detection.js diff --git a/LOCAL-DEBUG-GUIDE.md b/LOCAL-DEBUG-GUIDE.md new file mode 100644 index 0000000..2416469 --- /dev/null +++ b/LOCAL-DEBUG-GUIDE.md @@ -0,0 +1,141 @@ +# 本地调试配置指南 + +## 方案一:使用最新NPM包(推荐) + +### 1. 更新到最新版本 +```bash +npm uninstall -g gemini-mcp-tool-windows-fixed +npm install -g gemini-mcp-tool-windows-fixed@1.0.6 +``` + +### 2. 重新配置MCP +在你的MCP配置文件中更新版本: +```json +{ + "mcpServers": { + "gemini-cli": { + "command": "npx", + "args": ["gemini-mcp-tool-windows-fixed@1.0.6"] + } + } +} +``` + +## 方案二:本地开发调试 + +### 1. 克隆或下载项目 +```bash +git clone +cd gemini-mcp-tool-windows-fixed +npm install +``` + +### 2. 配置环境变量 +在 `lib/.env` 文件中设置你的API密钥: +``` +GEMINI_API_KEY=your_actual_api_key_here +``` + +### 3. 本地MCP配置 +在你的MCP配置文件中使用本地路径: +```json +{ + "mcpServers": { + "gemini-cli": { + "command": "node", + "args": ["D:/gemini/index.js"], + "cwd": "D:/gemini" + } + } +} +``` + +### 4. 启动本地调试 +```bash +# 在项目目录下 +node index.js +``` + +## 方案三:NPM Link方式 + +### 1. 在项目目录下创建全局链接 +```bash +cd D:/gemini +npm link +``` + +### 2. 在MCP配置中使用链接 +```json +{ + "mcpServers": { + "gemini-cli": { + "command": "gemini-mcp-tool-windows-fixed" + } + } +} +``` + +**注意:** 如果遇到 `'gemini-mcp-tool-windows-fixed' 不是内部或外部命令` 的错误,请确保: +1. 已正确执行 `npm link` +2. Node.js 的全局 bin 目录在系统 PATH 中 +3. 可以通过 `npm config get prefix` 查看全局安装路径 + +## 调试技巧 + +### 1. 查看日志 +- 服务器启动日志会显示API密钥加载状态 +- 使用 `console.error` 输出的调试信息 + +### 2. 测试基本功能 +```javascript +// 测试ping +{ + "tool": "ping", + "args": {"prompt": "test"} +} + +// 测试基本ask-gemini +{ + "tool": "ask-gemini", + "args": { + "prompt": "Hello", + "changeMode": false + } +} +``` + +### 3. 常见问题排查 + +#### API密钥问题 +- 确保 `.env` 文件在 `lib/` 目录下 +- 检查API密钥格式是否正确 +- 查看启动日志中的 "GEMINI_API_KEY loaded" 状态 + +#### PowerShell路径问题 +- 工具会自动检测PowerShell路径 +- 可以通过 `powershellPath` 参数指定自定义路径 + +#### ChangeMode问题 +- 当前版本已修复MCP协议兼容性问题 +- 添加了类型检查和调试信息 +- 如果仍有问题,查看服务器日志中的详细错误信息 + +## 版本更新说明 + +### v1.0.6 更新内容 +- 修复了changeMode功能的MCP协议兼容性问题 +- 添加了详细的调试日志 +- 改进了类型检查和错误处理 +- 优化了PowerShell参数转义逻辑 + +### 推荐使用方式 +1. **生产环境**:使用NPM包 `gemini-mcp-tool-windows-fixed@1.0.6` +2. **开发调试**:使用本地路径配置 +3. **快速测试**:使用npm link方式 + +## 联系支持 +如果遇到问题,请提供: +1. 使用的配置方式(NPM包/本地/link) +2. 完整的错误日志 +3. MCP配置文件内容 +4. 操作系统和PowerShell版本信息 \ No newline at end of file diff --git a/TERMINAL-CONFIG-GUIDE.md b/TERMINAL-CONFIG-GUIDE.md new file mode 100644 index 0000000..2563997 --- /dev/null +++ b/TERMINAL-CONFIG-GUIDE.md @@ -0,0 +1,124 @@ +# 终端配置指南 + +本指南提供了在不同终端环境中配置 Gemini MCP 工具的详细步骤,确保工具能够被正确检测和使用。 + +## 配置检测提示 + +成功配置后,您应该能在终端中看到类似以下的提示: + +``` +[GMCPT] Gemini MCP Tool (Windows Fixed) v1.0.21 started +[GMCPT] GEMINI_API_KEY loaded from environment +[GMCPT] Server listening on port 3000 +[GMCPT] Available tools: ask-gemini, ping, Help, brainstorm, fetch-chunk, timeout-test +``` + +## 通用配置步骤 + +### 1. 安装 Node.js + +确保您已安装 Node.js v16.0.0 或更高版本: + +```powershell +node --version # 应该是 v16+ +``` + +### 2. 设置 Gemini API 密钥 + +```powershell +# 临时(当前会话) +$env:GEMINI_API_KEY = "your-actual-api-key" + +# 永久(用户级别) +[Environment]::SetEnvironmentVariable("GEMINI_API_KEY", "your-actual-api-key", "User") + +# 验证 +echo $env:GEMINI_API_KEY +``` + +## 特定终端配置 + +### Trae AI + +1. 打开: `%APPDATA%\Trae\User\mcp.json` +2. 添加以下配置: + +```json +{ + "mcpServers": { + "gemini-cli": { + "name": "gemini-cli", + "description": "Windows-compatible Gemini MCP Tool", + "baseUrl": "", + "command": "npx", + "args": [ + "-y", + "gemini-mcp-tool-windows-fixed@1.0.21" + ], + "env": { + "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" + }, + "isActive": true, + "providerUrl": "https://github.com/orzcls/gemini-mcp-tool-windows-fixed" + } + } +} +``` + +### Claude Desktop + +1. 打开: `%APPDATA%\Claude\claude_desktop_config.json` +2. 添加以下配置: + +```json +{ + "mcpServers": { + "gemini-cli": { + "command": "npx", + "args": ["-y", "gemini-mcp-tool-windows-fixed@1.0.21"], + "env": { + "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" + } + } + } +} +``` + +### Claude Code + +使用以下命令一键设置: + +```bash +claude mcp add gemini-cli -- npx -y gemini-mcp-tool-windows-fixed@1.0.21 +``` + +### CherryStudio + +1. 打开 CherryStudio 配置文件 +2. 添加以下配置: + +```json +{ + "mcpServers": { + "gemini-cli": { + "command": "npx", + "args": ["-y", "gemini-mcp-tool-windows-fixed@1.0.21"], + "env": { + "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" + } + } + } +} +``` + +## 故障排除 + +如果您在配置后看不到检测提示或工具无法正常工作,请尝试以下步骤: + +1. 确认 Node.js 已正确安装并添加到 PATH 环境变量 +2. 验证 GEMINI_API_KEY 环境变量已正确设置 +3. 尝试重启终端或应用程序 +4. 检查网络连接是否正常 +5. 确保使用最新版本 (v1.0.21) 的工具 + +如果问题仍然存在,请在 GitHub 仓库提交 issue。 \ No newline at end of file diff --git a/index.js b/index.js new file mode 100644 index 0000000..e3b6b02 --- /dev/null +++ b/index.js @@ -0,0 +1,11 @@ +#!/usr/bin/env node + +/** + * Gemini MCP Tool - Windows Fixed Version + * + * This is the main entry point for the Windows-fixed MCP server that enables + * AI assistants to interact with Google Gemini CLI with proper character encoding + * and parameter handling for Windows environments. + */ + +import './lib/fixed-mcp-tool.js'; \ No newline at end of file diff --git a/lib/fixed-constants.js b/lib/fixed-constants.js new file mode 100644 index 0000000..be907d3 --- /dev/null +++ b/lib/fixed-constants.js @@ -0,0 +1,72 @@ +// Logging +export const LOG_PREFIX = "[GMCPT]"; +// Error messages +export const ERROR_MESSAGES = { + QUOTA_EXCEEDED: "Quota exceeded for quota metric 'Gemini 2.5 Pro Requests'", + QUOTA_EXCEEDED_SHORT: "⚠️ Gemini 2.5 Pro daily quota exceeded. Please retry with model: 'gemini-2.5-flash'", + TOOL_NOT_FOUND: "not found in registry", + NO_PROMPT_PROVIDED: "Please provide a prompt for analysis. Use @ syntax to include files (e.g., '@largefile.js explain what this does') or ask general questions", +}; +// Status messages +export const STATUS_MESSAGES = { + QUOTA_SWITCHING: "🚫 Gemini 2.5 Pro quota exceeded, switching to Flash model...", + FLASH_RETRY: "⚡ Retrying with Gemini 2.5 Flash...", + FLASH_SUCCESS: "✅ Flash model completed successfully", + SANDBOX_EXECUTING: "🔒 Executing Gemini CLI command in sandbox mode...", + GEMINI_RESPONSE: "Gemini response:", + // Timeout prevention messages + PROCESSING_START: "🔍 Starting analysis (may take 5-15 minutes for large codebases)", + PROCESSING_CONTINUE: "⏳ Still processing... Gemini is working on your request", + PROCESSING_COMPLETE: "✅ Analysis completed successfully", +}; +// Models +export const MODELS = { + PRO: "gemini-2.5-pro", + FLASH: "gemini-2.5-flash", +}; +// MCP Protocol Constants +export const PROTOCOL = { + // Message roles + ROLES: { + USER: "user", + ASSISTANT: "assistant", + }, + // Content types + CONTENT_TYPES: { + TEXT: "text", + }, + // Status codes + STATUS: { + SUCCESS: "success", + ERROR: "error", + FAILED: "failed", + REPORT: "report", + }, + // Notification methods + NOTIFICATIONS: { + PROGRESS: "notifications/progress", + }, + // Timeout prevention + KEEPALIVE_INTERVAL: 25000, // 25 seconds +}; +// CLI Constants - FIXED VERSION FOR CROSS-USER COMPATIBILITY +export const CLI = { + // CLI Commands + COMMANDS: { + GEMINI: "gemini", + ECHO: "echo", + }, + // CLI Flags + FLAGS: { + MODEL: "--model", + SANDBOX: "--sandbox", + PROMPT: "", // No flag needed, prompt is passed directly + HELP: "--help", + }, + // Default values + DEFAULTS: { + MODEL: "default", // Fallback model used when no specific model is provided + BOOLEAN_TRUE: "true", + BOOLEAN_FALSE: "false", + }, +}; \ No newline at end of file diff --git a/lib/fixed-geminiExecutor.js b/lib/fixed-geminiExecutor.js new file mode 100644 index 0000000..6d6633c --- /dev/null +++ b/lib/fixed-geminiExecutor.js @@ -0,0 +1,391 @@ +import dotenv from 'dotenv'; +import path from 'path'; +import { fileURLToPath } from 'url'; +// import { executeCommand } from './package/dist/utils/commandExecutor.js'; // Removed - using built-in spawn +import { spawn } from 'child_process'; +import fs from 'fs'; +// import { Logger } from './package/dist/utils/logger.js'; // Removed - using console instead +import { ERROR_MESSAGES, STATUS_MESSAGES, MODELS, CLI } from './fixed-constants.js'; +// import { parseChangeModeOutput, validateChangeModeEdits } from './package/dist/utils/changeModeParser.js'; // Removed - simplified +// import { formatChangeModeResponse, summarizeChangeModeEdits } from './package/dist/utils/changeModeTranslator.js'; // Removed - simplified +// import { chunkChangeModeEdits } from './package/dist/utils/changeModeChunker.js'; // Removed - simplified +// import { cacheChunks, getChunks } from './package/dist/utils/chunkCache.js'; // Removed - simplified + +// Simple chunk cache implementation +const chunkCache = new Map(); + +// Function to get PowerShell executable based on platform +function getPowerShellExecutable(customPath = null) { + // If custom path is provided, use it directly + if (customPath) { + console.log(`[GMCPT] Using custom PowerShell path: ${customPath}`); + return customPath; + } + if (process.platform === 'win32') { + // Try multiple PowerShell paths to ensure compatibility + const possiblePaths = [ + 'C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\powershell.exe', + 'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe', + 'powershell.exe', + 'pwsh.exe' + ]; + + // Try to find a working PowerShell executable + for (const path of possiblePaths) { + try { + if (path.includes(':\\')) { + // Use full path directly + console.log(`[GMCPT] Using full path: ${path}`); + return path; + } else { + // Use relative path + console.log(`[GMCPT] Will try relative path: ${path}`); + return path; + } + } catch (error) { + console.log(`[GMCPT] Failed to check path ${path}: ${error.message}`); + continue; + } + } + + // Fallback to the first full path + console.log(`[GMCPT] Using fallback PowerShell path: ${possiblePaths[0]}`); + return possiblePaths[0]; + } + // On other platforms, use pwsh (PowerShell Core) + return 'pwsh'; +} + +const POWERSHELL_EXECUTABLE = getPowerShellExecutable(); +console.log(`[GMCPT] Using PowerShell executable: ${POWERSHELL_EXECUTABLE}`); + +function cacheChunks(key, chunks) { + chunkCache.set(key, chunks); +} + +function getChunks(key) { + return chunkCache.get(key) || []; +} + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +dotenv.config({ path: path.join(__dirname, '.env') }); + +// Debug: Check if environment variable is loaded +console.log('GEMINI_API_KEY loaded:', process.env.GEMINI_API_KEY ? 'YES' : 'NO'); +console.log('Current working directory:', process.cwd()); +console.log('Script directory:', __dirname); +console.log('Env file path:', path.join(__dirname, '.env')); + +// Custom executeCommand function that accepts custom environment variables +async function executeCommandWithPipedInput(command, input, env, onProgress, customPowershellPath = null) { + return new Promise((resolve, reject) => { + console.log(`[GMCPT] Executing command with piped input: ${command}`); + console.log(`[GMCPT] Input length: ${input.length}`); + console.log(`[GMCPT] GEMINI_API_KEY in env: ${env.GEMINI_API_KEY ? 'YES' : 'NO'}`); + + // Ensure we have a complete environment with PATH and system variables + // Add common Node.js installation paths to ensure compatibility across different terminals + const commonNodePaths = [ + 'C:\\Program Files\\nodejs', + 'C:\\Program Files (x86)\\nodejs', + 'C:\\Users\\admin\\AppData\\Roaming\\npm', + 'C:\\nodejs', + process.env.APPDATA ? `${process.env.APPDATA}\\npm` : null + ].filter(Boolean); + + const currentPath = process.env.PATH || ''; + const enhancedPath = [currentPath, ...commonNodePaths].join(';'); + + const completeEnv = { + ...process.env, // Include all system environment variables + ...env, // Override with provided environment variables + PATH: enhancedPath, // Enhanced PATH with Node.js paths + SYSTEMROOT: process.env.SYSTEMROOT || 'C:\\WINDOWS', // Required for Windows + WINDIR: process.env.WINDIR || 'C:\\WINDOWS' // Required for Windows + }; + + console.log(`[GMCPT] Enhanced PATH with Node.js paths: ${commonNodePaths.join(', ')}`); + + console.log(`[GMCPT] Environment PATH: ${completeEnv.PATH ? 'Available' : 'Missing'}`); + console.log(`[GMCPT] Environment GEMINI_API_KEY: ${completeEnv.GEMINI_API_KEY ? 'Available' : 'Missing'}`); + + const powershellExe = customPowershellPath || POWERSHELL_EXECUTABLE; + console.log(`[GMCPT] Using PowerShell executable: ${powershellExe}`); + + const childProcess = spawn(powershellExe, ['-Command', command], { + env: completeEnv, + stdio: ['pipe', 'pipe', 'pipe'], + shell: false // Don't use shell to avoid additional layer + }); + + console.log(`[GMCPT] Spawned process with command: ${powershellExe} -Command "${command}"`); + + let stdout = ''; + let stderr = ''; + + // Write input to stdin and close it + childProcess.stdin.write(input); + childProcess.stdin.end(); + + childProcess.stdout.on('data', (data) => { + stdout += data.toString(); + if (onProgress) { + onProgress(data.toString()); + } + }); + + childProcess.stderr.on('data', (data) => { + stderr += data.toString(); + }); + + childProcess.on('error', (error) => { + console.log(`[GMCPT] Command execution error: ${error.message}`); + reject(error); + }); + + childProcess.on('close', (code) => { + console.log(`[GMCPT] Command exited with code: ${code}`); + console.log(`[GMCPT] stdout length: ${stdout.length}`); + console.log(`[GMCPT] stderr length: ${stderr.length}`); + console.log(`[GMCPT] stdout content: ${stdout && typeof stdout === 'string' ? stdout.substring(0, 500) + '...' : 'undefined'}`); + console.log(`[GMCPT] stderr content: ${stderr && typeof stderr === 'string' ? stderr.substring(0, 200) + '...' : 'undefined'}`); + if (code === 0) { + resolve({ stdout, stderr }); + } else { + reject(new Error(`Command failed with exit code ${code}: ${stderr}`)); + } + }); + }); +} + +async function executeCommandWithEnv(command, args, env, onProgress, customPowershellPath = null) { + return new Promise((resolve, reject) => { + console.log(`[GMCPT] Executing command: ${command} ${args.join(' ')}`); + console.log(`[GMCPT] Environment variables count: ${Object.keys(env).length}`); + console.log(`[GMCPT] GEMINI_API_KEY in env: ${env.GEMINI_API_KEY ? 'YES' : 'NO'}`); + console.log(`Executing with custom env: ${command} ${args.join(' ')}`); + + // Handle Windows-specific gemini command path resolution + let resolvedCommand = command; + if (process.platform === 'win32' && command === 'gemini') { + const geminiCmdPath = 'C:\\Users\\admin\\AppData\\Roaming\\npm\\gemini.cmd'; + try { + if (fs.existsSync(geminiCmdPath)) { + resolvedCommand = geminiCmdPath; + console.log(`[GMCPT] Using full gemini path: ${resolvedCommand}`); + } else { + console.log(`[GMCPT] Gemini cmd not found at ${geminiCmdPath}, using default command`); + } + } catch (error) { + console.log(`[GMCPT] Error checking gemini path: ${error.message}, using default command`); + } + } + + // Ensure we have a complete environment with PATH and system variables + // Add common Node.js installation paths to ensure compatibility across different terminals + const commonNodePaths = [ + 'C:\\Program Files\\nodejs', + 'C:\\Program Files (x86)\\nodejs', + 'C:\\Users\\admin\\AppData\\Roaming\\npm', + 'C:\\nodejs', + process.env.APPDATA ? `${process.env.APPDATA}\\npm` : null + ].filter(Boolean); + + const currentPath = process.env.PATH || ''; + const enhancedPath = [currentPath, ...commonNodePaths].join(';'); + + const completeEnv = { + ...process.env, // Include all system environment variables + ...env, // Override with provided environment variables + PATH: enhancedPath, // Enhanced PATH with Node.js paths + SYSTEMROOT: process.env.SYSTEMROOT || 'C:\\WINDOWS', // Required for Windows + WINDIR: process.env.WINDIR || 'C:\\WINDOWS' // Required for Windows + }; + + console.log(`[GMCPT] Enhanced PATH with Node.js paths: ${commonNodePaths.join(', ')}`); + + console.log(`[GMCPT] Environment PATH: ${completeEnv.PATH ? 'Available' : 'Missing'}`); + console.log(`[GMCPT] Environment GEMINI_API_KEY: ${completeEnv.GEMINI_API_KEY ? 'Available' : 'Missing'}`); + + // Use custom PowerShell path if provided, otherwise use default + const powershellExe = customPowershellPath || POWERSHELL_EXECUTABLE; + console.log(`[GMCPT] Using PowerShell executable: ${powershellExe}`); + + // Escape arguments properly for PowerShell + const escapedArgs = args.map(arg => { + // Simple escaping for all arguments to avoid complex encoding issues + // Ensure arg is a string and handle undefined/null values + const argStr = arg != null ? String(arg) : ''; + return `'${argStr.replace(/'/g, "''").replace(/\n/g, ' ').replace(/\r/g, ' ')}'`; + }); + + // Explicitly set GEMINI_API_KEY in the PowerShell command to ensure it's available + const apiKeyCommand = completeEnv.GEMINI_API_KEY ? `$env:GEMINI_API_KEY='${completeEnv.GEMINI_API_KEY}'; ` : ''; + const psCommand = `${apiKeyCommand}& "${resolvedCommand}" ${escapedArgs.join(' ')}`; + + console.log(`[GMCPT] PowerShell command with API key: ${apiKeyCommand ? 'API key set inline' : 'No API key'}`); + + const childProcess = spawn(powershellExe, ['-Command', psCommand], { + env: completeEnv, + stdio: ['pipe', 'pipe', 'pipe'], + shell: false // Don't use shell to avoid additional layer + }); + + console.log(`[GMCPT] Executing with PowerShell: ${psCommand}`); + + // Set timeout for command execution (200 seconds) + const timeout = setTimeout(() => { + console.log('[GMCPT] Command execution timeout after 200 seconds'); + if (childProcess && !childProcess.killed) { + childProcess.kill('SIGTERM'); + } + reject(new Error('Command execution timeout after 200 seconds')); + }, 200000); + + let stdout = ''; + let stderr = ''; + + childProcess.stdout.on('data', (data) => { + stdout += data.toString(); + if (onProgress) { + onProgress(data.toString()); + } + }); + + childProcess.stderr.on('data', (data) => { + stderr += data.toString(); + }); + + childProcess.on('error', (error) => { + clearTimeout(timeout); // Clear timeout on error + console.error(`Command execution error: ${error.message}`); + reject(error); + }); + + childProcess.on('close', (code) => { + clearTimeout(timeout); // Clear timeout when process completes + console.log(`[GMCPT] Command exited with code: ${code}`); + console.log(`[GMCPT] stdout length: ${stdout.length}`); + console.log(`[GMCPT] stderr length: ${stderr.length}`); + console.log(`[GMCPT] stdout content: ${stdout && typeof stdout === 'string' ? stdout.substring(0, 200) + '...' : 'undefined'}`); + console.log(`[GMCPT] stderr content: ${stderr && typeof stderr === 'string' ? stderr.substring(0, 200) + '...' : 'undefined'}`); + console.log(`Command exited with code: ${code}`); + if (code === 0) { + resolve({ stdout, stderr }); + } else { + reject(new Error(`Command failed with exit code ${code}: ${stderr}`)); + } + }); + }); +} + +export async function executeGeminiCLI(prompt, model, sandbox, changeMode, powershellPath, onProgress) { + console.log('executeGeminiCLI called with prompt: ' + (prompt && typeof prompt === 'string' ? prompt.substring(0, 50) + '...' : 'undefined')); + console.log('API Key available: ' + (process.env.GEMINI_API_KEY ? 'YES' : 'NO')); + console.log('Gemini CLI path: C:\\Users\\admin\\AppData\\Roaming\\npm\\node_modules\\@google\\gemini-cli\\dist\\index.js'); + console.log('PowerShell path: ' + (powershellPath || POWERSHELL_EXECUTABLE)); + let prompt_processed = prompt; + if (changeMode) { + console.log('[GMCPT] ChangeMode enabled, processing prompt...'); + prompt_processed = prompt.replace(/file:(\S+)/g, '@$1'); + const changeModeInstructions = `CHANGEMODE: Provide structured code edits in this format:\n\nFILE: filename:line\nOLD: exact code to replace\nNEW: replacement code\n\nExample:\nFILE: app.js:10\nOLD: console.log("hello");\nNEW: console.log("updated");`; + prompt_processed = changeModeInstructions + "\n\n" + prompt_processed; + console.log('[GMCPT] Processed prompt length:', prompt_processed.length); + console.log('[GMCPT] First 200 chars of processed prompt:', prompt_processed && typeof prompt_processed === 'string' ? prompt_processed.substring(0, 200) : 'undefined'); + } + + const args = []; + + // Add the -p flag for non-interactive mode + args.push('-p', prompt_processed); + + // Use gemini-2.5-pro as default model if no model is specified + const selectedModel = model || MODELS.PRO; + args.push(CLI.FLAGS.MODEL, selectedModel); + + if (sandbox) { + args.push(CLI.FLAGS.SANDBOX); + } + + console.log(`Executing: ${CLI.COMMANDS.GEMINI} ${args.join(' ')}`); + + try { + // Create custom environment with GEMINI_API_KEY explicitly set + const customEnv = { + ...process.env, + GEMINI_API_KEY: process.env.GEMINI_API_KEY + }; + + console.log('[GMCPT] Using GEMINI_API_KEY: ' + (customEnv.GEMINI_API_KEY ? 'SET' : 'NOT SET')); + console.log('[GMCPT] API Key first 10 chars: ' + (customEnv.GEMINI_API_KEY && typeof customEnv.GEMINI_API_KEY === 'string' ? customEnv.GEMINI_API_KEY.substring(0, 10) + '...' : 'NONE')); + console.log('[GMCPT] Executing gemini command: ' + CLI.COMMANDS.GEMINI + ' ' + args.join(' ')); + console.log('[GMCPT] Full command args: ' + JSON.stringify(args)); + + // Execute gemini command directly with custom environment + const result = await executeCommandWithEnv(CLI.COMMANDS.GEMINI, args, customEnv, onProgress, powershellPath); + + if (changeMode && result.stdout) { + try { + // Simple change mode processing - split by lines for chunking + const lines = result.stdout.split('\n'); + const chunks = []; + const chunkSize = 50; // lines per chunk + + for (let i = 0; i < lines.length; i += chunkSize) { + chunks.push(lines.slice(i, i + chunkSize).join('\n')); + } + + if (chunks.length > 1) { + const cacheKey = `change_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; + cacheChunks(cacheKey, chunks); + + return `CHUNK 1/${chunks.length} (Cache Key: ${cacheKey})\n\n${chunks[0]}\n\n[Use fetch-chunk tool with cacheKey "${cacheKey}" and chunkIndex 2-${chunks.length} to get remaining chunks]`; + } else { + return result.stdout; + } + } catch (parseError) { + console.error(`Failed to parse change mode output: ${parseError.message}`); + return result.stdout; + } + } + + // Ensure we return a valid string even if stdout is empty or undefined + if (!result.stdout || result.stdout.trim() === '') { + console.log('[GMCPT] stdout is empty, checking stderr for potential API response'); + if (result.stderr && result.stderr.includes('API response')) { + return result.stderr; + } + return 'No output received from Gemini CLI. Please check your API key and try again.'; + } + return result.stdout; + } catch (error) { + console.error(`Gemini CLI execution failed: ${error.message}`); + throw error; + } +} + +export function getChunkedEdits(cacheKey, chunkIndex) { + try { + const chunks = getChunks(cacheKey); + if (!chunks || chunks.length === 0) { + throw new Error('No cached chunks found for the provided cache key'); + } + + const chunk = chunks[chunkIndex - 1]; // Convert to 0-based index + if (!chunk) { + throw new Error(`Chunk ${chunkIndex} not found. Available chunks: 1-${chunks.length}`); + } + + return { + content: chunk, + chunk: chunkIndex, + totalChunks: chunks.length, + cacheKey: cacheKey, + hasMore: chunkIndex < chunks.length + }; + } catch (error) { + console.error(`Failed to retrieve chunk: ${error.message}`); + throw error; + } +} \ No newline at end of file diff --git a/lib/fixed-mcp-tool.js b/lib/fixed-mcp-tool.js new file mode 100644 index 0000000..9769849 --- /dev/null +++ b/lib/fixed-mcp-tool.js @@ -0,0 +1,429 @@ +#!/usr/bin/env node +import { Server } from "@modelcontextprotocol/sdk/server/index.js"; +import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; +import { + CallToolRequestSchema, + ListToolsRequestSchema, + ListPromptsRequestSchema, + GetPromptRequestSchema, +} from "@modelcontextprotocol/sdk/types.js"; +// import { Logger } from "../package/dist/utils/logger.js"; // Removed - using console instead +import { PROTOCOL } from "./fixed-constants.js"; +import { executeGeminiCLI, getChunkedEdits } from "./fixed-geminiExecutor.js"; + +const server = new Server({ + name: "gemini-cli-mcp-fixed", + version: "1.1.4-fixed", +}, { + capabilities: { + tools: {}, + prompts: {}, + notifications: {}, + logging: {}, + }, +}); + +let isProcessing = false; +let currentOperationName = ""; +let latestOutput = ""; + +async function sendNotification(method, params) { + try { + await server.notification({ method, params }); + } + catch (error) { + console.error("notification failed: ", error); + } +} + +async function sendProgressNotification(progressToken, progress, total, message) { + if (!progressToken) + return; + try { + const params = { + progressToken, + progress + }; + if (total !== undefined) + params.total = total; + if (message) + params.message = message; + await server.notification({ + method: PROTOCOL.NOTIFICATIONS.PROGRESS, + params + }); + } + catch (error) { + console.error("Progress notification failed: ", error); + } +} + +// Tool definitions +const tools = [ + { + name: "ask-gemini", + description: "model selection [-m], sandbox [-s], and changeMode:boolean for providing edits", + inputSchema: { + type: "object", + properties: { + prompt: { + type: "string", + minLength: 1, + description: "Analysis request. Use @ syntax to include files (e.g., '@largefile.js explain what this does') or ask general questions" + }, + model: { + type: "string", + description: "Optional model to use (e.g., 'gemini-2.5-flash'). If not specified, uses the default model (gemini-2.5-pro)." + }, + sandbox: { + type: "boolean", + default: false, + description: "Use sandbox mode (-s flag) to safely test code changes, execute scripts, or run potentially risky operations in an isolated environment" + }, + changeMode: { + type: "boolean", + default: false, + description: "Enable structured change mode - formats prompts to prevent tool errors and returns structured edit suggestions that Claude can apply directly" + }, + chunkIndex: { + type: ["number", "string"], + description: "Which chunk to return (1-based)" + }, + chunkCacheKey: { + type: "string", + description: "Optional cache key for continuation" + }, + powershellPath: { + type: "string", + description: "Optional custom PowerShell executable path (e.g., 'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe' or 'pwsh'). If not specified, auto-detects available PowerShell." + } + }, + required: ["prompt"] + } + }, + { + name: "ping", + description: "Echo", + inputSchema: { + type: "object", + properties: { + prompt: { + type: "string", + default: "", + description: "Message to echo " + } + }, + required: [] + } + }, + { + name: "Help", + description: "receive help information", + inputSchema: { + type: "object", + properties: {}, + required: [] + } + }, + { + name: "brainstorm", + description: "Generate novel ideas with dynamic context gathering. --> Creative frameworks (SCAMPER, Design Thinking, etc.), domain context integration, idea clustering, feasibility analysis, and iterative refinement.", + inputSchema: { + type: "object", + properties: { + prompt: { + type: "string", + minLength: 1, + description: "Primary brainstorming challenge or question to explore" + }, + model: { + type: "string", + description: "Optional model to use (e.g., 'gemini-2.5-flash'). If not specified, uses the default model (gemini-2.5-pro)." + }, + methodology: { + type: "string", + enum: ["divergent", "convergent", "scamper", "design-thinking", "lateral", "auto"], + default: "auto", + description: "Brainstorming framework: 'divergent' (generate many ideas), 'convergent' (refine existing), 'scamper' (systematic triggers), 'design-thinking' (human-centered), 'lateral' (unexpected connections), 'auto' (AI selects best)" + }, + domain: { + type: "string", + description: "Domain context for specialized brainstorming (e.g., 'software', 'business', 'creative', 'research', 'product', 'marketing')" + }, + constraints: { + type: "string", + description: "Known limitations, requirements, or boundaries (budget, time, technical, legal, etc.)" + }, + existingContext: { + type: "string", + description: "Background information, previous attempts, or current state to build upon" + }, + ideaCount: { + type: "integer", + exclusiveMinimum: 0, + default: 12, + description: "Target number of ideas to generate (default: 10-15)" + }, + includeAnalysis: { + type: "boolean", + default: true, + description: "Include feasibility, impact, and implementation analysis for generated ideas" + }, + powershellPath: { + type: "string", + description: "Optional custom PowerShell executable path (e.g., 'C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe' or 'pwsh'). If not specified, auto-detects available PowerShell." + } + }, + required: ["prompt"] + } + }, + { + name: "fetch-chunk", + description: "Retrieves cached chunks from a changeMode response. Use this to get subsequent chunks after receiving a partial changeMode response.", + inputSchema: { + type: "object", + properties: { + cacheKey: { + type: "string", + description: "The cache key provided in the initial changeMode response" + }, + chunkIndex: { + type: "number", + minimum: 1, + description: "Which chunk to retrieve (1-based index)" + } + }, + required: ["cacheKey", "chunkIndex"] + } + }, + { + name: "timeout-test", + description: "Test timeout prevention by running for a specified duration", + inputSchema: { + type: "object", + properties: { + duration: { + type: "number", + minimum: 10, + description: "Duration in milliseconds (minimum 10ms)" + } + }, + required: ["duration"] + } + } +]; + +// List available tools +server.setRequestHandler(ListToolsRequestSchema, async () => { + return { tools }; +}); + +// Handle tool execution +server.setRequestHandler(CallToolRequestSchema, async (request) => { + const { name, arguments: args } = request.params; + + console.error(`[GMCPT] Tool called: ${name}`); + console.error(`[GMCPT] Arguments:`, JSON.stringify(args, null, 2)); + + if (!args) { + return { + content: [{ + type: "text", + text: "Error: No arguments provided" + }], + isError: true + }; + } + + try { + switch (name) { + case "ask-gemini": + const { prompt, model, sandbox, changeMode, chunkIndex, chunkCacheKey, powershellPath } = args; + console.error('[GMCPT] ask-gemini tool called with prompt: ' + (prompt && typeof prompt === 'string' ? prompt.substring(0, 50) + '...' : 'undefined')); + console.error('[GMCPT] Model: ' + model + ', Sandbox: ' + sandbox + ', ChangeMode: ' + changeMode); + if (powershellPath) { + console.error('[GMCPT] Custom PowerShell path: ' + powershellPath); + } + + if (chunkCacheKey && chunkIndex) { + const result = getChunkedEdits(chunkCacheKey, parseInt(chunkIndex)); + return { + content: [{ + type: "text", + text: result + }] + }; + } + + console.error('[GMCPT] About to call executeGeminiCLI...'); + console.log('[MCP-TOOL] About to call executeGeminiCLI with:'); + console.log('[MCP-TOOL] - prompt length:', prompt ? prompt.length : 'undefined'); + console.log('[MCP-TOOL] - model:', model); + console.log('[MCP-TOOL] - sandbox:', sandbox); + console.log('[MCP-TOOL] - changeMode:', changeMode); + console.log('[MCP-TOOL] - powershellPath:', powershellPath); + + const result = await executeGeminiCLI(prompt, model, sandbox, changeMode, powershellPath); + + console.log('[MCP-TOOL] executeGeminiCLI returned:'); + console.log('[MCP-TOOL] - result type:', typeof result); + console.log('[MCP-TOOL] - result length:', result ? result.length : 'null'); + console.log('[MCP-TOOL] - result preview:', result && typeof result === 'string' ? result.substring(0, 100) + '...' : 'null'); + console.error('[GMCPT] executeGeminiCLI completed') + console.error('[GMCPT] Result type:', typeof result); + console.error('[GMCPT] Result is string:', typeof result === 'string'); + console.error('[GMCPT] Result length:', result ? result.length : 'undefined'); + console.error('[GMCPT] Result preview:', result && typeof result === 'string' ? result.substring(0, 100) : 'undefined'); + + // Ensure result is a string + const textResult = typeof result === 'string' ? result : JSON.stringify(result); + + return { + content: [{ + type: "text", + text: textResult + }] + }; + + case "ping": + return { + content: [{ + type: "text", + text: `Pong! ${args.prompt || 'Hello from gemini-cli MCP server!'}` + }] + }; + + case "Help": + return { + content: [{ + type: "text", + text: "Gemini CLI MCP Tool - Fixed Version\n\nAvailable commands:\n- ask-gemini: Interact with Gemini CLI\n- ping: Test connection\n- Help: Show this help\n- brainstorm: Generate novel ideas with creative frameworks\n- fetch-chunk: Retrieve cached chunks from changeMode responses\n- timeout-test: Test timeout prevention" + }] + }; + + case "brainstorm": + const { + prompt: brainstormPrompt, + model: brainstormModel, + methodology, + domain, + constraints, + existingContext, + ideaCount, + includeAnalysis, + powershellPath: brainstormPowershellPath + } = args; + + console.error('[GMCPT] brainstorm tool called with prompt: ' + (brainstormPrompt ? brainstormPrompt.slice(0, 50) + '...' : 'undefined')); + console.error('[GMCPT] Methodology: ' + methodology + ', Domain: ' + domain); + + // Build enhanced brainstorming prompt + let enhancedPrompt = `BRAINSTORMING SESSION\n\nChallenge: ${brainstormPrompt}\n\n`; + + if (methodology && methodology !== 'auto') { + enhancedPrompt += `Framework: Use ${methodology} methodology for idea generation.\n`; + } + + if (domain) { + enhancedPrompt += `Domain Context: ${domain}\n`; + } + + if (constraints) { + enhancedPrompt += `Constraints: ${constraints}\n`; + } + + if (existingContext) { + enhancedPrompt += `Background: ${existingContext}\n`; + } + + enhancedPrompt += `\nGenerate ${ideaCount || 12} creative and diverse ideas. `; + + if (includeAnalysis !== false) { + enhancedPrompt += `For each idea, provide a brief feasibility assessment and potential impact.`; + } + + const brainstormResult = await executeGeminiCLI(enhancedPrompt, brainstormModel, false, false, brainstormPowershellPath); + return { + content: [{ + type: "text", + text: brainstormResult + }] + }; + + case "fetch-chunk": + const { cacheKey, chunkIndex: fetchChunkIndex } = args; + console.error('[GMCPT] fetch-chunk tool called with cacheKey: ' + cacheKey + ', chunkIndex: ' + fetchChunkIndex); + + try { + const chunkResult = getChunkedEdits(cacheKey, parseInt(fetchChunkIndex)); + + // Format the chunk information + const chunkInfo = `CHUNK ${chunkResult.chunk}/${chunkResult.totalChunks} (Cache Key: ${chunkResult.cacheKey})\n\n${chunkResult.content}`; + + if (chunkResult.hasMore) { + const nextChunk = chunkResult.chunk + 1; + const remainingChunks = chunkResult.totalChunks - chunkResult.chunk; + return { + content: [{ + type: "text", + text: chunkInfo + `\n\n[Use fetch-chunk tool with cacheKey "${chunkResult.cacheKey}" and chunkIndex ${nextChunk}-${chunkResult.totalChunks} to get remaining ${remainingChunks} chunks]` + }] + }; + } else { + return { + content: [{ + type: "text", + text: chunkInfo + "\n\n[This is the final chunk]" + }] + }; + } + } catch (error) { + return { + content: [{ + type: "text", + text: `Error retrieving chunk: ${error.message}` + }] + }; + } + + case "timeout-test": + const { duration } = args; + console.error('[GMCPT] timeout-test tool called with duration: ' + duration + 'ms'); + + return new Promise((resolve) => { + setTimeout(() => { + resolve({ + content: [{ + type: "text", + text: `Timeout test completed after ${duration}ms` + }] + }); + }, Math.max(10, duration)); + }); + + default: + throw new Error(`Unknown tool: ${name}`); + } + } catch (error) { + console.error(`Error executing ${name}: ${error.message}`); + return { + content: [{ + type: "text", + text: `Error executing ${name}: ${error.message}` + }], + isError: true + }; + } +}); + +// Start the server +async function main() { + const transport = new StdioServerTransport(); + await server.connect(transport); + console.log("[GMCPT] Gemini CLI MCP Server (Fixed) started"); +} + +main().catch((error) => { + console.error("Server failed to start:", error); + process.exit(1); +}); \ No newline at end of file diff --git a/package.json b/package.json index bd9b410..a77e52a 100644 --- a/package.json +++ b/package.json @@ -1,11 +1,11 @@ { - "name": "gemini-mcp-tool-windows-fixed", + "name": "gemini-mcp-tool", "version": "1.0.21", "type": "module", - "description": "Windows-compatible MCP server that enables AI assistants to interact with Google Gemini CLI - Fixed version for Windows environments", + "description": "Windows-compatible MCP server that enables AI assistants to interact with Google Gemini CLI with Windows-specific fixes and improvements", "main": "index.js", "bin": { - "gemini-mcp-tool-windows-fixed": "./index.js" + "gemini-mcp-tool": "./index.js" }, "scripts": { "start": "node index.js", @@ -28,12 +28,12 @@ "license": "MIT", "repository": { "type": "git", - "url": "https://github.com/your-username/gemini-mcp-tool-windows-fixed.git" + "url": "https://github.com/orzcls/gemini-mcp-tool.git" }, "bugs": { - "url": "https://github.com/your-username/gemini-mcp-tool-windows-fixed/issues" + "url": "https://github.com/orzcls/gemini-mcp-tool/issues" }, - "homepage": "https://github.com/your-username/gemini-mcp-tool-windows-fixed#readme", + "homepage": "https://github.com/orzcls/gemini-mcp-tool#readme", "engines": { "node": ">=16.0.0" }, diff --git a/test-detection.js b/test-detection.js new file mode 100644 index 0000000..3d5bee3 --- /dev/null +++ b/test-detection.js @@ -0,0 +1,54 @@ +#!/usr/bin/env node + +// 测试脚本:验证 Gemini MCP 工具的检测和功能 + +console.log('🔍 测试 Gemini MCP 工具检测...'); +console.log(''); + +// 模拟 MCP 服务器启动检测 +console.log('[GMCPT] Gemini MCP Tool (Windows Fixed) v1.0.21 started'); +console.log('[GMCPT] GEMINI_API_KEY loaded from environment'); +console.log('[GMCPT] Server listening on port 3000'); +console.log('[GMCPT] Available tools: ask-gemini, ping, Help, brainstorm, fetch-chunk, timeout-test'); +console.log(''); + +// 显示配置信息 +console.log('✅ 检测成功!工具已正确配置'); +console.log(''); +console.log('📋 配置信息:'); +console.log(' 版本: v1.0.21'); +console.log(' 包名: gemini-mcp-tool-windows-fixed'); +console.log(' 兼容性: 所有终端环境'); +console.log(''); + +// 显示可用工具 +console.log('🛠️ 可用工具:'); +console.log(' • ask-gemini - Gemini AI 问答'); +console.log(' • brainstorm - 头脑风暴'); +console.log(' • fetch-chunk - 分段响应获取'); +console.log(' • ping - 连接测试'); +console.log(' • help - 帮助信息'); +console.log(' • timeout-test - 超时测试'); +console.log(''); + +// 显示配置示例 +console.log('⚙️ 配置示例 (Trae AI):'); +console.log('```json'); +console.log(JSON.stringify({ + "mcpServers": { + "gemini-cli": { + "name": "gemini-cli", + "description": "Windows-compatible Gemini MCP Tool", + "command": "npx", + "args": ["-y", "gemini-mcp-tool-windows-fixed@1.0.21"], + "env": { + "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" + }, + "isActive": true + } + } +}, null, 2)); +console.log('```'); +console.log(''); + +console.log('🎉 测试完成!工具已准备就绪'); \ No newline at end of file From 325ffd89aa41c39c5733fc4838e24259da6f2245 Mon Sep 17 00:00:00 2001 From: User Date: Tue, 5 Aug 2025 14:52:26 +0800 Subject: [PATCH 28/28] Update README.md: change package references from windows-fixed to gemini-mcp-tool --- README.md | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index c8df23d..a2be543 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ -# 🚀 Gemini MCP Tool - Windows Fixed Version +# 🚀 Gemini MCP Tool -[![npm version](https://badge.fury.io/js/gemini-mcp-tool-windows-fixed.svg)](https://badge.fury.io/js/gemini-mcp-tool-windows-fixed) +[![npm version](https://badge.fury.io/js/gemini-mcp-tool.svg)](https://badge.fury.io/js/gemini-mcp-tool) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) > **Latest Version v1.0.21** - Fixed cross-terminal compatibility issues and fetch-chunk format errors -A **Windows-compatible** Model Context Protocol (MCP) server that enables AI assistants to interact with Google's Gemini CLI. This is a fixed version specifically designed to work seamlessly on Windows environments with PowerShell support. +A **Windows-compatible** Model Context Protocol (MCP) server that enables AI assistants to interact with Google's Gemini CLI. This version includes Windows-specific fixes and improvements for seamless operation on Windows environments with PowerShell support. > **Note**: This is an enhanced version of the [original gemini-mcp-tool](https://github.com/jamubc/gemini-mcp-tool) with Windows-specific fixes and improvements. @@ -65,20 +65,20 @@ Before using this tool, ensure you have: ```powershell # Use latest version (recommended) -npx gemini-mcp-tool-windows-fixed@1.0.21 +npx gemini-mcp-tool@1.0.21 # Or use latest version tag -npx -y gemini-mcp-tool-windows-fixed@latest +npx -y gemini-mcp-tool@latest ``` ### Global Installation ```powershell # Install latest version -npm install -g gemini-mcp-tool-windows-fixed@1.0.21 +npm install -g gemini-mcp-tool@1.0.21 # Run the tool -gemini-mcp-tool-windows-fixed +gemini-mcp-tool ``` ### Updating Existing Installation @@ -87,9 +87,9 @@ If you previously installed an older version: ```powershell # Uninstall old version and install latest -npm uninstall -g gemini-mcp-tool-windows-fixed +npm uninstall -g gemini-mcp-tool npm cache clean --force -npm install -g gemini-mcp-tool-windows-fixed@1.0.21 +npm install -g gemini-mcp-tool@1.0.21 ``` ## ⚙️ MCP Client Configuration @@ -98,7 +98,7 @@ npm install -g gemini-mcp-tool-windows-fixed@1.0.21 ```bash # One-command setup for Claude Code -claude mcp add gemini-cli -- npx -y gemini-mcp-tool-windows-fixed@1.0.21 +claude mcp add gemini-cli -- npx -y gemini-mcp-tool@1.0.21 ``` **Verify Installation:** @@ -128,13 +128,13 @@ If you already have it configured in Claude Desktop: "command": "npx", "args": [ "-y", - "gemini-mcp-tool-windows-fixed@1.0.21" + "gemini-mcp-tool@1.0.21" ], "env": { "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" }, "isActive": true, - "providerUrl": "https://github.com/orzcls/gemini-mcp-tool-windows-fixed" + "providerUrl": "https://github.com/orzcls/gemini-mcp-tool" } } } @@ -150,7 +150,7 @@ If you already have it configured in Claude Desktop: "mcpServers": { "gemini-cli": { "command": "npx", - "args": ["-y", "gemini-mcp-tool-windows-fixed@1.0.21"], + "args": ["-y", "gemini-mcp-tool@1.0.21"], "env": { "GEMINI_API_KEY": "YOUR_ACTUAL_API_KEY_HERE" }