@andrebuzeli/git-mcp 10.0.3 → 10.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +37 -56
  2. package/dist/index.js +50 -13
  3. package/dist/server-new.d.ts +2 -0
  4. package/dist/server-new.js +224 -0
  5. package/dist/tools/gitArchive.d.ts +0 -8
  6. package/dist/tools/gitArchive.js +4 -12
  7. package/dist/tools/gitBackup.js +7 -7
  8. package/dist/tools/gitFiles-new.d.ts +89 -0
  9. package/dist/tools/gitFiles-new.js +335 -0
  10. package/dist/tools/gitFiles.d.ts +18 -15
  11. package/dist/tools/gitFiles.js +54 -15
  12. package/dist/tools/gitFix.js +7 -7
  13. package/dist/tools/gitFix.tool.js +4 -4
  14. package/dist/tools/gitHistory.d.ts +2 -25
  15. package/dist/tools/gitHistory.js +4 -25
  16. package/dist/tools/gitIgnore.d.ts +2 -14
  17. package/dist/tools/gitIgnore.js +5 -17
  18. package/dist/tools/gitIssues.d.ts +0 -4
  19. package/dist/tools/gitIssues.js +12 -18
  20. package/dist/tools/gitMonitor.js +1 -1
  21. package/dist/tools/gitPackages.d.ts +28 -0
  22. package/dist/tools/gitPackages.js +29 -1
  23. package/dist/tools/gitPulls.d.ts +60 -0
  24. package/dist/tools/gitPulls.js +68 -4
  25. package/dist/tools/gitRelease.d.ts +43 -0
  26. package/dist/tools/gitRelease.js +48 -4
  27. package/dist/tools/gitRemote.d.ts +23 -0
  28. package/dist/tools/gitRemote.js +23 -0
  29. package/dist/tools/gitReset.d.ts +23 -0
  30. package/dist/tools/gitReset.js +23 -0
  31. package/dist/tools/gitStash.d.ts +31 -0
  32. package/dist/tools/gitStash.js +31 -0
  33. package/dist/tools/gitSync.d.ts +6 -2
  34. package/dist/tools/gitSync.js +10 -6
  35. package/dist/tools/gitTags.d.ts +31 -0
  36. package/dist/tools/gitTags.js +31 -0
  37. package/dist/tools/gitUpdate.d.ts +0 -27
  38. package/dist/tools/gitUpdate.js +1 -26
  39. package/dist/tools/gitUpload.d.ts +2 -9
  40. package/dist/tools/gitUpload.js +81 -42
  41. package/dist/tools/gitWorkflow.d.ts +8 -0
  42. package/dist/tools/gitWorkflow.js +37 -3
  43. package/dist/utils/cache.d.ts +96 -0
  44. package/dist/utils/cache.js +208 -0
  45. package/dist/utils/gitAdapter.js +19 -3
  46. package/dist/utils/logger.d.ts +45 -0
  47. package/dist/utils/logger.js +140 -0
  48. package/dist/utils/rateLimiter.d.ts +113 -0
  49. package/dist/utils/rateLimiter.js +257 -0
  50. package/dist/utils/validation.d.ts +115 -0
  51. package/dist/utils/validation.js +270 -0
  52. package/package.json +1 -1
  53. package/dist/config.d.ts +0 -5
  54. package/dist/config.js +0 -35
package/README.md CHANGED
@@ -102,26 +102,47 @@ npx @andrebuzeli/git-mcp@latest
102
102
 
103
103
  ### Configuration
104
104
 
105
- Set up your provider credentials via environment variables:
105
+ Configure the git-mcp server in your MCP client's configuration file (e.g., Cursor's mcp.json, Claude Desktop's config, etc.):
106
106
 
