git_diff
Generate Git repository diffs to analyze code changes, supporting working directory, staged files, or commit ranges for technical review and documentation.
Instructions
Retorna um diff do repositório atual. Use para entender alterações locais.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| base | No | ||
| head | No | ||
| maxBytes | No | ||
| mode | No | working | |
| pathSpec | No |
Implementation Reference
- src/index.ts:32-84 (handler)The handler function for the 'git_diff' tool. It constructs git diff arguments based on the mode ('working', 'staged', 'range'), runs git diff and git diff --name-status using the runGit helper, processes the output to list changed files, truncates if necessary, and returns formatted content.async ({ mode = 'working', base, head, pathSpec, maxBytes = 200_000 }) => { let args: string[] = ['diff', '-U3'] if (mode === 'staged') { args = ['diff', '--staged', '-U3'] } if (mode === 'range' && (!base || !head)) { throw new Error('For mode=range informe base e head') } if (mode === 'range') { args = ['diff', `${base}...${head}`, '-U3'] } if (pathSpec && pathSpec.length) { args.push('--', ...pathSpec) } const nameStatus = await runGit( mode === 'range' ? ['diff', '--name-status', `${base}...${head}`] : mode === 'staged' ? ['diff', '--staged', '--name-status'] : ['diff', '--name-status'] ) const diff = await runGit(args) const truncated = diff.length > maxBytes ? diff.slice(0, maxBytes) + '\n\n[...truncated...]' : diff const files = nameStatus .split('\n') .filter(Boolean) .map((line) => { const [status, ...rest] = line.split(/\s+/) return { status, file: rest.join(' ') } }) return { content: [ { type: 'text', text: `Changed files:\n${files .map((f) => `${f.status}\t${f.file}`) .join('\n')}`, }, { type: 'text', text: '\n--- DIFF START ---\n' + truncated }, ], } }
- src/index.ts:19-30 (schema)Input schema for git_diff tool using Zod: mode (enum: working/staged/range), base/head (strings opt), pathSpec (array strings opt), maxBytes (number opt).inputSchema: { mode: z.enum(['working', 'staged', 'range']).default('working'), base: z.string().optional(), head: z.string().optional(), pathSpec: z.array(z.string()).optional(), maxBytes: z .number() .int() .positive() .max(5 * 1024 * 1024) .optional(), },
- src/index.ts:13-85 (registration)Registers the 'git_diff' tool with McpServer using server.registerTool, providing title, description, inputSchema, and the handler function.server.registerTool( 'git_diff', { title: 'Get Git diff', description: 'Retorna um diff do repositório atual. Use para entender alterações locais.', inputSchema: { mode: z.enum(['working', 'staged', 'range']).default('working'), base: z.string().optional(), head: z.string().optional(), pathSpec: z.array(z.string()).optional(), maxBytes: z .number() .int() .positive() .max(5 * 1024 * 1024) .optional(), }, }, async ({ mode = 'working', base, head, pathSpec, maxBytes = 200_000 }) => { let args: string[] = ['diff', '-U3'] if (mode === 'staged') { args = ['diff', '--staged', '-U3'] } if (mode === 'range' && (!base || !head)) { throw new Error('For mode=range informe base e head') } if (mode === 'range') { args = ['diff', `${base}...${head}`, '-U3'] } if (pathSpec && pathSpec.length) { args.push('--', ...pathSpec) } const nameStatus = await runGit( mode === 'range' ? ['diff', '--name-status', `${base}...${head}`] : mode === 'staged' ? ['diff', '--staged', '--name-status'] : ['diff', '--name-status'] ) const diff = await runGit(args) const truncated = diff.length > maxBytes ? diff.slice(0, maxBytes) + '\n\n[...truncated...]' : diff const files = nameStatus .split('\n') .filter(Boolean) .map((line) => { const [status, ...rest] = line.split(/\s+/) return { status, file: rest.join(' ') } }) return { content: [ { type: 'text', text: `Changed files:\n${files .map((f) => `${f.status}\t${f.file}`) .join('\n')}`, }, { type: 'text', text: '\n--- DIFF START ---\n' + truncated }, ], } } )
- src/helpers/github.ts:9-15 (helper)runGit helper function that promisifies execFile to run git commands with given args, returns trimmed stdout. Used by git_diff handler to execute git diff and git --name-status.export async function runGit(args: string[], cwd = process.cwd()) { const { stdout } = await pexec('git', ['--no-pager', ...args], { cwd, maxBuffer: 1024 * 1024 * 20, }) return stdout.trim() }