Skip to main content
Glama
PV-Bhat

GemForge-Gemini-Tools-MCP

gemini_code

Analyze codebases to answer questions about structure, logic, and improvements. Use Repomix and Gemini 2.5 Pro for detailed insights into your code directory or pre-packed files.

Instructions

Analyzes codebases using Repomix and Gemini 2.5 Pro. Answers questions about code structure, logic, and potential improvements.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
codebase_pathNoPath to pre-packed Repomix file
directory_pathNoPath to the code directory
model_idNoOptional model ID override (advanced users only)
questionYesQuestion about the codebase

Implementation Reference

  • Core handler function executing gemini_code tool: handles args validation, packs codebase if directory provided using repomix, selects Gemini model, builds structured request, calls API, formats output, cleans up temp files.
    export async function handleCode(request: any) {
      // --> ADD THIS LINE <--
      console.error('<<<<< RUNNING LATEST handleCode - FIX_ATTEMPT_4 >>>>>');
      let tempFilePath: string | null = null;
    
      try {
        // Validate required parameters
        if (!request.params.arguments || !request.params.arguments.question) {
          throw new McpError(
            ErrorCode.InvalidParams,
            'question parameter is required'
          );
        }
    
        // Extract arguments
        const args = request.params.arguments as CodeArgs;
        const { question, directory_path, codebase_path, model_id, repomix_options } = args;
    
        // Validate that at least one of directory_path or codebase_path is provided
        if (!directory_path && !codebase_path) {
          throw new McpError(
            ErrorCode.InvalidParams,
            'Either directory_path or codebase_path parameter is required'
          );
        }
    
        // Determine the analysis path
        let analysisPath: string;
    
        if (codebase_path) {
          // Use the provided codebase path
          console.error(`[handleCode] Using provided codebase path: ${codebase_path}`);
    
          // Normalize the path for Windows
          const normalizedPath = path.resolve(codebase_path);
          console.error(`[handleCode] Normalized codebase path: ${normalizedPath}`);
    
          // Check if the file exists
          try {
            await fs.access(normalizedPath);
            console.error(`[handleCode] File exists at: ${normalizedPath}`);
            analysisPath = normalizedPath;
          } catch (error) {
            console.error(`[handleCode] File access error: ${error}`);
            throw new McpError(
              ErrorCode.InvalidParams,
              `Codebase file not found: ${codebase_path} (normalized: ${normalizedPath})`
            );
          }
        } else {
          // Pack the directory using Repomix
          console.error(`[handleCode] Packing directory: ${directory_path}`);
    
          if (!directory_path) {
            throw new McpError(
              ErrorCode.InvalidParams,
              'directory_path is required for packing'
            );
          }
    
          // Normalize the directory path for Windows
          const normalizedDirPath = path.resolve(directory_path);
          console.error(`[handleCode] Normalized directory path: ${normalizedDirPath}`);
    
          // Pack the directory with custom options if provided
          const packOptions = repomix_options ? { customOptions: repomix_options } : {};
          console.error(`[handleCode] Calling packDirectory with${repomix_options ? ' custom options: ' + repomix_options : ''}: ${normalizedDirPath}`);
          const packResult = await packDirectory(normalizedDirPath, packOptions);
          console.error(`[handleCode] Pack result: ${JSON.stringify(packResult)}`);
    
          if (packResult.error) {
            console.error(`[handleCode] Pack error: ${packResult.error}`);
            throw new McpError(
              ErrorCode.InternalError,
              `Failed to pack directory: ${packResult.error}`
            );
          }
    
          analysisPath = packResult.outputPath;
          tempFilePath = analysisPath; // Store for cleanup
          console.error(`[handleCode] Directory packed successfully: ${analysisPath}`);
    
          // Verify the file exists
          try {
            await fs.access(analysisPath);
            console.error(`[handleCode] Packed file exists at: ${analysisPath}`);
          } catch (error) {
            console.error(`[handleCode] Packed file access error: ${error}`);
            throw new McpError(
              ErrorCode.InternalError,
              `Packed file not found: ${analysisPath}`
            );
          }
        }
    
        // Create a new args object with the updated codebase_path
        const updatedArgs: CodeArgs = {
          ...args,
          codebase_path: analysisPath
        };
    
        // Select the model using the tool-specific model selector
        const targetModelId = selectToolModel(TOOL_NAMES.GEM_CODE, updatedArgs);
        console.error(`[handleCode] Selected model: ${targetModelId}`);
    
        // Build the request using the new builder function
        const internalRequest = await buildCodeRequest(updatedArgs);
        console.error(`[handleCode] Request built for model: ${targetModelId}`);
    
        // Diagnostic: log contents to verify XML is included
        console.error(`[handleCode] SDK request contents: ${internalRequest.contents.length} entries`);
        if (internalRequest.contents[0]?.parts) {
          console.error(`[handleCode] First part length: ${internalRequest.contents[0].parts[0].text.length} chars`);
        }
    
        // Execute the request
        const { response, rawSdkResponse } = await executeRequest(targetModelId, internalRequest);
        console.error(`[handleCode] Got response from ${targetModelId}`);
    
        // Format the response
        return formatResponse(response, targetModelId, {
          operation: TOOL_NAMES.GEM_CODE,
          customFormat: {
            question,
            usedDirectory: !!directory_path,
            usedCodebasePath: !!codebase_path
          }
        }, rawSdkResponse);
      } catch (error) {
        console.error('Error in code handler:', error);
        if (error instanceof McpError) {
          throw error;
        }
        return {
          content: [
            {
              type: 'text',
              text: `Error: ${error instanceof Error ? error.message : 'Unknown error'}`
            }
          ],
          isError: true
        };
      } finally {
        // Clean up temporary files if created
        if (tempFilePath) {
          try {
            await cleanupPackedFile(tempFilePath);
          } catch (cleanupError) {
            console.error(`[handleCode] Error cleaning up temporary file: ${cleanupError}`);
          }
        }
      }
    }
  • src/index.ts:212-213 (registration)
    Registers the handleCode function for the 'gemini_code' tool in the MCP tool call switch statement.
    case TOOL_NAMES.GEM_CODE:
      return await handleCode(request);
  • TypeScript interface defining input arguments for the gemini_code tool.
    export interface CodeArgs extends BaseArgs {
      /** Question about the codebase */
      question: string;
    
      /** Path to the code directory */
      directory_path?: string;
    
      /** Path to pre-packed Repomix file */
      codebase_path?: string;
    
      /** Custom Repomix command options (for power users) */
      repomix_options?: string;
    }
  • src/index.ts:118-143 (registration)
    Tool specification registration in ListTools handler, including name, description, and input schema for 'gemini_code'.
    {
      name: TOOL_NAMES.GEM_CODE,
      description: 'Analyzes codebases using Repomix and Gemini 2.5 Pro. Answers questions about code structure, logic, and potential improvements.',
      inputSchema: {
        type: 'object',
        properties: {
          question: {
            type: 'string',
            description: 'Question about the codebase'
          },
          directory_path: {
            type: 'string',
            description: 'Path to the code directory'
          },
          codebase_path: {
            type: 'string',
            description: 'Path to pre-packed Repomix file'
          },
          model_id: {
            type: 'string',
            description: 'Optional model ID override (advanced users only)'
          }
        },
        required: ['question'],
      },
    },
  • Constant definition for the gemini_code tool name (TOOL_NAMES.GEM_CODE).
    GEM_CODE: 'gemini_code',        // For coding tasks (Gemini 2.5 Pro)
    GEM_FILEOPS: 'gemini_fileops',  // For file operations (Gemini 2.0 Flash-Lite/1.5 Pro)
Install Server

Other Tools

Related 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/PV-Bhat/GemForge-MCP'

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