107
- #### GitHub Configuration
108
- ```bash
109
- export GITHUB_TOKEN="your_github_token"
110
- export GITHUB_USERNAME="your_username"
107
+ ```json
108
+ {
109
+ "mcpServers": {
110
+ "git-mcp": {
111
+ "command": "npx",
112
+ "args": ["@andrebuzeli/git-mcp@latest"],
113
+ "env": {
114
+ "GITHUB_USERNAME": "your-github-username",
115
+ "GITHUB_TOKEN": "ghp_your_github_token_here",
116
+ "GITEA_USERNAME": "your-gitea-username",
117
+ "GITEA_TOKEN": "your_gitea_token_here",
118
+ "GITEA_URL": "https://your-gitea-instance.com/",
119
+ "DEBUG": "false"
120
+ }
121
+ }
122
+ }
123
+ }
111
124
  ```
112
125
 
113
- #### Gitea Configuration
126
+ **The MCP client automatically passes these environment variables to the git-mcp server - no additional configuration files needed!**
127
+
128
+ #### Alternative: Direct Environment Variables
129
+ If running the server directly (not through MCP client):
130
+
114
131
  ```bash
132
+ export GITHUB_TOKEN="your_github_token"
133
+ export GITHUB_USERNAME="your_username"
115
134
  export GITEA_URL="https://your-gitea-instance.com"
116
135
  export GITEA_TOKEN="your_gitea_token"
117
136
  export GITEA_USERNAME="your_username"
118
137
  ```
119
138
 
120
- PowerShell (Windows) example - session only:
139
+ #### PowerShell (Windows)
121
140
  ```powershell
122
141
  $env:GITEA_URL = 'https://your-gitea-instance.com'
123
142
  $env:GITEA_TOKEN = 'your_gitea_token'
124
143
  $env:GITEA_USERNAME = 'your_username'
144
+ $env:GITHUB_TOKEN = 'your_github_token'
145
+ $env:GITHUB_USERNAME = 'your_username'
125
146
  ```
126
147
 
127
148
  #### Multi-Provider Support
@@ -332,63 +353,23 @@ All tools provide detailed error messages with actionable solutions:
332
353
  | `DETACHED_HEAD` | Repository in detached HEAD state | Create branch or checkout existing |
333
354
  | `REF_LOCK_ERROR` | Cannot lock Git reference | Wait for other operations to complete |
334
355
 
335
- ## Configuration Guide
336
-
337
- ### Environment Variables
338
-
339
- **Required for GitHub:**
340
- - `GITHUB_TOKEN` - Personal access token with repo permissions
341
- - `GITHUB_USERNAME` - Your GitHub username
356
+ ## Setup Instructions
342
357
 
343
- **Required for Gitea:**
344
- - `GITEA_URL` - Your Gitea instance URL (e.g., `https://git.example.com`)
345
- - `GITEA_TOKEN` - Personal access token
346
- - `GITEA_USERNAME` - Your Gitea username
358
+ 1. **Configure your MCP client** with the git-mcp server and your credentials (see Configuration section above)
347
359
 
348
- ### Credential Validation
349
-
350
- The server automatically validates credentials on startup:
351
-
352
- - ✅ **Valid credentials** - API connectivity confirmed
353
- - ❌ **Invalid token** - Authentication failed
354
- - 🌐 **Network error** - Cannot reach provider API
355
- - ⚠️ **Partial failure** - Some providers failed validation
356
-
357
- ### Setup Instructions
358
-
359
- 1. **Generate GitHub Token:**
360
+ 2. **Generate GitHub Token:**
360
361
  - Go to GitHub Settings → Developer settings → Personal access tokens
361
362
  - Create token with `repo` scope
362
- - Copy token to `GITHUB_TOKEN` environment variable
363
+ - Add to your MCP client configuration
363
364
 
364
- 2. **Generate Gitea Token:**
365
+ 3. **Generate Gitea Token:**
365
366
  - Go to your Gitea instance → Settings → Applications
366
367
  - Generate new token with appropriate permissions
