@andrebuzeli/git-mcp 10.0.7 → 10.0.9

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 (45) hide show
  1. package/LICENSE +0 -0
  2. package/README.md +1 -1
  3. package/dist/providers/providerManager.js +2 -4
  4. package/dist/scripts/test_e2e.d.ts +1 -0
  5. package/dist/scripts/test_e2e.js +199 -0
  6. package/dist/scripts/test_exhaustive.d.ts +1 -0
  7. package/dist/scripts/test_exhaustive.js +275 -0
  8. package/dist/scripts/test_gitea_creation.d.ts +1 -0
  9. package/dist/scripts/test_gitea_creation.js +116 -0
  10. package/dist/scripts/verify_setup.d.ts +1 -0
  11. package/dist/scripts/verify_setup.js +61 -0
  12. package/dist/tools/gitAnalytics.js +3 -3
  13. package/dist/tools/gitBackup.d.ts +2 -2
  14. package/dist/tools/gitBackup.js +5 -5
  15. package/dist/tools/gitBranches.js +40 -29
  16. package/dist/tools/gitConfig.d.ts +2 -2
  17. package/dist/tools/gitConfig.js +12 -13
  18. package/dist/tools/gitFix.d.ts +2 -1
  19. package/dist/tools/gitFix.js +20 -24
  20. package/dist/tools/gitFix.tool.d.ts +2 -2
  21. package/dist/tools/gitFix.tool.js +2 -2
  22. package/dist/tools/gitHistory.js +4 -5
  23. package/dist/tools/gitIssues.js +8 -8
  24. package/dist/tools/gitMonitor.js +28 -33
  25. package/dist/tools/gitPulls.js +8 -8
  26. package/dist/tools/gitRelease.js +5 -6
  27. package/dist/tools/gitRemote.d.ts +1 -11
  28. package/dist/tools/gitRemote.js +14 -20
  29. package/dist/tools/gitReset.js +6 -7
  30. package/dist/tools/gitStash.d.ts +1 -12
  31. package/dist/tools/gitStash.js +11 -22
  32. package/dist/tools/gitSync.js +44 -36
  33. package/dist/tools/gitTags.d.ts +8 -0
  34. package/dist/tools/gitTags.js +44 -34
  35. package/dist/tools/gitUpdate.d.ts +27 -0
  36. package/dist/tools/gitUpdate.js +61 -34
  37. package/dist/tools/gitUpload.js +29 -44
  38. package/dist/tools/gitWorkflow.js +27 -46
  39. package/dist/utils/gitAdapter.js +10 -0
  40. package/dist/utils/repoHelpers.js +7 -12
  41. package/package.json +2 -3
  42. package/dist/server-new.d.ts +0 -2
  43. package/dist/server-new.js +0 -224
  44. package/dist/tools/gitFiles-new.d.ts +0 -89
  45. package/dist/tools/gitFiles-new.js +0 -335
