Skip to main content
Glama
orzcls

Gemini CLI MCP Server

by orzcls

ask-gemini

Analyze files or ask questions using Google's Gemini models with options for model selection, sandbox testing, and structured edit suggestions.

Instructions

model selection [-m], sandbox [-s], and changeMode:boolean for providing edits

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
promptYesAnalysis request. Use @ syntax to include files (e.g., '@largefile.js explain what this does') or ask general questions
modelNoOptional model to use (e.g., 'gemini-2.5-flash'). If not specified, uses the default model (gemini-2.5-pro).
sandboxNoUse sandbox mode (-s flag) to safely test code changes, execute scripts, or run potentially risky operations in an isolated environment
changeModeNoEnable structured change mode - formats prompts to prevent tool errors and returns structured edit suggestions that Claude can apply directly
chunkIndexNoWhich chunk to return (1-based)
chunkCacheKeyNoOptional cache key for continuation
powershellPathNoOptional custom PowerShell executable path (e.g., 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe' or 'pwsh'). If not specified, auto-detects available PowerShell.

Implementation Reference

  • The handler function for the 'ask-gemini' tool within the CallToolRequestSchema handler. It processes input arguments, handles chunked responses if requested, calls the executeGeminiCLI helper for Gemini AI interaction, and returns the result as MCP content.
    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
            }]
        };
  • The schema definition for the 'ask-gemini' tool, including name, description, and detailed inputSchema with properties for prompt, model, sandbox, changeMode, chunking parameters, and powershellPath.
    {
        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"]
        }
    },
  • Registers the list tools handler which returns the tools array containing the 'ask-gemini' tool definition.
    server.setRequestHandler(ListToolsRequestSchema, async () => {
        return { tools };
    });
  • Core helper function that implements the actual execution of the Gemini CLI. Processes the prompt (including changeMode formatting), constructs CLI arguments, spawns the process using PowerShell with proper environment, handles chunking for large changeMode responses, and returns the output.
    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;
        }
    }
  • Helper function to retrieve specific chunks from cached changeMode responses, used by the ask-gemini handler for continuation.
    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;
        }
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It mentions 'sandbox mode' for safe testing and 'changeMode' for structured edits, which adds some context about safety and output formatting. However, it lacks critical details like rate limits, authentication needs, error handling, or what the tool returns (no output schema exists). The description is insufficient for a tool with 7 parameters and complex functionality.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness2/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is poorly structured—it reads like a fragmented parameter reference rather than a coherent tool description. It's not front-loaded with purpose, and the phrase 'providing edits' is tacked on ambiguously. While brief, it fails to communicate effectively, making it inefficient rather than concise.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (7 parameters, AI interaction, no output schema, and no annotations), the description is highly incomplete. It doesn't explain the core functionality, return values, error conditions, or practical usage scenarios. The schema handles parameter documentation, but the description adds little contextual value, leaving significant gaps for an AI agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the input schema already documents all parameters thoroughly. The description lists three parameters ('model selection [-m], sandbox [-s], and changeMode:boolean') but doesn't add meaningful semantics beyond what the schema provides (e.g., it doesn't explain interactions between parameters or usage nuances). This meets the baseline of 3 when schema coverage is high.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose2/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description is essentially a parameter list ('model selection [-m], sandbox [-s], and changeMode:boolean') rather than stating what the tool does. It mentions 'providing edits' at the end, which hints at functionality but doesn't clearly articulate the core purpose. The description fails to specify that this tool queries or interacts with a Gemini AI model.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit guidance on when to use this tool versus alternatives like 'brainstorm' or 'fetch-chunk' is provided. The description mentions 'providing edits' which might imply use cases involving code or text modifications, but it doesn't clarify context, prerequisites, or distinctions from sibling tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/orzcls/gemini-mcp-tool-windows-fixed'

If you have feedback or need assistance with the MCP directory API, please join our Discord server