367
- - Copy token to `GITEA_TOKEN` environment variable
368
-
369
- 3. **Test Configuration:**
370
- ```bash
371
- # Start the server to see validation results
372
- npx @andrebuzeli/git-mcp@latest
373
- ```
374
-
375
- Optional: use a local `mcp.json` (NOT committed) to keep credentials for local testing.
376
-
377
- 1. Create `mcp.json` next to package.json with this shape (use the `.example` as a starting point):
378
-
379
- ```json
380
- {
381
- "env": {
382
- "GITEA_URL": "http://nas-ubuntu:3000",
383
- "GITEA_TOKEN": "<GITEA_TOKEN>",
384
- "GITEA_USERNAME": "<GITEA_USERNAME>",
385
- "GITHUB_TOKEN": "<GITHUB_TOKEN>",
386
- "GITHUB_USERNAME": "<GITHUB_USERNAME>"
387
- }
388
- }
389
- ```
368
+ - Add to your MCP client configuration
390
369
 
391
- Security note: do NOT commit `mcp.json` with real tokens. The repository's `.gitignore` includes `mcp.json` to help avoid leaks.
370
+ 4. **Test Configuration:**
371
+ - Restart your MCP client
372
+ - Try using git-mcp tools in your IDE
392
373
 
393
374
  ## Troubleshooting
394
375
 
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
3
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
4
  import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
5
5
  import { ProviderManager } from './providers/providerManager.js';
6
- import { loadMCPConfig } from './config.js';
6
+ import { MCPError } from './utils/errors.js';
7
7
  import { IsomorphicGitAdapter } from './utils/gitAdapter.js';
8
8
  import { GitFilesTool } from './tools/gitFiles.js';
9
9
  import { GitWorkflowTool } from './tools/gitWorkflow.js';
@@ -29,11 +29,11 @@ import { GitFixTool } from './tools/gitFix.tool.js';
29
29
  import { GitIgnoreTool } from './tools/gitIgnore.js';
30
30
  import { GIT_PROMPTS } from './prompts/gitPrompts.js';
31
31
  import TOOLS_GUIDE from './resources/toolsGuide.js';
