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)

Tool Definition Quality

Score is being calculated. Check back soon.

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