Skip to main content
Glama

Git MCP Server

git-diff.tool.ts4.99 kB
/** * @fileoverview Git diff tool - view differences between commits/files * @module mcp-server/tools/definitions/git-diff */ import { z } from 'zod'; import { withToolAuth } from '@/mcp-server/transports/auth/lib/withAuth.js'; import { CommitRefSchema, PathSchema } from '../schemas/common.js'; import type { ToolDefinition } from '../utils/toolDefinition.js'; import { createToolHandler, type ToolLogicDependencies, } from '../utils/toolHandlerFactory.js'; import { createJsonFormatter, type VerbosityLevel, } from '../utils/json-response-formatter.js'; const TOOL_NAME = 'git_diff'; const TOOL_TITLE = 'Git Diff'; const TOOL_DESCRIPTION = 'View differences between commits, branches, or working tree. Shows changes in unified diff format.'; const InputSchema = z.object({ path: PathSchema, target: CommitRefSchema.optional().describe( 'Target commit/branch to compare against. If not specified, shows unstaged changes in working tree.', ), source: CommitRefSchema.optional().describe( 'Source commit/branch to compare from. If target is specified but not source, compares target against working tree.', ), paths: z .array(z.string()) .optional() .describe( 'Limit diff to specific file paths (relative to repository root).', ), staged: z .boolean() .default(false) .describe('Show diff of staged changes instead of unstaged.'), includeUntracked: z .boolean() .default(false) .describe( 'Include untracked files in the diff. Useful for reviewing all upcoming changes.', ), nameOnly: z .boolean() .default(false) .describe('Show only names of changed files, not the diff content.'), stat: z .boolean() .default(false) .describe( 'Show diffstat (summary of changes) instead of full diff content.', ), contextLines: z .number() .int() .min(0) .max(100) .default(3) .describe('Number of context lines to show around changes.'), }); const OutputSchema = z.object({ success: z.boolean().describe('Indicates if the operation was successful.'), diff: z.string().describe('The diff output in unified diff format.'), filesChanged: z.number().int().describe('Number of files with differences.'), insertions: z .number() .int() .optional() .describe('Total number of line insertions.'), deletions: z .number() .int() .optional() .describe('Total number of line deletions.'), }); type ToolInput = z.infer<typeof InputSchema>; type ToolOutput = z.infer<typeof OutputSchema>; async function gitDiffLogic( input: ToolInput, { provider, targetPath, appContext }: ToolLogicDependencies, ): Promise<ToolOutput> { // Build options object with only defined properties const diffOptions: { target?: string; source?: string; paths?: string[]; staged?: boolean; includeUntracked?: boolean; nameOnly?: boolean; stat?: boolean; contextLines?: number; } = { staged: input.staged, includeUntracked: input.includeUntracked, nameOnly: input.nameOnly, stat: input.stat, contextLines: input.contextLines, }; if (input.target !== undefined) { diffOptions.target = input.target; } if (input.source !== undefined) { diffOptions.source = input.source; } if (input.paths !== undefined) { diffOptions.paths = input.paths; } const result = await provider.diff(diffOptions, { workingDirectory: targetPath, requestContext: appContext, tenantId: appContext.tenantId || 'default-tenant', }); return { success: true, diff: result.diff, filesChanged: result.filesChanged || 0, insertions: result.insertions, deletions: result.deletions, }; } /** * Filter git_diff output based on verbosity level. * * Verbosity levels: * - minimal: Files changed and stats only (no diff content) * - standard: Above + diff content (RECOMMENDED, may be large) * - full: Complete output (same as standard) */ function filterGitDiffOutput( result: ToolOutput, level: VerbosityLevel, ): Partial<ToolOutput> { // minimal: Summary stats only, no diff content if (level === 'minimal') { return { success: result.success, filesChanged: result.filesChanged, insertions: result.insertions, deletions: result.deletions, }; } // standard & full: Complete output including diff content // (LLMs need full diff to understand changes) return result; } // Create JSON response formatter with verbosity filtering const responseFormatter = createJsonFormatter<ToolOutput>({ filter: filterGitDiffOutput, }); export const gitDiffTool: ToolDefinition< typeof InputSchema, typeof OutputSchema > = { name: TOOL_NAME, title: TOOL_TITLE, description: TOOL_DESCRIPTION, inputSchema: InputSchema, outputSchema: OutputSchema, annotations: { readOnlyHint: true }, logic: withToolAuth(['tool:git:read'], createToolHandler(gitDiffLogic)), responseFormatter, };

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/cyanheads/git-mcp-server'

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