@@ -1,89 +0,0 @@
1
- import { Tool } from '../types.js';
2
- export declare class GitFilesTool implements Tool {
3
- name: string;
4
- description: string;
5
- inputSchema: {
6
- type: "object";
7
- properties: {
8
- action: {
9
- type: string;
10
- enum: string[];
11
- description: string;
12
- };
13
- projectPath: {
14
- type: string;
15
- description: string;
16
- };
17
- filePath: {
18
- type: string;
19
- description: string;
20
- };
21
- directoryPath: {
22
- type: string;
23
- description: string;
24
- };
25
- content: {
26
- type: string;
27
- description: string;
28
- };
29
- comment: {
30
- type: string;
31
- description: string;
32
- };
33
- patterns: {
34
- type: string;
35
- items: {
36
- type: string;
37
- };
38
- description: string;
39
- };
40
- searchText: {
41
- type: string;
42
- description: string;
43
- };
44
- query: {
45
- type: string;
46
- description: string;
47
- };
48
- searchPath: {
49
- type: string;
50
- description: string;
51
- };
52
- };
53
- required: string[];
54
- additionalProperties: boolean;
55
- };
56
- handle(params: Record<string, any>): Promise<any>;
57
- /**
58
- * Lê arquivo com cache
59
- */
60
- private handleRead;
61
- /**
62
- * Lista diretório com cache
63
- */
64
- private handleList;
65
- /**
66
- * Cria arquivo com validação de segurança
67
- */
68
- private handleCreate;
69
- /**
70
- * Atualiza arquivo com validação de segurança
71
- */
72
- private handleUpdate;
73
- /**
74
- * Deleta arquivo com validação de segurança
75
- */
76
- private handleDelete;
77
- /**
78
- * Busca texto em arquivos com cache
79
- */
80
- private handleSearch;
81
- /**
82
- * Busca recursivamente em diretórios
83
- */
84
- private searchInDirectory;
85
- /**
86
- * Verifica se arquivo é buscável
87
- */
88
- private isSearchableFile;
89
- }
@@ -1,335 +0,0 @@
1
- import fs from 'fs/promises';
2
- import path from 'path';
3
- import { MCPError } from '../utils/errors.js';
4
- import { cacheHelpers } from '../utils/cache.js';
5
- import { Logger } from '../utils/logger.js';
6
- export class GitFilesTool {
7
- constructor() {
8
- this.name = 'git-files';
9
- this.description = 'Read-only file operations for repositories - local operations only with caching and rate limiting';
10
- this.inputSchema = {
11
- type: "object",
12
- properties: {
13
- action: {
14
- type: "string",
15
- enum: ["read", "list", "create", "update", "delete", "search"],
16
- description: "File operation to perform"
17
- },
18
- projectPath: {
19
- type: "string",
20
- description: "Absolute path to the project directory (REQUIRED)"
21
- },
22
- filePath: {
23
- type: "string",
24
- description: "Relative path to the file within projectPath - required for read, create, update, delete"
25
- },
26
- directoryPath: {
27
- type: "string",
28
- description: "Relative path to directory for listing - optional, defaults to projectPath root"
29
- },
30
- content: {
31
- type: "string",
32
- description: "File content to write - required for create and update actions"
33
- },
34
- comment: {
35
- type: "string",
36
- description: "Comment to add when appending patterns to .gitignore - optional for add action"
37
- },
38
- patterns: {
39
- type: "array",
40
- items: { type: "string" },
41
- description: "Array of file patterns - required for add and remove actions"
42
- },
43
- searchText: {
44
- type: "string",
45
- description: "Text to search for in files - required for search action"
46
- },
47
- query: {
48
- type: "string",
49
- description: "Alternative name for searchText - required for search action"
50
- },
51
- searchPath: {
52
- type: "string",
53
- description: "Relative path to search within - optional for search, defaults to projectPath root"
54
- }
55
- },
56
- required: ["projectPath", "action"],
57
- additionalProperties: true
58
- };
59
- }
60
- async handle(params) {
61
- const logger = Logger.getInstance();
62
- const startTime = Date.now();
63
- try {
64
- const action = params.action;
65
- const projectPath = params.projectPath;
66
- if (!action || !projectPath) {
67
- throw new MCPError('VALIDATION_ERROR', 'action and projectPath are required');
68
- }
69
- logger.debug(`Executing git-files:${action}`, { projectPath, filePath: params.filePath });
70
- let result;
71
- switch (action) {
72
- case 'read':
73
- result = await this.handleRead(projectPath, params.filePath);
74
- break;
75
- case 'list':
76
- result = await this.handleList(projectPath, params.directoryPath);
77
- break;
78
- case 'create':
79
- result = await this.handleCreate(projectPath, params.filePath, params.content || '');
80
- // Invalidar cache após modificação
81
- cacheHelpers.invalidateRepoCache(projectPath);
82
- break;
83
- case 'update':
84
- result = await this.handleUpdate(projectPath, params.filePath, params.content);
85
- // Invalidar cache após modificação
86
- cacheHelpers.invalidateRepoCache(projectPath);
87
- break;
88
- case 'delete':
89
- result = await this.handleDelete(projectPath, params.filePath);
90
- // Invalidar cache após modificação
91
- cacheHelpers.invalidateRepoCache(projectPath);
92
- break;
93
- case 'search':
94
- result = await this.handleSearch(projectPath, params.searchText || params.query, params.searchPath);
95
- break;
96
- default:
97
- throw new MCPError('VALIDATION_ERROR', `Unknown action: ${action}`);
98
- }
99
- const duration = Date.now() - startTime;
100
- logger.debug(`git-files:${action} completed in ${duration}ms`);
101
- return result;
102
- }
103
- catch (error) {
104
- const duration = Date.now() - startTime;
105
- logger.error(`git-files operation failed`, {
106
- action: params.action,
107
- projectPath: params.projectPath,
108
- duration,
109
- error: error.message
110
- });
111
- throw error;
112
- }
113
- }
114
- /**
115
- * Lê arquivo com cache
116
- */
117
- async handleRead(projectPath, filePath) {
118
- if (!filePath) {
119
- throw new MCPError('VALIDATION_ERROR', 'filePath is required for read action');
120
- }
121
- const fullPath = path.resolve(projectPath, filePath);
122
- // Verificar segurança: path traversal
123
- if (!fullPath.startsWith(path.resolve(projectPath))) {
124
- throw new MCPError('SECURITY_ERROR', 'File path must be within project directory');
125
- }
126
- // Leitura de arquivo sem cache por enquanto
127
- try {
128
- const content = await fs.readFile(fullPath, 'utf8');
129
- return { success: true, path: fullPath, content, size: content.length };
130
- }
131
- catch (error) {
132
- if (error.code === 'ENOENT') {
133
- throw new MCPError('FILE_NOT_FOUND', `File not found: ${filePath}`);
134
- }
135
- throw new MCPError('FILE_ERROR', `Failed to read file: ${error.message}`);
136
- }
137
- }
138
- /**
139
- * Lista diretório com cache
140
- */
141
- async handleList(projectPath, directoryPath) {
142
- const dirPath = directoryPath ? path.join(projectPath, directoryPath) : projectPath;
143
- // Verificar segurança: path traversal
144
- if (!dirPath.startsWith(path.resolve(projectPath))) {
145
- throw new MCPError('SECURITY_ERROR', 'Directory path must be within project directory');
146
- }
147
- // Usar cache para listagem de diretórios
148
- // Listar diretório sem cache por enquanto
149
- try {
150
- const files = await fs.readdir(dirPath, { withFileTypes: true });
151
- return {
152
- success: true,
153
- files: files.map(entry => ({
154
- name: entry.name,
155
- isDirectory: entry.isDirectory(),
156
- isFile: entry.isFile(),
157
- path: path.join(directoryPath || '', entry.name)
158
- }))
159
- };
160
- }
161
- catch (error) {
162
- if (error.code === 'ENOENT') {
163
- throw new MCPError('DIRECTORY_NOT_FOUND', `Directory not found: ${directoryPath || 'root'}`);
164
- }
165
- throw new MCPError('DIRECTORY_ERROR', `Failed to list directory: ${error.message}`);
166
- }
167
- }
168
- /**
169
- * Cria arquivo com validação de segurança
170
- */
171
- async handleCreate(projectPath, filePath, content = '') {
172
- if (!filePath) {
173
- throw new MCPError('VALIDATION_ERROR', 'filePath is required for create action');
174
- }
175
- const targetPath = path.resolve(projectPath, filePath);
176
- // Verificar segurança: path traversal
177
- if (!targetPath.startsWith(path.resolve(projectPath))) {
178
- throw new MCPError('SECURITY_ERROR', 'File path must be within project directory');
179
- }
180
- try {
181
- // Criar diretório se necessário
182
- const dir = path.dirname(targetPath);
183
- await fs.mkdir(dir, { recursive: true });
184
- await fs.writeFile(targetPath, content, 'utf-8');
185
- return {
186
- success: true,
187
- created: true,
188
- path: targetPath,
189
- size: content.length,
190
- };
191
- }
192
- catch (error) {
193
- throw new MCPError('FILE_ERROR', `Failed to create file: ${error.message}`);
194
- }
195
- }
196
- /**
197
- * Atualiza arquivo com validação de segurança
198
- */
199
- async handleUpdate(projectPath, filePath, content) {
200
- if (!filePath) {
201
- throw new MCPError('VALIDATION_ERROR', 'filePath is required for update action');
202
- }
203
- if (content === undefined) {
204
- throw new MCPError('VALIDATION_ERROR', 'content is required for update action');
205
- }
206
- const targetPath = path.resolve(projectPath, filePath);
207
- // Verificar segurança: path traversal
208
- if (!targetPath.startsWith(path.resolve(projectPath))) {
209
- throw new MCPError('SECURITY_ERROR', 'File path must be within project directory');
210
- }
211
- try {
212
- // Verificar se arquivo existe
213
- await fs.access(targetPath);
214
- await fs.writeFile(targetPath, content, 'utf-8');
215
- return {
216
- success: true,
217
- updated: true,
218
- path: targetPath,
219
- size: content.length,
220
- };
221
- }
222
- catch (error) {
223
- if (error.code === 'ENOENT') {
224
- throw new MCPError('FILE_NOT_FOUND', 'File does not exist. Use create action.');
225
- }
226
- throw new MCPError('FILE_ERROR', `Failed to update file: ${error.message}`);
227
- }
228
- }
229
- /**
230
- * Deleta arquivo com validação de segurança
231
- */
232
- async handleDelete(projectPath, filePath) {
233
- if (!filePath) {
234
- throw new MCPError('VALIDATION_ERROR', 'filePath is required for delete action');
235
- }
236
- const targetPath = path.resolve(projectPath, filePath);
237
- // Verificar segurança: path traversal
238
- if (!targetPath.startsWith(path.resolve(projectPath))) {
239
- throw new MCPError('SECURITY_ERROR', 'File path must be within project directory');
240
- }
241
- try {
242
- await fs.unlink(targetPath);
243
- return {
244
- success: true,
245
- deleted: true,
246
- path: targetPath,
247
- };
248
- }
249
- catch (error) {
250
- if (error.code === 'ENOENT') {
251
- throw new MCPError('FILE_NOT_FOUND', `File not found: ${filePath}`);
252
- }
253
- throw new MCPError('FILE_ERROR', `Failed to delete file: ${error.message}`);
254
- }
255
- }
256
- /**
257
- * Busca texto em arquivos com cache
258
- */
259
- async handleSearch(projectPath, searchText, searchPath) {
260
- if (!searchText) {
261
- throw new MCPError('VALIDATION_ERROR', 'searchText or query is required for search action');
262
- }
263
- const searchDir = searchPath ? path.join(projectPath, searchPath) : projectPath;
264
- // Verificar segurança: path traversal
265
- if (!searchDir.startsWith(path.resolve(projectPath))) {
266
- throw new MCPError('SECURITY_ERROR', 'Search path must be within project directory');
267
- }
268
- // Busca sem cache por enquanto
269
- try {
270
- const results = await this.searchInDirectory(searchDir, searchText);
271
- return {
272
- success: true,
273
- searchText,
274
- searchPath: searchPath || 'root',
275
- results: results.slice(0, 50), // Limitar resultados para performance
276
- totalResults: results.length,
277
- };
278
- }
279
- catch (error) {
280
- throw new MCPError('SEARCH_ERROR', `Failed to search files: ${error.message}`);
281
- }
282
- }
283
- /**
284
- * Busca recursivamente em diretórios
285
- */
286
- async searchInDirectory(dir, searchText) {
287
- const results = [];
288
- try {
289
- const entries = await fs.readdir(dir, { withFileTypes: true });
290
- for (const entry of entries) {
291
- const fullPath = path.join(dir, entry.name);
292
- if (entry.isDirectory() && !entry.name.startsWith('.') && entry.name !== 'node_modules') {
293
- // Recursivamente buscar em subdiretórios
294
- const subResults = await this.searchInDirectory(fullPath, searchText);
295
- results.push(...subResults);
296
- }
297
- else if (entry.isFile() && this.isSearchableFile(entry.name)) {
298
- // Buscar em arquivos
299
- try {
300
- const content = await fs.readFile(fullPath, 'utf8');
301
- const lines = content.split('\n');
302
- lines.forEach((line, index) => {
303
- if (line.toLowerCase().includes(searchText.toLowerCase())) {
304
- results.push({
305
- file: fullPath,
306
- line: index + 1,
307
- text: line.trim(),
308
- });
309
- }
310
- });
311
- }
312
- catch (error) {
313
- // Ignorar erros de leitura (arquivos binários, etc.)
314
- }
315
- }
316
- }
317
- }
318
- catch (error) {
319
- // Ignorar erros de acesso
320
- }
321
- return results;
322
- }
323
- /**
324
- * Verifica se arquivo é buscável
325
- */
326
- isSearchableFile(filename) {
327
- const searchableExtensions = [
328
- '.js', '.ts', '.jsx', '.tsx', '.json', '.md', '.txt', '.yml', '.yaml',
329
- '.html', '.css', '.scss', '.sass', '.less', '.xml', '.sh', '.bat',
330
- '.py', '.java', '.cpp', '.c', '.h', '.php', '.rb', '.go', '.rs'
331
- ];
332
- const ext = path.extname(filename).toLowerCase();
333
- return searchableExtensions.includes(ext);
334
- }
335
- }