Skip to main content
Glama
server.ts21.1 kB
/** * GIT MCP Server Implementation * * Main MCP server class that handles tool registration and execution. * Provides 17 specialized Git tools with multi-provider support. */ import { Server } from '@modelcontextprotocol/sdk/server/index.js'; import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'; import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, } from '@modelcontextprotocol/sdk/types.js'; import { GitWorkflowTool } from './tools/git-workflow.js'; import { GitBranchesTool } from './tools/git-branches.js'; import { GitFilesTool } from './tools/git-files.js'; import { GitIssuesTool } from './tools/git-issues.js'; import { GitPullsTool } from './tools/git-pulls.js'; import { GitTagsTool } from './tools/git-tags.js'; import { GitReleaseTool } from './tools/git-release.js'; import { GitRemoteTool } from './tools/git-remote.js'; import { GitResetTool } from './tools/git-reset.js'; import { GitStashTool } from './tools/git-stash.js'; import { GitConfigTool } from './tools/git-config.js'; import { GitMonitorTool } from './tools/git-monitor.js'; import { GitBackupTool } from './tools/git-backup.js'; import { GitArchiveTool } from './tools/git-archive.js'; import { GitSyncTool } from './tools/git-sync.js'; import { GitPackagesTool } from './tools/git-packages.js'; import { GitAnalyticsTool } from './tools/git-analytics.js'; import { GitUpdateTool } from './tools/git-update.js'; import { GitHistoryTool } from './tools/git-history.js'; import { getProviderConfig, configManager } from './config.js'; export class GitMCPServer { private server: Server; private transport: StdioServerTransport; private gitWorkflowTool!: GitWorkflowTool; private gitBranchesTool!: GitBranchesTool; private gitFilesTool!: GitFilesTool; private gitIssuesTool!: GitIssuesTool; private gitPullsTool!: GitPullsTool; private gitTagsTool!: GitTagsTool; private gitReleaseTool!: GitReleaseTool; private gitRemoteTool!: GitRemoteTool; private gitResetTool!: GitResetTool; private gitStashTool!: GitStashTool; private gitConfigTool!: GitConfigTool; private gitMonitorTool!: GitMonitorTool; private gitBackupTool!: GitBackupTool; private gitArchiveTool!: GitArchiveTool; private gitSyncTool!: GitSyncTool; private gitPackagesTool!: GitPackagesTool; private gitAnalyticsTool!: GitAnalyticsTool; private gitUpdateTool!: GitUpdateTool; private gitHistoryTool!: GitHistoryTool; constructor() { try { this.server = new Server( { name: 'git-mcp', version: '1.0.0', } ); this.transport = new StdioServerTransport(); // Initialize tools with provider configuration const providerConfig = getProviderConfig(); this.initializeTools(providerConfig); this.setupHandlers(); console.error('GIT MCP Server initialized successfully'); } catch (error) { console.error('Failed to initialize GIT MCP Server:', error); throw error; } } private initializeTools(providerConfig: any): void { try { // Initialize tools that require provider configuration this.gitWorkflowTool = new GitWorkflowTool(providerConfig); this.gitBranchesTool = new GitBranchesTool(providerConfig); this.gitFilesTool = new GitFilesTool(providerConfig); this.gitIssuesTool = new GitIssuesTool(providerConfig); this.gitPullsTool = new GitPullsTool(providerConfig); this.gitTagsTool = new GitTagsTool(providerConfig); this.gitReleaseTool = new GitReleaseTool(providerConfig); // Initialize tools that don't require provider configuration this.gitRemoteTool = new GitRemoteTool(); this.gitResetTool = new GitResetTool(providerConfig); this.gitStashTool = new GitStashTool(); this.gitConfigTool = new GitConfigTool(); this.gitMonitorTool = new GitMonitorTool(); this.gitBackupTool = new GitBackupTool(); this.gitArchiveTool = new GitArchiveTool(); // Initialize git-sync with provider configuration (for remote sync) this.gitSyncTool = new GitSyncTool(providerConfig); // Initialize git-packages and git-analytics with provider configuration this.gitPackagesTool = new GitPackagesTool(providerConfig); this.gitAnalyticsTool = new GitAnalyticsTool(providerConfig); this.gitUpdateTool = new GitUpdateTool(providerConfig); this.gitHistoryTool = new GitHistoryTool(providerConfig); console.error(`Initialized ${this.getRegisteredToolsCount()} Git tools`); } catch (error) { console.error('Failed to initialize Git tools:', error); throw error; } } private setupHandlers(): void { // List tools handler this.server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: [ GitWorkflowTool.getToolSchema(), GitFilesTool.getToolSchema(), GitBranchesTool.getToolSchema(), GitIssuesTool.getToolSchema(), GitPullsTool.getToolSchema(), GitTagsTool.getToolSchema(), GitReleaseTool.getToolSchema(), GitRemoteTool.getToolSchema(), GitResetTool.getToolSchema(), GitStashTool.getToolSchema(), GitConfigTool.getToolSchema(), GitMonitorTool.getToolSchema(), GitBackupTool.getToolSchema(), GitArchiveTool.getToolSchema(), GitSyncTool.getToolSchema(), GitPackagesTool.getToolSchema(), GitAnalyticsTool.getToolSchema(), GitUpdateTool.getToolSchema(), GitHistoryTool.getToolSchema() ] }; }); // Call tool handler this.server.setRequestHandler(CallToolRequestSchema, async (request: any) => { const { name, arguments: args } = request.params; try { // Validate tool exists if (!this.isValidTool(name)) { throw new Error(`Unknown tool: ${name}. Available tools: ${this.getAvailableToolNames().join(', ')}`); } // Execute tool with proper error handling const result = await this.executeTool(name, args); // Format successful response if (result.success) { return { content: [ { type: 'text', text: JSON.stringify(result.data, null, 2) } ] }; } else { // Format error response with detailed information return { content: [ { type: 'text', text: this.formatErrorResponse(result.error, name, args) } ], isError: true }; } } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error'; return { content: [ { type: 'text', text: `Tool execution failed: ${errorMessage}\n\nTool: ${name}\nArguments: ${JSON.stringify(args, null, 2)}` } ], isError: true }; } }); // List resources handler this.server.setRequestHandler(ListResourcesRequestSchema, async () => { return { resources: [ { uri: 'mcp-git://status', name: 'Server Status', description: 'Current server status and configuration', mimeType: 'application/json' }, { uri: 'mcp-git://tools', name: 'Available Tools', description: 'List of all available Git tools with detailed information', mimeType: 'application/json' } ] }; }); // Read resource handler this.server.setRequestHandler(ReadResourceRequestSchema, async (request: any) => { const { uri } = request.params; try { switch (uri) { case 'mcp-git://status': return this.getServerStatus(uri); case 'mcp-git://tools': return this.getToolsListing(uri); default: throw new Error(`Resource not found: ${uri}`); } } catch (error) { const errorMessage = error instanceof Error ? error.message : 'Unknown error'; throw new Error(`Failed to read resource ${uri}: ${errorMessage}`); } }); } private getServerStatus(uri: string) { const providerConfig = getProviderConfig(); const startTime = new Date().toISOString(); return { contents: [ { uri, mimeType: 'application/json', text: JSON.stringify({ status: 'running', version: '1.0.0', startTime, server: { name: 'git-mcp', description: 'Professional MCP server for Git operations with multi-provider support' }, providers: { github: { configured: !!providerConfig.github?.token, username: providerConfig.github?.username || null, status: providerConfig.github?.token ? 'ready' : 'not configured' }, gitea: { configured: !!providerConfig.gitea?.token, url: providerConfig.gitea?.url || null, username: providerConfig.gitea?.username || null, status: providerConfig.gitea?.token ? 'ready' : 'not configured' } }, mode: configManager.getMode(), universalMode: { enabled: configManager.isUniversalMode(), description: configManager.isUniversalMode() ? 'All operations automatically execute on both GitHub and Gitea providers' : 'Use provider parameter to specify GitHub, Gitea, or both' }, capabilities: { tools: true, resources: true, prompts: false }, toolsRegistered: this.getRegisteredToolsCount(), environment: { nodeVersion: process.version, platform: process.platform } }, null, 2) } ] }; } private getToolsListing(uri: string) { const implementedTools = [ { name: 'git-workflow', description: 'Core Git workflow operations (init, commit, sync, create, list, etc.)', category: 'Core Workflow', operations: ['init', 'commit', 'sync', 'status', 'backup', 'create', 'list', 'get', 'update', 'delete', 'fork', 'search'], implemented: true }, { name: 'git-files', description: 'File management operations (CRUD, search, backup, list)', category: 'File Management', operations: ['read', 'create', 'update', 'delete', 'search', 'backup', 'list'], implemented: true }, { name: 'git-branches', description: 'Branch lifecycle management (create, merge, compare)', category: 'Branch Management', operations: ['create', 'list', 'get', 'delete', 'merge', 'compare'], implemented: true }, { name: 'git-issues', description: 'Issue lifecycle management (create, update, comment)', category: 'Issue Management', operations: ['create', 'list', 'get', 'update', 'close', 'comment', 'search'], implemented: true }, { name: 'git-pulls', description: 'Pull request management (create, review, merge)', category: 'Pull Request Management', operations: ['create', 'list', 'get', 'update', 'merge', 'close', 'review', 'search'], implemented: true }, { name: 'git-tags', description: 'Tag management operations (create, list, delete)', category: 'Version Control', operations: ['create', 'list', 'get', 'delete', 'search'], implemented: true }, { name: 'git-release', description: 'Release management (create, publish, download)', category: 'Version Control', operations: ['create', 'list', 'get', 'update', 'delete', 'publish', 'download'], implemented: true }, { name: 'git-remote', description: 'Remote repository management (add, remove, rename)', category: 'Repository Operations', operations: ['add', 'remove', 'rename', 'show', 'set-url', 'prune'], implemented: true }, { name: 'git-reset', description: 'Reset operations (soft, mixed, hard)', category: 'Repository Operations', operations: ['soft', 'mixed', 'hard', 'reset-to-commit', 'reset-branch'], implemented: true }, { name: 'git-stash', description: 'Stash management (stash, pop, apply)', category: 'Repository Operations', operations: ['stash', 'pop', 'apply', 'list', 'show', 'drop', 'clear'], implemented: true }, { name: 'git-config', description: 'Git configuration management (get, set, list)', category: 'Configuration', operations: ['get', 'set', 'unset', 'list', 'edit', 'show'], implemented: true }, { name: 'git-monitor', description: 'Monitoring and logging (log, status, commits)', category: 'Monitoring', operations: ['log', 'status', 'commits', 'contributors'], implemented: true }, { name: 'git-backup', description: 'Backup system (backup, restore, verify)', category: 'Backup & Archive', operations: ['backup', 'restore', 'list', 'verify'], implemented: true }, { name: 'git-archive', description: 'Archive operations (create, extract, verify)', category: 'Backup & Archive', operations: ['create', 'extract', 'list', 'verify'], implemented: true }, { name: 'git-packages', description: 'Package management (list, create, publish)', category: 'Package Management', operations: ['list', 'get', 'create', 'update', 'delete', 'publish', 'download'], implemented: true }, { name: 'git-analytics', description: 'Analytics and statistics (stats, commits, contributors)', category: 'Analytics', operations: ['stats', 'commits', 'contributors'], implemented: true }, { name: 'git-sync', description: 'Advanced synchronization (sync, status)', category: 'Synchronization', operations: ['sync', 'status'], implemented: true } ]; const implementedCount = implementedTools.filter(tool => tool.implemented).length; const totalCount = implementedTools.length; return { contents: [ { uri, mimeType: 'application/json', text: JSON.stringify({ totalTools: totalCount, implementedTools: implementedCount, pendingTools: totalCount - implementedCount, tools: implementedTools, categories: { 'Core Workflow': implementedTools.filter(t => t.category === 'Core Workflow').length, 'File Management': implementedTools.filter(t => t.category === 'File Management').length, 'Branch Management': implementedTools.filter(t => t.category === 'Branch Management').length, 'Issue Management': implementedTools.filter(t => t.category === 'Issue Management').length, 'Pull Request Management': implementedTools.filter(t => t.category === 'Pull Request Management').length, 'Version Control': implementedTools.filter(t => t.category === 'Version Control').length, 'Repository Operations': implementedTools.filter(t => t.category === 'Repository Operations').length, 'Configuration': implementedTools.filter(t => t.category === 'Configuration').length, 'Monitoring': implementedTools.filter(t => t.category === 'Monitoring').length, 'Backup & Archive': implementedTools.filter(t => t.category === 'Backup & Archive').length, 'Package Management': implementedTools.filter(t => t.category === 'Package Management').length, 'Analytics': implementedTools.filter(t => t.category === 'Analytics').length, 'Synchronization': implementedTools.filter(t => t.category === 'Synchronization').length } }, null, 2) } ] }; } private isValidTool(toolName: string): boolean { const validTools = [ 'git-workflow', 'git-files', 'git-branches', 'git-issues', 'git-pulls', 'git-tags', 'git-release', 'git-remote', 'git-reset', 'git-stash', 'git-config', 'git-monitor', 'git-backup', 'git-archive', 'git-sync', 'git-packages', 'git-analytics', 'git-update', 'git-history' ]; return validTools.includes(toolName); } private getAvailableToolNames(): string[] { return [ 'git-workflow', 'git-files', 'git-branches', 'git-issues', 'git-pulls', 'git-tags', 'git-release', 'git-remote', 'git-reset', 'git-stash', 'git-config', 'git-monitor', 'git-backup', 'git-archive', 'git-sync', 'git-packages', 'git-analytics', 'git-update', 'git-history' ]; } private async executeTool(name: string, args: any): Promise<any> { switch (name) { case 'git-workflow': return await this.gitWorkflowTool.execute(args); case 'git-files': return await this.gitFilesTool.execute(args); case 'git-branches': return await this.gitBranchesTool.execute(args); case 'git-issues': return await this.gitIssuesTool.execute(args); case 'git-pulls': return await this.gitPullsTool.execute(args); case 'git-tags': return await this.gitTagsTool.execute(args); case 'git-release': return await this.gitReleaseTool.execute(args); case 'git-remote': return await this.gitRemoteTool.execute(args); case 'git-reset': return await this.gitResetTool.execute(args); case 'git-stash': return await this.gitStashTool.execute(args); case 'git-config': return await this.gitConfigTool.execute(args); case 'git-monitor': return await this.gitMonitorTool.execute(args); case 'git-backup': return await this.gitBackupTool.execute(args); case 'git-archive': return await this.gitArchiveTool.execute(args); case 'git-sync': return await this.gitSyncTool.execute(args); case 'git-packages': return await this.gitPackagesTool.execute(args); case 'git-analytics': return await this.gitAnalyticsTool.execute(args); case 'git-update': return await this.gitUpdateTool.execute(args); case 'git-history': return await this.gitHistoryTool.execute(args); default: throw new Error(`Tool execution not implemented: ${name}`); } } private formatErrorResponse(error: any, toolName: string, args: any): string { const errorInfo = { tool: toolName, error: { message: error?.message || 'Unknown error', code: error?.code || 'UNKNOWN_ERROR', details: error?.details || null, suggestions: error?.suggestions || [] }, arguments: args, timestamp: new Date().toISOString() }; return `Error executing ${toolName}:\n\n${JSON.stringify(errorInfo, null, 2)}`; } private getRegisteredToolsCount(): number { // Count currently registered tools return 18; // Currently 18 tools: workflow, files, branches, issues, pulls, tags, release, remote, reset, stash, config, monitor, backup, archive, sync, packages, analytics, update } async start(): Promise<void> { try { await this.server.connect(this.transport); console.error('GIT MCP Server started successfully'); console.error(`Server capabilities: tools=${this.getRegisteredToolsCount()}, resources=2`); // Log provider configuration status const providerConfig = getProviderConfig(); const githubConfigured = !!providerConfig.github?.token; const giteaConfigured = !!providerConfig.gitea?.token; console.error(`Provider status: GitHub=${githubConfigured ? 'configured' : 'not configured'}, Gitea=${giteaConfigured ? 'configured' : 'not configured'}`); // Log universal mode status const mode = configManager.getMode(); console.error(`Operation mode: ${mode}`); if (mode === 'universal') { console.error('⚡ Universal mode active: All operations will execute on both providers'); if (!githubConfigured || !giteaConfigured) { console.error('⚠️ Warning: Universal mode requires both providers configured'); } } } catch (error) { console.error('Failed to start GIT MCP Server:', error); throw error; } } }

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/Andre-Buzeli/git-mcp'

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