Skip to main content
Glama

GemForge-Gemini-Tools-MCP

code.ts6.3 kB
/** * Handler for gemini_code tool * * This file contains the implementation of the gemini_code tool, * which analyzes codebases using Repomix and Gemini 2.5 Pro. */ import { McpError, ErrorCode } from '@modelcontextprotocol/sdk/types.js'; import { CodeArgs } from '../interfaces/tool-args.js'; import { TOOL_NAMES } from '../config/constants.js'; import { packDirectory, cleanupPackedFile } from '../utils/repo-packer.js'; import { buildCodeRequest } from '../utils/request-builder.js'; import { executeRequest } from '../utils/api-executor.js'; import { formatResponse } from '../utils/response-formatter.js'; import { selectToolModel } from '../utils/model-selector.js'; import fs from 'fs/promises'; import path from 'path'; /** * Handle Gemini code analysis request * @param request - MCP request * @returns MCP response */ 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}`); } } } }

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