Skip to main content
Glama

Claude Code Review MCP

git-utils.ts4.86 kB
import { execSync, ExecSyncOptionsWithStringEncoding } from "child_process"; import { ReviewTarget, isDebugMode } from "./config.js"; // Ensure .js for ESM NodeNext /** * Gets the git diff for the specified target. * * @param target - The git target to review ('staged', 'HEAD', or 'branch_diff') * @param baseBranch - For 'branch_diff' target, the base branch/commit to compare against * @returns The git diff as a string or a message if no changes are found * @throws Error if not in a git repository, or if git encounters any errors * * Note: For branch_diff, this function assumes the remote is named 'origin'. * If your repository uses a different remote name, this operation may fail. */ export function getGitDiff(target: ReviewTarget, baseBranch?: string): string { const execOptions: ExecSyncOptionsWithStringEncoding = { encoding: "utf8", maxBuffer: 20 * 1024 * 1024, // Increased to 20MB buffer stdio: ["pipe", "pipe", "pipe"], // pipe stderr to catch git errors }; let command: string = ""; try { // Verify it's a git repository first execSync("git rev-parse --is-inside-work-tree", { ...execOptions, stdio: "ignore", }); } catch (error) { console.error( "[MCP Server Git] Current directory is not a git repository or git is not found." ); throw new Error( "Execution directory is not a git repository or git command is not available. Please run from a git project root." ); } try { switch (target) { case "staged": command = "git diff --staged --patch-with-raw --unified=10"; // More context break; case "HEAD": command = "git diff HEAD --patch-with-raw --unified=10"; break; case "branch_diff": if (!baseBranch || baseBranch.trim() === "") { throw new Error( "Base branch/commit is required for 'branch_diff' target and cannot be empty." ); } // Sanitize baseBranch to prevent command injection // Only allow alphanumeric characters, underscore, dash, dot, and forward slash const sanitizedBaseBranch = baseBranch.replace( /[^a-zA-Z0-9_.\-/]/g, "" ); if (sanitizedBaseBranch !== baseBranch) { throw new Error( `Invalid characters in base branch name. Only alphanumeric characters, underscore, dash, dot, and forward slash are allowed. Received: "${baseBranch}"` ); } // Fetch the base branch to ensure the diff is against the latest version of it // Note: This assumes the remote is named 'origin' const fetchCommand = `git fetch origin ${sanitizedBaseBranch}:${sanitizedBaseBranch} --no-tags --quiet`; try { execSync(fetchCommand, execOptions); } catch (fetchError: any) { // Log a warning but proceed; the branch might be local or already up-to-date console.warn( `[MCP Server Git] Warning during 'git fetch' for base branch '${sanitizedBaseBranch}': ${fetchError.message}. Diff will proceed with local state.` ); } command = `git diff ${sanitizedBaseBranch}...HEAD --patch-with-raw --unified=10`; break; default: // This case should ideally be caught by Zod validation on parameters throw new Error(`Unsupported git diff target: ${target}`); } // Only log the command if in debug mode if (isDebugMode()) { console.log(`[MCP Server Git] Executing: ${command}`); } // Execute the command (execOptions has encoding:'utf8' so the result should already be a string) const diffOutput = execSync(command, execOptions); // Ensure we always have a string to work with // This is for type safety and to handle any unexpected Buffer return types const diffString = Buffer.isBuffer(diffOutput) ? diffOutput.toString('utf8') : String(diffOutput); if (!diffString.trim()) { return "No changes found for the specified target."; } return diffString; } catch (error: any) { const errorMessage = error.stderr?.toString().trim() || error.message || "Unknown git error"; console.error( `[MCP Server Git] Error getting git diff for target "${target}" (base: ${ baseBranch || "N/A" }):` ); console.error(`[MCP Server Git] Command: ${command || "N/A"}`); // Only log the full error details in debug mode if (isDebugMode()) { console.error( `[MCP Server Git] Stderr: ${error.stderr?.toString().trim()}` ); console.error( `[MCP Server Git] Stdout: ${error.stdout?.toString().trim()}` ); } throw new Error( `Failed to get git diff. Git error: ${errorMessage}. Ensure you are in a git repository and the target/base is valid.` ); } }

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/praneybehl/claude-code-review-mcp'

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