32
+ import { Logger, logToolExecution, logSecurityEvent, logPerformanceMetric } from './utils/logger.js';
32
33
  async function main() {
33
- // Load optional mcp.json configuration (will populate process.env if values present)
34
- loadMCPConfig();
35
34
  const providerManager = new ProviderManager();
36
35
  const gitAdapter = new IsomorphicGitAdapter(providerManager);
36
+ const logger = Logger.getInstance();
37
37
  // Skip validation on startup to prevent hanging (validation happens on first use)
38
38
  // Provider validation moved to lazy initialization
39
39
  // Register all 22 Git tools
@@ -67,17 +67,18 @@ async function main() {
67
67
  ];
68
68
  // Silent mode for MCP clients - only log to stderr in debug mode
69
69
  if (process.env.DEBUG) {
70
- console.error(`Registered ${tools.length} Git tools`);
71
- console.error(`Registered ${resources.length} resource(s)`);
72
- console.error(`Registered ${GIT_PROMPTS.length} prompt(s)`);
70
+ logger.info(`Registered ${tools.length} Git tools`);
71
+ logger.info(`Registered ${resources.length} resource(s)`);
72
+ logger.info(`Registered ${GIT_PROMPTS.length} prompt(s)`);
73
73
  }
74
74
  // Create MCP Server with STDIO transport
75
75
  const server = new Server({
76
76
  name: '@andrebuzeli/git-mcp',
77
- version: '10.0.1',
77
+ version: '10.0.4',
78
78
  });
79
79
  // Register tool list handler
80
80
  server.setRequestHandler(ListToolsRequestSchema, async () => {
81
+ logger.debug('Listing available tools');
81
82
  return {
82
83
  tools: tools.map(tool => ({
83
84
  name: tool.name,
@@ -90,15 +91,42 @@ async function main() {
90
91
  })),
91
92
  };
92
93
  });
93
- // Register tool execution handler
94
+ // Register tool execution handler with logging e segurança aprimorados
94
95
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
95
96
  const toolName = request.params.name;
96
97
  const tool = tools.find(t => t.name === toolName);
98
+ const startTime = Date.now();
97
99
  if (!tool) {
100
+ logSecurityEvent('TOOL_NOT_FOUND', { toolName });
98
101
  throw new Error(`Tool not found: ${toolName}`);
99
102
  }
100
103
  try {
101
- const result = await tool.handle(request.params.arguments ?? {}, { providerManager, gitAdapter });
104
+ // Validar argumentos contra o schema da ferramenta
105
+ const args = request.params.arguments ?? {};
106
+ // Validação básica de segurança
107
+ if (typeof args !== 'object' || args === null) {
108
+ logSecurityEvent('INVALID_ARGUMENTS', { toolName, args });
109
+ throw new MCPError('VALIDATION_ERROR', 'Arguments must be an object');
110
+ }
111
+ // Validar projectPath se existir
112
+ if ('projectPath' in args) {
113
+ const projectPath = args.projectPath;
114
+ if (typeof projectPath !== 'string') {
115
+ logSecurityEvent('INVALID_PROJECT_PATH_TYPE', { toolName, projectPath });
116
+ throw new MCPError('VALIDATION_ERROR', 'projectPath must be a string');
117
+ }
118
+ if (!projectPath || projectPath.includes('..')) {
119
+ logSecurityEvent('PATH_TRAVERSION_ATTEMPT', { toolName, projectPath });
120
+ throw new MCPError('VALIDATION_ERROR', 'Invalid project path');
121
+ }
122
+ }
123
+ // Log da execução
124
+ logger.info(`Executing tool: ${toolName}`, { args }, toolName);
125
+ // Executar a ferramenta
126
+ const result = await tool.handle(args, { providerManager, gitAdapter });
127
+ const duration = Date.now() - startTime;
128
+ logPerformanceMetric(`tool_${toolName}`, duration, { success: true });
129
+ logToolExecution(toolName, args, result);
102
130
  return {
103
131
  content: [
104
132
  {
@@ -109,6 +137,9 @@ async function main() {
109
137
  };
110
138
  }
111
139
  catch (error) {
140
+ const duration = Date.now() - startTime;
141
+ logPerformanceMetric(`tool_${toolName}`, duration, { success: false, error: error.message });
142
+ logToolExecution(toolName, request.params.arguments ?? {}, undefined, error);
112
143
  return {
113
144
  content: [
114
145
  {
@@ -122,6 +153,7 @@ async function main() {
122
153
  });
123
154
  // Register resource list handler
124
155
  server.setRequestHandler(ListResourcesRequestSchema, async () => {
156
+ logger.debug('Listing available resources');
125
157
  return {
126
158
  resources: resources.map(resource => ({
127
159
  uri: resource.uri,
@@ -136,8 +168,10 @@ async function main() {
136
168
  const uri = request.params.uri;
137
169
  const resource = resources.find(r => r.uri === uri);
138
170
  if (!resource) {
171
+ logger.warn(`Resource not found: ${uri}`);
139
172
  throw new Error(`Resource not found: ${uri}`);
140
173
  }
174
+ logger.debug(`Reading resource: ${uri}`);
141
175
  return {
142
176
  contents: [
143
177
  {
@@ -150,6 +184,7 @@ async function main() {
150
184
  });
151
185
  // Register prompt list handler
152
186
  server.setRequestHandler(ListPromptsRequestSchema, async () => {
187
+ logger.debug('Listing available prompts');
153
188
  return {
154
189
  prompts: GIT_PROMPTS.map(prompt => ({
155
190
  name: prompt.name,
@@ -163,8 +198,10 @@ async function main() {
163
198
  const promptName = request.params.name;
164
199
  const prompt = GIT_PROMPTS.find(p => p.name === promptName);
165
200
  if (!prompt) {
201
+ logger.warn(`Prompt not found: ${promptName}`);
166
202
  throw new Error(`Prompt not found: ${promptName}`);
167
203
  }
204
+ logger.debug(`Generating prompt: ${promptName}`);
168
205
  const result = await prompt.generate(request.params.arguments ?? {}, { providerManager, gitAdapter });
169
206
  return {
170
207
  description: result.description,
@@ -175,10 +212,10 @@ async function main() {
175
212
  await server.connect(transport);
176
213
  // Only log in debug mode
177
214
  if (process.env.DEBUG) {
178
- console.error(`✅ git-mcp MCP server running via STDIO`);
179
- console.error(`Tools: ${tools.length} registered`);
180
- console.error(`Resources: ${resources.length} registered`);
181
- console.error(`Prompts: ${GIT_PROMPTS.length} registered`);
215
+ logger.info(`✅ git-mcp MCP server running via STDIO`);
216
+ logger.info(`Tools: ${tools.length} registered`);
217
+ logger.info(`Resources: ${resources.length} registered`);
218
+ logger.info(`Prompts: ${GIT_PROMPTS.length} registered`);
182
219
  }
183
220
  }
184
221
  main().catch(err => {
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,224 @@
1
+ #!/usr/bin/env node
2
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
3
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
4
+ import { CallToolRequestSchema, ListToolsRequestSchema, ListResourcesRequestSchema, ReadResourceRequestSchema, ListPromptsRequestSchema, GetPromptRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
5
+ import { ProviderManager } from './providers/providerManager.js';
6
+ import { MCPError } from './utils/errors.js';
7
+ import { IsomorphicGitAdapter } from './utils/gitAdapter.js';
8
+ import { GitFilesTool } from './tools/gitFiles.js';
9
+ import { GitWorkflowTool } from './tools/gitWorkflow.js';
10
+ import { GitBranchesTool } from './tools/gitBranches.js';
11
+ import { GitIssuesTool } from './tools/gitIssues.js';
12
+ import { GitPullsTool } from './tools/gitPulls.js';
13
+ import { GitTagsTool } from './tools/gitTags.js';
14
+ import { GitReleaseTool } from './tools/gitRelease.js';
15
+ import { GitRemoteTool } from './tools/gitRemote.js';
16
+ import { GitResetTool } from './tools/gitReset.js';
17
+ import { GitStashTool } from './tools/gitStash.js';
18
+ import { GitConfigTool } from './tools/gitConfig.js';
19
+ import { GitMonitorTool } from './tools/gitMonitor.js';
20
+ import { GitBackupTool } from './tools/gitBackup.js';
21
+ import { GitArchiveTool } from './tools/gitArchive.js';
22
+ import { GitSyncTool } from './tools/gitSync.js';
23
+ import { GitPackagesTool } from './tools/gitPackages.js';
24
+ import { GitAnalyticsTool } from './tools/gitAnalytics.js';
25
+ import { GitUploadTool } from './tools/gitUpload.js';
26
+ import { GitUpdateTool } from './tools/gitUpdate.js';
27
+ import { GitHistoryTool } from './tools/gitHistory.js';
28
+ import { GitFixTool } from './tools/gitFix.tool.js';
29
+ import { GitIgnoreTool } from './tools/gitIgnore.js';
30
+ import { GIT_PROMPTS } from './prompts/gitPrompts.js';
31
+ import TOOLS_GUIDE from './resources/toolsGuide.js';
32
+ import { Logger, logToolExecution, logSecurityEvent, logPerformanceMetric } from './utils/logger.js';
33
+ async function main() {
34
+ const providerManager = new ProviderManager();
35
+ const gitAdapter = new IsomorphicGitAdapter(providerManager);
36
+ const logger = Logger.getInstance();
37
+ // Skip validation on startup to prevent hanging (validation happens on first use)
38
+ // Provider validation moved to lazy initialization
39
+ // Register all 22 Git tools
40
+ const tools = [
41
+ new GitWorkflowTool(),
42
+ new GitFilesTool(),
43
+ new GitBranchesTool(),
44
+ new GitIssuesTool(),
45
+ new GitPullsTool(),
46
+ new GitTagsTool(),
47
+ new GitReleaseTool(),
48
+ new GitRemoteTool(),
49
+ new GitResetTool(),
50
+ new GitStashTool(),
51
+ new GitConfigTool(),
52
+ new GitMonitorTool(),
53
+ new GitBackupTool(),
54
+ new GitArchiveTool(),
55
+ new GitSyncTool(),
56
+ new GitPackagesTool(),
57
+ new GitAnalyticsTool(),
58
+ new GitUploadTool(),
59
+ new GitUpdateTool(),
60
+ new GitHistoryTool(),
61
+ new GitFixTool(),
62
+ new GitIgnoreTool(),
63
+ ];
64
+ // Register resources
65
+ const resources = [
66
+ TOOLS_GUIDE
67
+ ];
68
+ // Silent mode for MCP clients - only log to stderr in debug mode
69
+ if (process.env.DEBUG) {
70
+ logger.info(`Registered ${tools.length} Git tools`);
71
+ logger.info(`Registered ${resources.length} resource(s)`);
72
+ logger.info(`Registered ${GIT_PROMPTS.length} prompt(s)`);
73
+ }
74
+ // Create MCP Server with STDIO transport
75
+ const server = new Server({
76
+ name: '@andrebuzeli/git-mcp',
77
+ version: '10.0.4',
78
+ });
79
+ // Register tool list handler
80
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
81
+ logger.debug('Listing available tools');
82
+ return {
83
+ tools: tools.map(tool => ({
84
+ name: tool.name,
85
+ description: tool.description,
86
+ inputSchema: tool.inputSchema || {
87
+ type: 'object',
88
+ properties: {},
89
+ additionalProperties: true,
90
+ },
91
+ })),
92
+ };
93
+ });
94
+ // Register tool execution handler with logging e segurança aprimorados
95
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
96
+ const toolName = request.params.name;
97
+ const tool = tools.find(t => t.name === toolName);
98
+ const startTime = Date.now();
99
+ if (!tool) {
100
+ logSecurityEvent('TOOL_NOT_FOUND', { toolName });
101
+ throw new Error(`Tool not found: ${toolName}`);
102
+ }
103
+ try {
104
+ // Validar argumentos contra o schema da ferramenta
105
+ const args = request.params.arguments ?? {};
106
+ // Validação básica de segurança
107
+ if (typeof args !== 'object' || args === null) {
108
+ logSecurityEvent('INVALID_ARGUMENTS', { toolName, args });
109
+ throw new MCPError('VALIDATION_ERROR', 'Arguments must be an object');
110
+ }
111
+ // Validar projectPath se existir
112
+ if ('projectPath' in args) {
113
+ const projectPath = args.projectPath;
114
+ if (typeof projectPath !== 'string') {
115
+ logSecurityEvent('INVALID_PROJECT_PATH_TYPE', { toolName, projectPath });
116
+ throw new MCPError('VALIDATION_ERROR', 'projectPath must be a string');
117
+ }
118
+ if (!projectPath || projectPath.includes('..')) {
119
+ logSecurityEvent('PATH_TRAVERSION_ATTEMPT', { toolName, projectPath });
120
+ throw new MCPError('VALIDATION_ERROR', 'Invalid project path');
121
+ }
122
+ }
123
+ // Log da execução
124
+ logger.info(`Executing tool: ${toolName}`, { args }, toolName);
125
+ // Executar a ferramenta
126
+ const result = await tool.handle(args, { providerManager, gitAdapter });
127
+ const duration = Date.now() - startTime;
128
+ logPerformanceMetric(`tool_${toolName}`, duration, { success: true });
129
+ logToolExecution(toolName, args, result);
130
+ return {
131
+ content: [
132
+ {
133
+ type: 'text',
134
+ text: typeof result === 'string' ? result : JSON.stringify(result, null, 2),
135
+ },
136
+ ],
137
+ };
138
+ }
139
+ catch (error) {
140
+ const duration = Date.now() - startTime;
141
+ logPerformanceMetric(`tool_${toolName}`, duration, { success: false, error: error.message });
142
+ logToolExecution(toolName, request.params.arguments ?? {}, undefined, error);
143
+ return {
144
+ content: [
145
+ {
146
+ type: 'text',
147
+ text: `Error: ${error.message || String(error)}`,
148
+ },
149
+ ],
150
+ isError: true,
151
+ };
152
+ }
153
+ });
154
+ // Register resource list handler
155
+ server.setRequestHandler(ListResourcesRequestSchema, async () => {
156
+ logger.debug('Listing available resources');
157
+ return {
158
+ resources: resources.map(resource => ({
159
+ uri: resource.uri,
160
+ name: resource.name,
161
+ description: resource.description,
162
+ mimeType: resource.mimeType,
163
+ })),
164
+ };
165
+ });
166
+ // Register resource read handler
167
+ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
168
+ const uri = request.params.uri;
169
+ const resource = resources.find(r => r.uri === uri);
170
+ if (!resource) {
171
+ logger.warn(`Resource not found: ${uri}`);
172
+ throw new Error(`Resource not found: ${uri}`);
173
+ }
174
+ logger.debug(`Reading resource: ${uri}`);
175
+ return {
176
+ contents: [
177
+ {
178
+ uri: resource.uri,
179
+ mimeType: resource.mimeType,
180
+ text: resource.content,
181
+ },
182
+ ],
183
+ };
184
+ });
185
+ // Register prompt list handler
186
+ server.setRequestHandler(ListPromptsRequestSchema, async () => {
187
+ logger.debug('Listing available prompts');
188
+ return {
189
+ prompts: GIT_PROMPTS.map(prompt => ({
190
+ name: prompt.name,
191
+ description: prompt.description,
192
+ arguments: prompt.arguments,
193
+ })),
194
+ };
195
+ });
196
+ // Register prompt get handler
197
+ server.setRequestHandler(GetPromptRequestSchema, async (request) => {
198
+ const promptName = request.params.name;
199
+ const prompt = GIT_PROMPTS.find(p => p.name === promptName);
200
+ if (!prompt) {
201
+ logger.warn(`Prompt not found: ${promptName}`);
202
+ throw new Error(`Prompt not found: ${promptName}`);
203
+ }
204
+ logger.debug(`Generating prompt: ${promptName}`);
205
+ const result = await prompt.generate(request.params.arguments ?? {}, { providerManager, gitAdapter });
206
+ return {
207
+ description: result.description,
208
+ messages: result.messages,
209
+ };
210
+ });
211
+ const transport = new StdioServerTransport();
212
+ await server.connect(transport);
213
+ // Only log in debug mode
214
+ if (process.env.DEBUG) {
215
+ logger.info(`✅ git-mcp MCP server running via STDIO`);
216
+ logger.info(`Tools: ${tools.length} registered`);
217
+ logger.info(`Resources: ${resources.length} registered`);
218
+ logger.info(`Prompts: ${GIT_PROMPTS.length} registered`);
219
+ }
220
+ }
221
+ main().catch(err => {
222
+ console.error('❌ Failed to start git-mcp:', err);
223
+ process.exit(1);
224
+ });
@@ -14,10 +14,6 @@ export declare class GitArchiveTool implements Tool {
14
14
  enum: string[];
15
15
  description: string;
16
16
  };
17
- archiveName: {
18
- type: string;
19
- description: string;
20
- };
21
17
  outputPath: {
22
18
  type: string;
23
19
  description: string;
@@ -31,10 +27,6 @@ export declare class GitArchiveTool implements Tool {
31
27
  type: string;
32
28
  description: string;
33
29
  };
34
- archivePath: {
35
- type: string;
36
- description: string;
37
- };
38
30
  };
39
31
  required: string[];
40
32
  additionalProperties: boolean;
@@ -10,20 +10,16 @@ export class GitArchiveTool {
10
10
  properties: {
11
11
  projectPath: {
12
12
  type: "string",
13
- description: "Absolute path to the project/repository (REQUIRED)"
13
+ description: "The absolute path to the Git repository directory on the local filesystem. This should be the root directory containing the .git folder. For example: '/home/user/my-project' on Linux/Mac or 'C:\\Users\\user\\my-project' on Windows."
14
14
  },
15
15
  action: {
16
16
  type: "string",
17
- enum: ["create", "list", "verify", "extract"],
18
- description: "Action to perform: create (create archive), list (list archives), verify (verify archive), extract (extract archive)"
19
- },
20
- archiveName: {
21
- type: "string",
22
- description: "Name for the archive file (optional for create, default: timestamp-based)"
17
+ enum: ["create", "extract"],
18
+ description: "Archive operation to perform: create (create archive), extract (extract archive)"
23
19
  },
24
20
  outputPath: {
25
21
  type: "string",
26
- description: "Output directory for archives (optional for create, default: .git-archives)"
22
+ description: "Output archive file path (required for create)"
27
23
  },
28
24
  format: {
29
25
  type: "string",
@@ -33,10 +29,6 @@ export class GitArchiveTool {
33
29
  ref: {
34
30
  type: "string",
35
31
  description: "Git reference to archive (optional for create, default: HEAD)"
36
- },
37
- archivePath: {
38
- type: "string",
39
- description: "Path to archive file (required for verify/extract)"
40
32
  }
41
33
  },
42
34
  required: ["projectPath", "action"],
@@ -11,28 +11,28 @@ export class GitBackupTool {
11
11
  properties: {
12
12
  projectPath: {
13
13
  type: "string",
14
- description: "Absolute path to the project/repository (REQUIRED)"
14
+ description: "The absolute path to the Git repository directory on the local filesystem. This should be the root directory containing the .git folder. For example: '/home/user/my-project' on Linux/Mac or 'C:\\Users\\user\\my-project' on Windows."
15
15
  },
16
16
  action: {
17
17
  type: "string",
18
- enum: ["backup", "list", "verify", "restore"],
19
- description: "Action to perform: backup (create backup), list (list backups), verify (verify backup), restore (restore from backup)"
18
+ enum: ["create", "restore", "list", "delete"],
19
+ description: "Backup operation to perform: create (create backup), restore (restore from backup), list (list backups), delete (delete backup)"
20
20
  },
21
21
  backupPath: {
22
22
  type: "string",
23
- description: "Path to backup file (required for restore/verify)"
23
+ description: "Path to backup file (required for create/restore/delete)"
24
24
  },
25
25
  compress: {
26
26
  type: "boolean",
27
- description: "Compress backup (optional for backup, default: true)"
27
+ description: "Compress backup (optional for create, default: true)"
28
28
  },
29
29
  confirm: {
30
30
  type: "boolean",
31
- description: "Confirm destructive operations (optional for restore)"
31
+ description: "Confirm destructive operations (optional for restore/delete)"
32
32
  },
33
33
  name: {
34
34
  type: "string",
35
- description: "Backup name (optional for backup)"
35
+ description: "Backup name (optional for create)"
36
36
  }
37
37
  },
38
38
  required: ["projectPath", "action"],