UNPKG

@cyanheads/git-mcp-server

Version:

An MCP (Model Context Protocol) server enabling LLMs and AI agents to interact with Git repositories. Provides tools for comprehensive Git operations including clone, commit, branch, diff, log, status, push, pull, merge, rebase, worktree, tag management,

75 lines 3.06 kB
/** * @fileoverview Defines the core logic, schemas, and types for the git_set_working_dir tool. * @module src/mcp-server/tools/gitSetWorkingDir/logic */ import { execFile } from "child_process"; import fs from "fs/promises"; import { promisify } from "util"; import { z } from "zod"; import { logger, sanitization, } from "../../../utils/index.js"; import { McpError, BaseErrorCode } from "../../../types-global/errors.js"; const execFileAsync = promisify(execFile); // 1. DEFINE the Zod input schema. export const GitSetWorkingDirInputSchema = z.object({ path: z .string() .min(1) .describe("The absolute path to set as the default working directory."), validateGitRepo: z .boolean() .default(true) .describe("Validate that the path is a Git repository."), initializeIfNotPresent: z .boolean() .default(false) .describe("If not a Git repository, initialize it with 'git init'."), }); // 2. DEFINE the Zod response schema. export const GitSetWorkingDirOutputSchema = z.object({ success: z.boolean().describe("Indicates if the command was successful."), message: z.string().describe("A summary message of the result."), path: z.string().describe("The path that was set as the working directory."), initialized: z .boolean() .describe("Indicates if a new repository was initialized."), }); async function checkIsGitRepo(path) { const { stdout } = await execFileAsync("git", ["rev-parse", "--is-inside-work-tree"], { cwd: path }).catch(() => ({ stdout: "false" })); return stdout.trim() === "true"; } /** * 4. IMPLEMENT the core logic function. * @throws {McpError} If the logic encounters an unrecoverable issue. */ export async function gitSetWorkingDirLogic(params, context) { const operation = "gitSetWorkingDirLogic"; logger.debug(`Executing ${operation}`, { ...context, params }); const sanitizedPath = sanitization.sanitizePath(params.path, { allowAbsolute: true, }).sanitizedPath; const stats = await fs.stat(sanitizedPath); if (!stats.isDirectory()) { throw new McpError(BaseErrorCode.VALIDATION_ERROR, `Path is not a directory: ${sanitizedPath}`); } let isGitRepo = await checkIsGitRepo(sanitizedPath); let initializedRepo = false; if (!isGitRepo && params.initializeIfNotPresent) { await execFileAsync("git", ["init", "--initial-branch=main"], { cwd: sanitizedPath, }); initializedRepo = true; isGitRepo = true; } if (params.validateGitRepo && !isGitRepo) { throw new McpError(BaseErrorCode.VALIDATION_ERROR, `Path is not a valid Git repository: ${sanitizedPath}.`); } context.setWorkingDirectory(sanitizedPath); const message = `Working directory set to: ${sanitizedPath}${initializedRepo ? " (New repository initialized)." : ""}`; return { success: true, message, path: sanitizedPath, initialized: initializedRepo, }; } //# sourceMappingURL=logic.js.map