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,

95 lines (94 loc) 5.39 kB
import { BaseErrorCode } from "../../../types-global/errors.js"; // Direct import for types-global import { ErrorHandler, logger, requestContextService, } from "../../../utils/index.js"; // ErrorHandler (./utils/internal/errorHandler.js), logger (./utils/internal/logger.js), requestContextService & RequestContext (./utils/internal/requestContext.js) import { GitSetWorkingDirInputSchema, gitSetWorkingDirLogic, } from "./logic.js"; let _getWorkingDirectory; // Added getter let _setWorkingDirectory; let _getSessionId; /** * Initializes the state accessors needed by the tool registration. * This should be called once during server setup. * @param getWdFn - Function to get the working directory for a session. * @param setWdFn - Function to set the working directory for a session. * @param getSidFn - Function to get the session ID from context. */ export function initializeGitSetWorkingDirStateAccessors(getWdFn, // Added getter parameter setWdFn, getSidFn) { _getWorkingDirectory = getWdFn; // Store getter _setWorkingDirectory = setWdFn; _getSessionId = getSidFn; logger.info("State accessors initialized for git_set_working_dir tool registration."); } const TOOL_NAME = "git_set_working_dir"; const TOOL_DESCRIPTION = "Sets the default working directory for the current session. Subsequent Git tool calls within this session can use '.' for the `path` parameter, which will resolve to this directory. Optionally validates if the path is a Git repository (`validateGitRepo: true`). Can optionally initialize a Git repository with 'git init' if it's not already one and `initializeIfNotPresent: true` is set. Returns the result as a JSON object. IMPORTANT: The provided path must be absolute."; /** * Registers the git_set_working_dir tool with the MCP server. * * @param {McpServer} server - The MCP server instance. * @throws {Error} If state accessors are not initialized. */ export async function registerGitSetWorkingDirTool(server) { // Check all required accessors if (!_getWorkingDirectory || !_setWorkingDirectory || !_getSessionId) { throw new Error("State accessors (getWD, setWD, getSID) for git_set_working_dir must be initialized before registration."); } try { server.tool(TOOL_NAME, TOOL_DESCRIPTION, GitSetWorkingDirInputSchema.shape, // Pass the shape for SDK validation async (validatedArgs, callContext) => { // Use callContext provided by SDK const operation = "tool:git_set_working_dir"; // Create a request context, potentially inheriting from callContext if it provides relevant info const requestContext = requestContextService.createRequestContext({ operation, parentContext: callContext, }); // Get session ID using the accessor function const sessionId = _getSessionId(requestContext); // Non-null assertion as we checked initialization // Define the session-specific setter function const setWorkingDirectoryForSession = (path) => { _setWorkingDirectory(sessionId, path); // Non-null assertion }; // Define the session-specific getter function (needed by logic?) // If the logic needs the current WD, pass the getter too. Assuming it might. const getWorkingDirectoryForSession = () => { return _getWorkingDirectory(sessionId); // Non-null assertion }; // Enhance context with session ID and the getter/setter functions const logicContext = { ...requestContext, sessionId: sessionId, getWorkingDirectory: getWorkingDirectoryForSession, // Pass getter setWorkingDirectory: setWorkingDirectoryForSession, // Pass setter }; return await ErrorHandler.tryCatch(async () => { // Call the core logic function with validated args and enhanced context const result = await gitSetWorkingDirLogic(validatedArgs, logicContext); // Format the successful result for the MCP client const responseContent = { type: "text", text: JSON.stringify(result, null, 2), // Pretty-print JSON result contentType: "application/json", }; logger.info(`Tool ${TOOL_NAME} executed successfully`, { ...logicContext, result, }); return { content: [responseContent] }; }, { operation, context: logicContext, input: validatedArgs, // Log sanitized input errorCode: BaseErrorCode.INTERNAL_ERROR, // Default error code if logic fails unexpectedly // toolName: TOOL_NAME, // Removed as it's not part of ErrorHandlerOptions }); }); logger.info(`Tool registered: ${TOOL_NAME}`); } catch (error) { logger.error(`Failed to register tool: ${TOOL_NAME}`, { error: error instanceof Error ? error.message : String(error), stack: error instanceof Error ? error.stack : undefined, }); // Propagate the error to prevent server startup if registration fails throw error; } }