Skip to main content
Glama

Git MCP Server

# Git MCP Server: Architectural Standard & Developer Mandate **Effective Date:** 2025-07-15 **Version:** 2.1 ## Preamble This document constitutes the official mandate governing all development practices, architectural patterns, and operational procedures for the `git-mcp-server`. It merges the project's original cheatsheet with the new architectural standards. Adherence to these standards is not optional. ## I. Core Architectural Principles ### 1. The Logic Throws, The Handler Catches This is the immutable cornerstone of our error-handling and control-flow strategy. - **Core Logic (`logic.ts`):** This layer's sole responsibility is the execution of pure business logic (e.g., running a Git command). It must be self-contained. If an operational or validation error occurs, it **must** terminate its execution by **throwing a structured `McpError`**. Logic files shall **not** contain `try...catch` blocks for formatting a final response. - **Handlers (`registration.ts`):** This layer's responsibility is to interface with the MCP server, invoke core logic, and manage the final response lifecycle. It **must** wrap every call to the logic layer in a `try...catch` block. This is the **exclusive** location where errors are caught, processed by the `ErrorHandler`, and formatted into a definitive `CallToolResult`. ### 2. Structured, Traceable Operations Every operation must be fully traceable via structured logging and context propagation. - **RequestContext:** Any significant operation shall be initiated by creating a `RequestContext`. This context, containing a unique `requestId`, **must** be passed as an argument through the entire call stack. - **Logger:** All logging shall be performed through the centralized `logger` singleton. Every log entry **must** include the `RequestContext`. ## II. Tool Development Workflow This section mandates the workflow for creating and modifying all Git tools. ### A. File and Directory Structure Each tool shall reside in a dedicated directory within `src/mcp-server/tools/`. The structure is fixed: - **`toolName/`** - `index.ts`: Barrel file exporting only the `register...` function. - `logic.ts`: Contains the tool's core logic, Zod schemas (input and output), and all inferred TypeScript types. - `registration.ts`: Registers the tool, implementing the "Handler" role. ### B. The Canonical Pattern for Git Tools The following pattern is the authoritative implementation for all tool development. **Step 1: Define Schema and Logic (`logic.ts`)** ```typescript /** * @fileoverview Defines the core logic, schemas, and types for a Git tool. * @module src/mcp-server/tools/gitTool/logic */ import { z } from "zod"; import { logger, type RequestContext, sanitization, } from "../../../utils/index.js"; import { BaseErrorCode, McpError } from "../../../types-global/errors.js"; // 1. DEFINE the Zod input schema. // CRITICAL: Descriptions are sent to the LLM. They must be clear, concise, // and contain all necessary context for the model to use the tool effectively. export const GitToolInputSchema = z.object({ path: z.string().default(".").describe("Path to the Git repository."), // ... other parameters }); // 2. DEFINE the Zod response schema for structured output. export const GitToolOutputSchema = z.object({ success: z.boolean().describe("Indicates if the command was successful."), // ... other structured output fields }); // 3. INFER and export TypeScript types. export type GitToolInput = z.infer<typeof GitToolInputSchema>; export type GitToolOutput = z.infer<typeof GitToolOutputSchema>; /** * 4. IMPLEMENT the core logic function. * It must remain pure; its only concerns are its inputs and its return value or thrown error. * @param params The validated input parameters. * @param context The request context for logging and tracing. * @returns A promise resolving with the structured response data. * @throws {McpError} If the logic encounters an unrecoverable issue. */ export async function gitToolLogic( params: GitToolInput, context: RequestContext & { getWorkingDirectory: () => string | undefined }, ): Promise<GitToolOutput> { logger.debug("Executing gitToolLogic...", { ...context }); // Path resolution and sanitization logic here... // Example of a logic failure. if (someConditionFails) { // CRITICAL: Logic layer MUST throw a structured error on failure. throw new McpError( BaseErrorCode.VALIDATION_ERROR, "A specific error message.", ); } // Execute git command... // On success, RETURN a structured output object. return { success: true /* ...other data */ }; } ``` **Step 2: Register the Tool and Handle Outcomes (`registration.ts`)** ```typescript /** * @fileoverview Handles registration and error handling for the Git tool. * @module src/mcp-server/tools/gitTool/registration */ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { ErrorHandler, logger, requestContextService, } from "../../../utils/index.js"; import { GitToolInput, GitToolInputSchema, gitToolLogic, GitToolOutputSchema, } from "./logic.js"; import { McpError } from "../../../types-global/errors.js"; export type GetWorkingDirectoryFn = ( sessionId: string | undefined, ) => string | undefined; export type GetSessionIdFn = (context: RequestContext) => string | undefined; /** * Registers the tool with the MCP server instance. * @param server The MCP server instance. * @param getWorkingDirectory Function to get the session's working directory. * @param getSessionId Function to get the session ID from context. */ export const registerGitTool = async ( server: McpServer, getWorkingDirectory: GetWorkingDirectoryFn, getSessionId: GetSessionIdFn, ): Promise<void> => { const toolName = "git_tool_name"; server.registerTool( toolName, { title: "Git Tool Title", description: "A clear, concise description for the LLM.", inputSchema: GitToolInputSchema.shape, outputSchema: GitToolOutputSchema.shape, // MANDATORY annotations: { readOnlyHint: false /* ...other hints */ }, }, async (params: GitToolInput, callContext) => { const handlerContext = requestContextService.createRequestContext({ toolName, parentContext: callContext, }); try { const sessionId = getSessionId(handlerContext); const result = await gitToolLogic(params, { ...handlerContext, getWorkingDirectory: () => getWorkingDirectory(sessionId), }); return { structuredContent: result, content: [ { type: "text", text: `Success: ${JSON.stringify(result)}` }, ], }; } catch (error) { logger.error(`Error in ${toolName} handler`, { error, ...handlerContext, }); const mcpError = ErrorHandler.handleError(error, { operation: toolName, context: handlerContext, input: params, }) as McpError; return { isError: true, content: [{ type: "text", text: mcpError.message }], structuredContent: { code: mcpError.code, message: mcpError.message, details: mcpError.details, }, }; } }, ); logger.info(`Tool '${toolName}' registered successfully.`); }; ``` ## III. Code Quality and Documentation Mandates - **JSDoc:** Every file shall begin with a `@fileoverview` and `@module` block. All exported functions, types, and classes shall have complete JSDoc comments. - **LLM-Facing Descriptions:** The tool's `title`, `description`, and all parameter descriptions in Zod schemas (`.describe()`) are transmitted directly to the LLM. They must be written with the LLM as the primary audience, being descriptive, concise, and explicit about requirements. - **Clarity and Intent:** Code shall be self-documenting. Variable and function names must be explicit and unambiguous. - **Formatting:** All code must be formatted using Prettier (`npm run format`) before being committed. - **Linting:** All code must pass ESLint checks (`npm run lint`) before being committed. ## IV. Security Mandates - **Input Sanitization:** All input shall be treated as untrusted and validated with Zod. Use `sanitization` utilities for explicit sanitization, especially for file paths. - **Secrets Management:** All secrets (API keys, credentials) shall be loaded exclusively from environment variables via the `config` module. ## V. Server Configuration & Operation (Cheatsheet) ### Environment Variables - **`MCP_TRANSPORT_TYPE`**: `"stdio"` (default) or `"http"`. - **`MCP_HTTP_PORT`**: Default `3015`. - **`MCP_HTTP_HOST`**: Default `127.0.0.1`. - **`MCP_ALLOWED_ORIGINS`**: Comma-separated list for CORS. - **`MCP_LOG_LEVEL`**: `debug`, `info`, `warning`, `error`, etc. Default `info`. - **`GIT_SIGN_COMMITS`**: Set to `"true"` to enable GPG/SSH signing for commits. ### Running the Server - **Production (Stdio)**: `npm run start:stdio` - **Production (HTTP)**: `npm run start:http` - **Development (Stdio)**: `npm run dev:stdio` - **Development (HTTP)**: `npm run dev:http` ### Core Utilities - **Logging**: `src/utils/internal/logger.ts` - **Error Handling**: `src/types-global/errors.ts`, `src/utils/internal/errorHandler.ts` - **Request Context**: `src/utils/internal/requestContext.ts` - **Sanitization**: `src/utils/security/sanitization.ts`

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