Skip to main content
Glama
blade47

ShadowGit MCP Server

by blade47

checkpoint

Create a git commit with your changes to save work progress. Use this tool after completing work but before ending a session to generate a clean commit for review.

Instructions

Create a git commit with your changes. Call this AFTER completing your work but BEFORE end_session. Creates a clean commit for the user to review.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
repoYesRepository name
titleYesCommit title (max 50 chars) - REQUIRED. Be specific about what was changed.
messageNoDetailed commit message (optional, max 1000 chars)
authorNoAuthor name (e.g., "Claude", "GPT-4"). Defaults to "AI Assistant"

Implementation Reference

  • Main handler logic for the 'checkpoint' tool. Validates input, checks for changes, stages all files with 'git add -A', creates a git commit with custom message and author, returns detailed success response with commit hash and change summary.
      async handle(args: unknown): Promise<MCPToolResponse> {
        if (!this.isValidArgs(args)) {
          return createErrorResponse(
            "Error: Both 'repo' and 'title' parameters are required.",
            `Example usage:
      checkpoint({
        repo: "my-project",
        title: "Fix authentication bug",
        author: "Claude"
      })
    
    Use list_repos() to see available repositories.`
          );
        }
        
        // Validate title length
        if (args.title.length > 50) {
          return createErrorResponse(
            `Error: Title must be 50 characters or less (current: ${args.title.length} chars).`
          );
        }
        
        // Validate message length if provided
        if (args.message && args.message.length > 1000) {
          return createErrorResponse(
            `Error: Message must be 1000 characters or less (current: ${args.message.length} chars).`
          );
        }
        
        const repoPath = this.repositoryManager.resolveRepoPath(args.repo);
        
        if (!repoPath) {
          const repos = this.repositoryManager.getRepositories();
          
          if (repos.length === 0) {
            return createErrorResponse(
              'Error: No repositories found. Please add repositories to ShadowGit first.'
            );
          }
          
          return createErrorResponse(
            `Error: Repository '${args.repo}' not found.`,
            `Available repositories:
    ${repos.map(r => `  - ${r.name}: ${r.path}`).join('\n')}`
          );
        }
    
    
        // Check for changes
        const statusOutput = await this.gitExecutor.execute(['status', '--porcelain'], repoPath, true);
        
        if (!statusOutput || statusOutput.trim() === '' || statusOutput === '(empty output)') {
          return createErrorResponse(
            `āŒ **No Changes Detected**
    ${'='.repeat(50)}
    
    šŸ“ Repository has no changes to commit.
    
    āš ļø **Important:** Do NOT call end_session() - no commit was created.
    
    šŸ’” **NEXT STEP:** Make some changes first, then call checkpoint() again.`
          );
        }
        
        // Build commit message
        const commitTitle = args.title;
        const commitBody = args.message || '';
        const author = args.author || 'AI Assistant';
        
        // Add all changes
        const addOutput = await this.gitExecutor.execute(['add', '-A'], repoPath, true);
        
        if (addOutput.startsWith('Error:')) {
          return createErrorResponse(
            `āŒ **Failed to Stage Changes**
    ${'='.repeat(50)}
    
    🚨 **Error:** ${addOutput}
    
    āš ļø **Important:** Do NOT call end_session() - commit was not created.
    
    šŸ’” **NEXT STEP:** Check the error and try again.`
          );
        }
        
        // Build full commit message
        let fullMessage = commitTitle;
        if (commitBody) {
          fullMessage += `\n\n${commitBody}`;
        }
        fullMessage += `\n\nAuthor: ${author} (via ShadowGit MCP)`;
        
        // Create commit with author information
        const commitEnv = {
          GIT_AUTHOR_NAME: author,
          GIT_AUTHOR_EMAIL: `${author.toLowerCase().replace(/\s+/g, '-')}@shadowgit.local`,
          GIT_COMMITTER_NAME: 'ShadowGit MCP',
          GIT_COMMITTER_EMAIL: 'shadowgit-mcp@shadowgit.local'
        };
        
        // Use array-based command to avoid parsing issues
        const commitOutput = await this.gitExecutor.execute(
          ['commit', '-m', fullMessage],
          repoPath,
          true,
          commitEnv
        );
        
        if (commitOutput.startsWith('Error:')) {
          return createErrorResponse(
            `āŒ **Failed to Create Commit**
    ${'='.repeat(50)}
    
    🚨 **Error:** ${commitOutput}
    
    āš ļø **Important:** Do NOT call end_session() - commit was not created.
    
    šŸ’” **NEXT STEP:** Check the error message and try checkpoint() again.`
          );
        }
        
        // Extract commit hash from output
        let commitHash: string | undefined;
        const hashMatch = commitOutput.match(/\[[\w\-]+ ([a-f0-9]+)\]/);
        if (hashMatch) {
          commitHash = hashMatch[1];
        }
        
        
        // Get summary of changes
        const showOutput = await this.gitExecutor.execute(['show', '--stat', '--format=short', 'HEAD'], repoPath, true);
        
        return {
          content: [
            {
              type: 'text',
              text: `āœ… **Checkpoint Created Successfully!**
    ${'='.repeat(50)}
    
    šŸ“¦ **Commit Details:**
    ${commitOutput}
    
    šŸ“Š **Changes Summary:**
    ${showOutput}
    
    šŸ”‘ **Commit Hash:** \`${commitHash || 'unknown'}\`
    
    ${'='.repeat(50)}
    
    šŸ“‹ **Workflow Progress:**
    - [x] Session started
    - [x] Changes made
    - [x] Checkpoint created ✨
    - [ ] Session ended
    
    🚨 **REQUIRED NEXT STEP:**
    You MUST now call \`end_session()\` to resume auto-commits:
    
    \`\`\`javascript
    end_session({
      sessionId: "your-session-id",
      commitHash: "${commitHash || 'unknown'}"
    })
    \`\`\`
    
    āš ļø **Important:** Only call end_session() because the commit was SUCCESSFUL.`
            }
          ],
          success: true
        };
      }
  • Tool registration in ListToolsRequestSchema handler, defining name, description, and input schema for the 'checkpoint' tool.
    {
      name: 'checkpoint',
      description: 'Create a git commit with your changes. Call this AFTER completing your work but BEFORE end_session. Creates a clean commit for the user to review.',
      inputSchema: {
        type: 'object',
        properties: {
          repo: {
            type: 'string',
            description: 'Repository name',
          },
          title: {
            type: 'string',
            description: 'Commit title (max 50 chars) - REQUIRED. Be specific about what was changed.',
          },
          message: {
            type: 'string',
            description: 'Detailed commit message (optional, max 1000 chars)',
          },
          author: {
            type: 'string',
            description: 'Author name (e.g., "Claude", "GPT-4"). Defaults to "AI Assistant"',
          },
        },
        required: ['repo', 'title'],
      },
    },
  • Switch case in CallToolRequestSchema handler that routes 'checkpoint' calls to CheckpointHandler.handle().
    case 'checkpoint':
      return await this.checkpointHandler.handle(args);
  • TypeScript interface defining the expected arguments for the checkpoint tool, used for validation in the handler.
    export interface ManualCheckpointArgs {
      repo: string;
      title: string;
      message?: string;
      author?: string;
    }
  • Helper method for validating checkpoint arguments against ManualCheckpointArgs type.
    private isValidArgs(args: unknown): args is ManualCheckpointArgs {
      return (
        typeof args === 'object' &&
        args !== null &&
        'repo' in args &&
        'title' in args &&
        typeof (args as ManualCheckpointArgs).repo === 'string' &&
        typeof (args as ManualCheckpointArgs).title === 'string'
      );
    }

Tool Definition Quality

Score is being calculated. Check back soon.

Install Server

Other 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/blade47/shadowgit-mcp'

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