Skip to main content
Glama
MrOrz

git-commit-aider MCP Server

by MrOrz

commit_staged

Stage and commit changes with a custom message while appending "(aider)" to the committer name, enabling clear tracking of AI contributions in your codebase.

Instructions

Commit staged changes with a specific message, appending "(aider)" to the committer name.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
cwdNoOptional: The working directory for the git command (defaults to the workspace root).
messageYesThe commit message.

Implementation Reference

  • Handler for executing the commit_staged tool. Validates input, retrieves committer info from env or git config, appends '(aider)' to name, and executes 'git commit -m <message> --author=<aider_name> <email>'.
    server.setRequestHandler(CallToolRequestSchema, async (request) => {
        if (request.params.name !== 'commit_staged') {
            throw new McpError(
                ErrorCode.MethodNotFound,
                `Unknown tool: ${request.params.name}`
            );
        }
    
        if (!isValidCommitArgs(request.params.arguments)) {
            throw new McpError(
                ErrorCode.InvalidParams,
                'Invalid arguments for commit_staged. Requires "message" (string) and optional "cwd" (string).'
            );
        }
    
        const { message, cwd } = request.params.arguments;
        const executionOptions = { cwd: cwd || '' };
    
        try {
            let committerName: string;
            let committerEmail: string;
    
            // Get committer name: prioritize env var, fallback to git config
            const envName = process.env.GIT_COMMITTER_NAME;
            if (envName) {
                committerName = envName;
                console.error('Using committer name from environment variable.');
            } else {
                console.error('GIT_COMMITTER_NAME not set, falling back to git config user.name.');
                try {
                    const { stdout: nameOutput } = await execa('git', ['config', 'user.name'], executionOptions);
                    committerName = nameOutput.trim();
                    if (!committerName) {
                        throw new Error('Git user.name is empty.');
                    }
                    console.error(`Using committer name from git config: ${committerName}`);
                } catch (configError: any) {
                    const configErrorMessage = configError?.stderr || configError?.stdout || configError?.shortMessage || configError?.message || 'Unknown error getting git config user.name.';
                    throw new McpError(
                        ErrorCode.InternalError,
                        `Failed to get git user.name: ${configErrorMessage}. Please ensure git user.name is configured or set the GIT_COMMITTER_NAME environment variable.`
                    );
                }
            }
    
            // Get committer email: prioritize env var, fallback to git config
            const envEmail = process.env.GIT_COMMITTER_EMAIL;
            if (envEmail) {
                committerEmail = envEmail;
                console.error('Using committer email from environment variable.');
            } else {
                console.error('GIT_COMMITTER_EMAIL not set, falling back to git config user.email.');
                try {
                    const { stdout: emailOutput } = await execa('git', ['config', 'user.email'], executionOptions);
                    committerEmail = emailOutput.trim();
                     if (!committerEmail) {
                        throw new Error('Git user.email is empty.');
                    }
                    console.error(`Using committer email from git config: ${committerEmail}`);
                } catch (configError: any) {
                    const configErrorMessage = configError?.stderr || configError?.stdout || configError?.shortMessage || configError?.message || 'Unknown error getting git config user.email.';
                     throw new McpError(
                        ErrorCode.InternalError,
                        `Failed to get git user.email: ${configErrorMessage}. Please ensure git user.email is configured or set the GIT_COMMITTER_EMAIL environment variable.`
                    );
                }
            }
    
            // Construct the aider committer string
            const aiderName = `${committerName} (aider)`;
            const authorString = `${aiderName} <${committerEmail}>`;
    
            // Execute the git commit command
            console.error(`Executing: git commit -m "${message}" --author="${authorString}"`);
            const { stdout, stderr } = await execa(
                'git',
                ['commit', '-m', message, `--author=${authorString}`],
                executionOptions
            );
    
            return {
                content: [
                    {
                        type: 'text',
                        text: `Commit successful:\n${stdout}\n${stderr ? `Stderr:\n${stderr}` : ''}`,
                    },
                ],
            };
        } catch (error: any) {
             // Handle McpError specifically if thrown from git config fallback
             if (error instanceof McpError) {
                 return {
                     content: [{ type: 'text', text: error.message }],
                     isError: true,
                 };
             }
    
             // Handle other errors (likely from the commit command itself)
             const errorMessage = error?.stderr || error?.stdout || error?.shortMessage || error?.message || 'Unknown error during git commit.';
             // Check for specific git errors like "nothing to commit"
             if (errorMessage.includes('nothing to commit, working tree clean') || errorMessage.includes('no changes added to commit')) {
                 return {
                     content: [{ type: 'text', text: `Git commit skipped: ${errorMessage}` }],
                     isError: false, // Not technically an error in execution, just nothing happened
                 };
             }
             // Return a more specific error message if possible
             return {
                 content: [{ type: 'text', text: `Git commit failed: ${errorMessage}` }],
                 isError: true,
             };
        }
    });
  • src/index.ts:38-59 (registration)
    Registration of the commit_staged tool via ListToolsRequestSchema handler, including name, description, and input schema.
    server.setRequestHandler(ListToolsRequestSchema, async () => ({
        tools: [
            {
                name: 'commit_staged',
                description: 'Commit staged changes with a specific message, appending "(aider)" to the committer name.',
                inputSchema: {
                    type: 'object',
                    properties: {
                        message: {
                            type: 'string',
                            description: 'The commit message.',
                        },
                        cwd: {
                            type: 'string',
                            description: 'Optional: The working directory for the git command (defaults to the workspace root).',
                        }
                    },
                    required: ['message'],
                },
            },
        ],
    }));
  • Helper function to validate commit_staged arguments: requires 'message' string and optional 'cwd' string.
    // Helper function to validate arguments for the commit_staged tool
    const isValidCommitArgs = (
        args: any
    ): args is { message: string; cwd?: string } =>
        typeof args === 'object' &&
        args !== null &&
        typeof args.message === 'string' &&
        (args.cwd === undefined || typeof args.cwd === 'string');
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It mentions the committer name modification but fails to describe other critical behaviors: whether this is a read-only or destructive operation, error handling (e.g., if no staged changes exist), or side effects. The description is insufficient for a mutation tool with zero annotation coverage.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence that front-loads the core action and includes a unique behavioral detail (appending '(aider)'). There is zero waste, and it is appropriately sized for the tool's complexity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's moderate complexity (2 parameters, no output schema, no annotations), the description is minimally adequate. It covers the basic purpose and a unique trait but lacks details on usage context, behavioral transparency, and error handling, leaving gaps for an AI agent to infer correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents both parameters ('cwd' and 'message') adequately. The description adds no additional meaning beyond the schema, such as format details or usage examples. Baseline 3 is appropriate when the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb ('commit') and resource ('staged changes') with a specific action ('with a specific message, appending "(aider)" to the committer name'). It distinguishes the tool by mentioning the unique committer name modification. However, without sibling tools, differentiation is not explicitly needed, so it doesn't fully earn a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives, prerequisites (e.g., having staged changes), or exclusions. It lacks context about typical workflows or related tools, offering only basic functional information.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Related Tools

Latest Blog Posts

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/MrOrz/mcp-git-commit-aider'

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