@andrebuzeli/git-mcp 7.1.0 → 7.2.0
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.
- package/dist/index.js +4 -2
- package/dist/tools/gitIgnore.d.ts +191 -0
- package/dist/tools/gitIgnore.js +354 -0
- package/dist/tools/gitUpdate.js +98 -5
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -30,6 +30,7 @@ const gitUpload_1 = require("./tools/gitUpload");
|
|
|
30
30
|
const gitUpdate_1 = require("./tools/gitUpdate");
|
|
31
31
|
const gitHistory_1 = require("./tools/gitHistory");
|
|
32
32
|
const gitFix_tool_1 = require("./tools/gitFix.tool");
|
|
33
|
+
const gitIgnore_1 = require("./tools/gitIgnore");
|
|
33
34
|
const toolsGuide_1 = __importDefault(require("./resources/toolsGuide"));
|
|
34
35
|
async function main() {
|
|
35
36
|
// Load optional mcp.json configuration (will populate process.env if values present)
|
|
@@ -41,7 +42,7 @@ async function main() {
|
|
|
41
42
|
if (process.env.DEBUG) {
|
|
42
43
|
console.error('Provider validation:', JSON.stringify(validation, null, 2));
|
|
43
44
|
}
|
|
44
|
-
// Register all
|
|
45
|
+
// Register all 22 Git tools
|
|
45
46
|
const tools = [
|
|
46
47
|
new gitWorkflow_1.GitWorkflowTool(),
|
|
47
48
|
new gitFiles_1.GitFilesTool(),
|
|
@@ -64,6 +65,7 @@ async function main() {
|
|
|
64
65
|
new gitUpdate_1.GitUpdateTool(),
|
|
65
66
|
new gitHistory_1.GitHistoryTool(),
|
|
66
67
|
new gitFix_tool_1.GitFixTool(),
|
|
68
|
+
new gitIgnore_1.GitIgnoreTool(),
|
|
67
69
|
];
|
|
68
70
|
// Register resources
|
|
69
71
|
const resources = [
|
|
@@ -77,7 +79,7 @@ async function main() {
|
|
|
77
79
|
// Create MCP Server with STDIO transport
|
|
78
80
|
const server = new index_1.Server({
|
|
79
81
|
name: '@andrebuzeli/git-mcp',
|
|
80
|
-
version: '
|
|
82
|
+
version: '7.2.0',
|
|
81
83
|
});
|
|
82
84
|
// Register tool list handler
|
|
83
85
|
server.setRequestHandler(types_1.ListToolsRequestSchema, async () => {
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { Tool, MCPContext } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Git Ignore Tool - Manage .gitignore file
|
|
4
|
+
* Create, read, add, remove patterns, and ensure .gitignore exists
|
|
5
|
+
*/
|
|
6
|
+
export declare class GitIgnoreTool implements Tool {
|
|
7
|
+
name: string;
|
|
8
|
+
description: string;
|
|
9
|
+
handle(params: Record<string, any>, ctx: MCPContext): Promise<{
|
|
10
|
+
success: boolean;
|
|
11
|
+
path: string;
|
|
12
|
+
exists: boolean;
|
|
13
|
+
content: string;
|
|
14
|
+
patterns: string[];
|
|
15
|
+
lines: number;
|
|
16
|
+
message?: undefined;
|
|
17
|
+
created?: undefined;
|
|
18
|
+
template?: undefined;
|
|
19
|
+
action?: undefined;
|
|
20
|
+
added?: undefined;
|
|
21
|
+
skipped?: undefined;
|
|
22
|
+
total?: undefined;
|
|
23
|
+
removed?: undefined;
|
|
24
|
+
remaining?: undefined;
|
|
25
|
+
updated?: undefined;
|
|
26
|
+
cleared?: undefined;
|
|
27
|
+
} | {
|
|
28
|
+
success: boolean;
|
|
29
|
+
path: string;
|
|
30
|
+
exists: boolean;
|
|
31
|
+
message: string;
|
|
32
|
+
content?: undefined;
|
|
33
|
+
patterns?: undefined;
|
|
34
|
+
lines?: undefined;
|
|
35
|
+
created?: undefined;
|
|
36
|
+
template?: undefined;
|
|
37
|
+
action?: undefined;
|
|
38
|
+
added?: undefined;
|
|
39
|
+
skipped?: undefined;
|
|
40
|
+
total?: undefined;
|
|
41
|
+
removed?: undefined;
|
|
42
|
+
remaining?: undefined;
|
|
43
|
+
updated?: undefined;
|
|
44
|
+
cleared?: undefined;
|
|
45
|
+
} | {
|
|
46
|
+
success: boolean;
|
|
47
|
+
message: string;
|
|
48
|
+
path: string;
|
|
49
|
+
exists?: undefined;
|
|
50
|
+
content?: undefined;
|
|
51
|
+
patterns?: undefined;
|
|
52
|
+
lines?: undefined;
|
|
53
|
+
created?: undefined;
|
|
54
|
+
template?: undefined;
|
|
55
|
+
action?: undefined;
|
|
56
|
+
added?: undefined;
|
|
57
|
+
skipped?: undefined;
|
|
58
|
+
total?: undefined;
|
|
59
|
+
removed?: undefined;
|
|
60
|
+
remaining?: undefined;
|
|
61
|
+
updated?: undefined;
|
|
62
|
+
cleared?: undefined;
|
|
63
|
+
} | {
|
|
64
|
+
success: boolean;
|
|
65
|
+
path: string;
|
|
66
|
+
created: boolean;
|
|
67
|
+
template: any;
|
|
68
|
+
lines: number;
|
|
69
|
+
exists?: undefined;
|
|
70
|
+
content?: undefined;
|
|
71
|
+
patterns?: undefined;
|
|
72
|
+
message?: undefined;
|
|
73
|
+
action?: undefined;
|
|
74
|
+
added?: undefined;
|
|
75
|
+
skipped?: undefined;
|
|
76
|
+
total?: undefined;
|
|
77
|
+
removed?: undefined;
|
|
78
|
+
remaining?: undefined;
|
|
79
|
+
updated?: undefined;
|
|
80
|
+
cleared?: undefined;
|
|
81
|
+
} | {
|
|
82
|
+
success: boolean;
|
|
83
|
+
path: string;
|
|
84
|
+
exists: boolean;
|
|
85
|
+
action: string;
|
|
86
|
+
message: string;
|
|
87
|
+
content?: undefined;
|
|
88
|
+
patterns?: undefined;
|
|
89
|
+
lines?: undefined;
|
|
90
|
+
created?: undefined;
|
|
91
|
+
template?: undefined;
|
|
92
|
+
added?: undefined;
|
|
93
|
+
skipped?: undefined;
|
|
94
|
+
total?: undefined;
|
|
95
|
+
removed?: undefined;
|
|
96
|
+
remaining?: undefined;
|
|
97
|
+
updated?: undefined;
|
|
98
|
+
cleared?: undefined;
|
|
99
|
+
} | {
|
|
100
|
+
success: boolean;
|
|
101
|
+
path: string;
|
|
102
|
+
created: boolean;
|
|
103
|
+
template: any;
|
|
104
|
+
action: string;
|
|
105
|
+
exists?: undefined;
|
|
106
|
+
content?: undefined;
|
|
107
|
+
patterns?: undefined;
|
|
108
|
+
lines?: undefined;
|
|
109
|
+
message?: undefined;
|
|
110
|
+
added?: undefined;
|
|
111
|
+
skipped?: undefined;
|
|
112
|
+
total?: undefined;
|
|
113
|
+
removed?: undefined;
|
|
114
|
+
remaining?: undefined;
|
|
115
|
+
updated?: undefined;
|
|
116
|
+
cleared?: undefined;
|
|
117
|
+
} | {
|
|
118
|
+
success: boolean;
|
|
119
|
+
path: string;
|
|
120
|
+
added: string[];
|
|
121
|
+
skipped: number;
|
|
122
|
+
total: number;
|
|
123
|
+
exists?: undefined;
|
|
124
|
+
content?: undefined;
|
|
125
|
+
patterns?: undefined;
|
|
126
|
+
lines?: undefined;
|
|
127
|
+
message?: undefined;
|
|
128
|
+
created?: undefined;
|
|
129
|
+
template?: undefined;
|
|
130
|
+
action?: undefined;
|
|
131
|
+
removed?: undefined;
|
|
132
|
+
remaining?: undefined;
|
|
133
|
+
updated?: undefined;
|
|
134
|
+
cleared?: undefined;
|
|
135
|
+
} | {
|
|
136
|
+
success: boolean;
|
|
137
|
+
path: string;
|
|
138
|
+
removed: number;
|
|
139
|
+
remaining: number;
|
|
140
|
+
exists?: undefined;
|
|
141
|
+
content?: undefined;
|
|
142
|
+
patterns?: undefined;
|
|
143
|
+
lines?: undefined;
|
|
144
|
+
message?: undefined;
|
|
145
|
+
created?: undefined;
|
|
146
|
+
template?: undefined;
|
|
147
|
+
action?: undefined;
|
|
148
|
+
added?: undefined;
|
|
149
|
+
skipped?: undefined;
|
|
150
|
+
total?: undefined;
|
|
151
|
+
updated?: undefined;
|
|
152
|
+
cleared?: undefined;
|
|
153
|
+
} | {
|
|
154
|
+
success: boolean;
|
|
155
|
+
path: string;
|
|
156
|
+
updated: boolean;
|
|
157
|
+
lines: any;
|
|
158
|
+
exists?: undefined;
|
|
159
|
+
content?: undefined;
|
|
160
|
+
patterns?: undefined;
|
|
161
|
+
message?: undefined;
|
|
162
|
+
created?: undefined;
|
|
163
|
+
template?: undefined;
|
|
164
|
+
action?: undefined;
|
|
165
|
+
added?: undefined;
|
|
166
|
+
skipped?: undefined;
|
|
167
|
+
total?: undefined;
|
|
168
|
+
removed?: undefined;
|
|
169
|
+
remaining?: undefined;
|
|
170
|
+
cleared?: undefined;
|
|
171
|
+
} | {
|
|
172
|
+
success: boolean;
|
|
173
|
+
path: string;
|
|
174
|
+
cleared: boolean;
|
|
175
|
+
template: any;
|
|
176
|
+
exists?: undefined;
|
|
177
|
+
content?: undefined;
|
|
178
|
+
patterns?: undefined;
|
|
179
|
+
lines?: undefined;
|
|
180
|
+
message?: undefined;
|
|
181
|
+
created?: undefined;
|
|
182
|
+
action?: undefined;
|
|
183
|
+
added?: undefined;
|
|
184
|
+
skipped?: undefined;
|
|
185
|
+
total?: undefined;
|
|
186
|
+
removed?: undefined;
|
|
187
|
+
remaining?: undefined;
|
|
188
|
+
updated?: undefined;
|
|
189
|
+
}>;
|
|
190
|
+
private getTemplate;
|
|
191
|
+
}
|
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.GitIgnoreTool = void 0;
|
|
37
|
+
const fs = __importStar(require("fs/promises"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
const errors_1 = require("../utils/errors");
|
|
40
|
+
/**
|
|
41
|
+
* Git Ignore Tool - Manage .gitignore file
|
|
42
|
+
* Create, read, add, remove patterns, and ensure .gitignore exists
|
|
43
|
+
*/
|
|
44
|
+
class GitIgnoreTool {
|
|
45
|
+
constructor() {
|
|
46
|
+
this.name = 'git-ignore';
|
|
47
|
+
this.description = 'Manage .gitignore file - create, add, remove, and update ignore patterns';
|
|
48
|
+
}
|
|
49
|
+
async handle(params, ctx) {
|
|
50
|
+
const projectPath = params.projectPath;
|
|
51
|
+
if (!projectPath) {
|
|
52
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', 'projectPath is required');
|
|
53
|
+
}
|
|
54
|
+
const action = params.action || 'read';
|
|
55
|
+
const gitignorePath = path.join(projectPath, '.gitignore');
|
|
56
|
+
switch (action) {
|
|
57
|
+
case 'read': {
|
|
58
|
+
try {
|
|
59
|
+
const content = await fs.readFile(gitignorePath, 'utf-8');
|
|
60
|
+
const patterns = content.split('\n').filter(l => l.trim() && !l.startsWith('#'));
|
|
61
|
+
return {
|
|
62
|
+
success: true,
|
|
63
|
+
path: gitignorePath,
|
|
64
|
+
exists: true,
|
|
65
|
+
content,
|
|
66
|
+
patterns,
|
|
67
|
+
lines: content.split('\n').length,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
if (err.code === 'ENOENT') {
|
|
72
|
+
return {
|
|
73
|
+
success: true,
|
|
74
|
+
path: gitignorePath,
|
|
75
|
+
exists: false,
|
|
76
|
+
message: '.gitignore does not exist',
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
throw err;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
case 'create': {
|
|
83
|
+
const template = params.template || 'default';
|
|
84
|
+
const content = this.getTemplate(template);
|
|
85
|
+
try {
|
|
86
|
+
await fs.access(gitignorePath);
|
|
87
|
+
return {
|
|
88
|
+
success: false,
|
|
89
|
+
message: '.gitignore already exists. Use "add" to add patterns.',
|
|
90
|
+
path: gitignorePath,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
await fs.writeFile(gitignorePath, content, 'utf-8');
|
|
95
|
+
return {
|
|
96
|
+
success: true,
|
|
97
|
+
path: gitignorePath,
|
|
98
|
+
created: true,
|
|
99
|
+
template,
|
|
100
|
+
lines: content.split('\n').length,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
case 'ensure': {
|
|
105
|
+
// Create if doesn't exist, otherwise do nothing
|
|
106
|
+
try {
|
|
107
|
+
await fs.access(gitignorePath);
|
|
108
|
+
return {
|
|
109
|
+
success: true,
|
|
110
|
+
path: gitignorePath,
|
|
111
|
+
exists: true,
|
|
112
|
+
action: 'none',
|
|
113
|
+
message: '.gitignore already exists',
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
const template = params.template || 'default';
|
|
118
|
+
const content = this.getTemplate(template);
|
|
119
|
+
await fs.writeFile(gitignorePath, content, 'utf-8');
|
|
120
|
+
return {
|
|
121
|
+
success: true,
|
|
122
|
+
path: gitignorePath,
|
|
123
|
+
created: true,
|
|
124
|
+
template,
|
|
125
|
+
action: 'created',
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
case 'add': {
|
|
130
|
+
const patterns = params.patterns;
|
|
131
|
+
if (!patterns || !Array.isArray(patterns) || patterns.length === 0) {
|
|
132
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', 'patterns array is required for add action');
|
|
133
|
+
}
|
|
134
|
+
let content = '';
|
|
135
|
+
try {
|
|
136
|
+
content = await fs.readFile(gitignorePath, 'utf-8');
|
|
137
|
+
}
|
|
138
|
+
catch (err) {
|
|
139
|
+
if (err.code === 'ENOENT') {
|
|
140
|
+
// Create new file
|
|
141
|
+
content = this.getTemplate('minimal');
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
throw err;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
const existingPatterns = new Set(content.split('\n').map(l => l.trim()).filter(l => l && !l.startsWith('#')));
|
|
148
|
+
const newPatterns = [];
|
|
149
|
+
for (const pattern of patterns) {
|
|
150
|
+
if (!existingPatterns.has(pattern)) {
|
|
151
|
+
newPatterns.push(pattern);
|
|
152
|
+
existingPatterns.add(pattern);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
if (newPatterns.length > 0) {
|
|
156
|
+
const comment = params.comment ? `# ${params.comment}\n` : '';
|
|
157
|
+
content += `\n${comment}${newPatterns.join('\n')}\n`;
|
|
158
|
+
await fs.writeFile(gitignorePath, content, 'utf-8');
|
|
159
|
+
}
|
|
160
|
+
return {
|
|
161
|
+
success: true,
|
|
162
|
+
path: gitignorePath,
|
|
163
|
+
added: newPatterns,
|
|
164
|
+
skipped: patterns.length - newPatterns.length,
|
|
165
|
+
total: existingPatterns.size,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
case 'remove': {
|
|
169
|
+
const patterns = params.patterns;
|
|
170
|
+
if (!patterns || !Array.isArray(patterns) || patterns.length === 0) {
|
|
171
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', 'patterns array is required for remove action');
|
|
172
|
+
}
|
|
173
|
+
let content = '';
|
|
174
|
+
try {
|
|
175
|
+
content = await fs.readFile(gitignorePath, 'utf-8');
|
|
176
|
+
}
|
|
177
|
+
catch (err) {
|
|
178
|
+
if (err.code === 'ENOENT') {
|
|
179
|
+
return {
|
|
180
|
+
success: false,
|
|
181
|
+
message: '.gitignore does not exist',
|
|
182
|
+
path: gitignorePath,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
throw err;
|
|
186
|
+
}
|
|
187
|
+
const patternsToRemove = new Set(patterns);
|
|
188
|
+
const lines = content.split('\n');
|
|
189
|
+
const filteredLines = lines.filter(line => {
|
|
190
|
+
const trimmed = line.trim();
|
|
191
|
+
return !patternsToRemove.has(trimmed);
|
|
192
|
+
});
|
|
193
|
+
const removed = lines.length - filteredLines.length;
|
|
194
|
+
const newContent = filteredLines.join('\n');
|
|
195
|
+
await fs.writeFile(gitignorePath, newContent, 'utf-8');
|
|
196
|
+
return {
|
|
197
|
+
success: true,
|
|
198
|
+
path: gitignorePath,
|
|
199
|
+
removed,
|
|
200
|
+
remaining: filteredLines.filter(l => l.trim() && !l.startsWith('#')).length,
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
case 'update': {
|
|
204
|
+
const content = params.content;
|
|
205
|
+
if (!content) {
|
|
206
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', 'content is required for update action');
|
|
207
|
+
}
|
|
208
|
+
await fs.writeFile(gitignorePath, content, 'utf-8');
|
|
209
|
+
return {
|
|
210
|
+
success: true,
|
|
211
|
+
path: gitignorePath,
|
|
212
|
+
updated: true,
|
|
213
|
+
lines: content.split('\n').length,
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
case 'clear': {
|
|
217
|
+
const template = params.template || 'empty';
|
|
218
|
+
const content = template === 'empty' ? '' : this.getTemplate('minimal');
|
|
219
|
+
await fs.writeFile(gitignorePath, content, 'utf-8');
|
|
220
|
+
return {
|
|
221
|
+
success: true,
|
|
222
|
+
path: gitignorePath,
|
|
223
|
+
cleared: true,
|
|
224
|
+
template,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
default:
|
|
228
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', `Unsupported action: ${action}`);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
getTemplate(template) {
|
|
232
|
+
const templates = {
|
|
233
|
+
empty: '',
|
|
234
|
+
minimal: `# Dependencies
|
|
235
|
+
node_modules/
|
|
236
|
+
.pnp
|
|
237
|
+
.pnp.js
|
|
238
|
+
|
|
239
|
+
# Build output
|
|
240
|
+
dist/
|
|
241
|
+
build/
|
|
242
|
+
*.log
|
|
243
|
+
`,
|
|
244
|
+
default: `# Dependencies
|
|
245
|
+
node_modules/
|
|
246
|
+
.pnp
|
|
247
|
+
.pnp.js
|
|
248
|
+
bower_components/
|
|
249
|
+
|
|
250
|
+
# Build output
|
|
251
|
+
dist/
|
|
252
|
+
build/
|
|
253
|
+
out/
|
|
254
|
+
.next/
|
|
255
|
+
.nuxt/
|
|
256
|
+
.cache/
|
|
257
|
+
.parcel-cache/
|
|
258
|
+
|
|
259
|
+
# Environment
|
|
260
|
+
.env
|
|
261
|
+
.env.local
|
|
262
|
+
.env.*.local
|
|
263
|
+
*.env
|
|
264
|
+
|
|
265
|
+
# IDE
|
|
266
|
+
.vscode/
|
|
267
|
+
.idea/
|
|
268
|
+
*.swp
|
|
269
|
+
*.swo
|
|
270
|
+
*~
|
|
271
|
+
.DS_Store
|
|
272
|
+
|
|
273
|
+
# Logs
|
|
274
|
+
logs/
|
|
275
|
+
*.log
|
|
276
|
+
npm-debug.log*
|
|
277
|
+
yarn-debug.log*
|
|
278
|
+
yarn-error.log*
|
|
279
|
+
lerna-debug.log*
|
|
280
|
+
pnpm-debug.log*
|
|
281
|
+
|
|
282
|
+
# Testing
|
|
283
|
+
coverage/
|
|
284
|
+
.nyc_output/
|
|
285
|
+
*.lcov
|
|
286
|
+
|
|
287
|
+
# Temporary
|
|
288
|
+
tmp/
|
|
289
|
+
temp/
|
|
290
|
+
*.tmp
|
|
291
|
+
`,
|
|
292
|
+
node: `# Node
|
|
293
|
+
node_modules/
|
|
294
|
+
npm-debug.log*
|
|
295
|
+
yarn-debug.log*
|
|
296
|
+
yarn-error.log*
|
|
297
|
+
lerna-debug.log*
|
|
298
|
+
pnpm-debug.log*
|
|
299
|
+
.pnpm-store/
|
|
300
|
+
.npm
|
|
301
|
+
.eslintcache
|
|
302
|
+
.node_repl_history
|
|
303
|
+
*.tgz
|
|
304
|
+
.yarn-integrity
|
|
305
|
+
.env
|
|
306
|
+
.env.test
|
|
307
|
+
.env.production
|
|
308
|
+
.cache
|
|
309
|
+
.next/
|
|
310
|
+
out/
|
|
311
|
+
build/
|
|
312
|
+
dist/
|
|
313
|
+
`,
|
|
314
|
+
python: `# Python
|
|
315
|
+
__pycache__/
|
|
316
|
+
*.py[cod]
|
|
317
|
+
*$py.class
|
|
318
|
+
*.so
|
|
319
|
+
.Python
|
|
320
|
+
build/
|
|
321
|
+
develop-eggs/
|
|
322
|
+
dist/
|
|
323
|
+
downloads/
|
|
324
|
+
eggs/
|
|
325
|
+
.eggs/
|
|
326
|
+
lib/
|
|
327
|
+
lib64/
|
|
328
|
+
parts/
|
|
329
|
+
sdist/
|
|
330
|
+
var/
|
|
331
|
+
wheels/
|
|
332
|
+
*.egg-info/
|
|
333
|
+
.installed.cfg
|
|
334
|
+
*.egg
|
|
335
|
+
MANIFEST
|
|
336
|
+
pip-log.txt
|
|
337
|
+
pip-delete-this-directory.txt
|
|
338
|
+
.tox/
|
|
339
|
+
.coverage
|
|
340
|
+
.pytest_cache/
|
|
341
|
+
.mypy_cache/
|
|
342
|
+
.dmypy.json
|
|
343
|
+
dmypy.json
|
|
344
|
+
.env
|
|
345
|
+
.venv
|
|
346
|
+
env/
|
|
347
|
+
venv/
|
|
348
|
+
ENV/
|
|
349
|
+
`,
|
|
350
|
+
};
|
|
351
|
+
return templates[template] || templates.default;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
exports.GitIgnoreTool = GitIgnoreTool;
|
package/dist/tools/gitUpdate.js
CHANGED
|
@@ -145,14 +145,107 @@ class GitUpdateTool {
|
|
|
145
145
|
throw err;
|
|
146
146
|
}
|
|
147
147
|
}
|
|
148
|
-
// 5. Get remotes
|
|
148
|
+
// 5. Get remotes and ensure repos exist
|
|
149
149
|
const remotes = await git.getRemotes(true);
|
|
150
|
-
|
|
151
|
-
|
|
150
|
+
let githubRemote = remotes.find(r => r.name === 'github' || r.name === 'origin');
|
|
151
|
+
let giteaRemote = remotes.find(r => r.name === 'gitea');
|
|
152
|
+
// Auto-create repos if they don't exist
|
|
153
|
+
const repoName = params.repoName || path.basename(projectPath);
|
|
154
|
+
const description = params.description || `Project updated via git-update at ${new Date().toISOString()}`;
|
|
155
|
+
const isPrivate = params.private !== undefined ? params.private : true;
|
|
156
|
+
const githubOwner = params.owner || process.env.GITHUB_USERNAME;
|
|
157
|
+
const giteaOwner = process.env.GITEA_USERNAME;
|
|
158
|
+
// 5a. Ensure GitHub repo exists
|
|
159
|
+
if (ctx.providerManager.github && !githubRemote) {
|
|
160
|
+
results.traceability.updateSteps.push({
|
|
161
|
+
step: 5,
|
|
162
|
+
action: 'ensure_github_repo',
|
|
163
|
+
timestamp: new Date().toISOString(),
|
|
164
|
+
});
|
|
165
|
+
try {
|
|
166
|
+
// Try to get repo, create if doesn't exist
|
|
167
|
+
let repoExists = false;
|
|
168
|
+
try {
|
|
169
|
+
await ctx.providerManager.github.rest.repos.get({
|
|
170
|
+
owner: githubOwner,
|
|
171
|
+
repo: repoName
|
|
172
|
+
});
|
|
173
|
+
repoExists = true;
|
|
174
|
+
}
|
|
175
|
+
catch { }
|
|
176
|
+
if (!repoExists) {
|
|
177
|
+
await ctx.providerManager.github.rest.repos.createForAuthenticatedUser({
|
|
178
|
+
name: repoName,
|
|
179
|
+
description,
|
|
180
|
+
private: isPrivate,
|
|
181
|
+
auto_init: false,
|
|
182
|
+
});
|
|
183
|
+
results.traceability.updateSteps.push({
|
|
184
|
+
step: 5.1,
|
|
185
|
+
action: 'created_github_repo',
|
|
186
|
+
timestamp: new Date().toISOString(),
|
|
187
|
+
repo: repoName,
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
// Add remote
|
|
191
|
+
await git.addRemote('github', `https://github.com/${githubOwner}/${repoName}.git`);
|
|
192
|
+
githubRemote = { name: 'github', refs: { push: `https://github.com/${githubOwner}/${repoName}.git`, fetch: '' } };
|
|
193
|
+
}
|
|
194
|
+
catch (err) {
|
|
195
|
+
results.traceability.errors.push({
|
|
196
|
+
provider: 'github',
|
|
197
|
+
action: 'ensure_repo',
|
|
198
|
+
error: err.message,
|
|
199
|
+
timestamp: new Date().toISOString(),
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
// 5b. Ensure Gitea repo exists
|
|
204
|
+
if (ctx.providerManager.giteaBaseUrl && !giteaRemote) {
|
|
205
|
+
results.traceability.updateSteps.push({
|
|
206
|
+
step: 5.5,
|
|
207
|
+
action: 'ensure_gitea_repo',
|
|
208
|
+
timestamp: new Date().toISOString(),
|
|
209
|
+
});
|
|
210
|
+
try {
|
|
211
|
+
// Try to get repo, create if doesn't exist
|
|
212
|
+
let repoExists = false;
|
|
213
|
+
try {
|
|
214
|
+
await axios_1.default.get(`${ctx.providerManager.giteaBaseUrl}/api/v1/repos/${giteaOwner}/${repoName}`, { headers: { Authorization: `token ${ctx.providerManager.giteaToken}` } });
|
|
215
|
+
repoExists = true;
|
|
216
|
+
}
|
|
217
|
+
catch { }
|
|
218
|
+
if (!repoExists) {
|
|
219
|
+
await axios_1.default.post(`${ctx.providerManager.giteaBaseUrl}/api/v1/user/repos`, {
|
|
220
|
+
name: repoName,
|
|
221
|
+
description,
|
|
222
|
+
private: isPrivate,
|
|
223
|
+
auto_init: false,
|
|
224
|
+
}, { headers: { Authorization: `token ${ctx.providerManager.giteaToken}` } });
|
|
225
|
+
results.traceability.updateSteps.push({
|
|
226
|
+
step: 5.6,
|
|
227
|
+
action: 'created_gitea_repo',
|
|
228
|
+
timestamp: new Date().toISOString(),
|
|
229
|
+
repo: repoName,
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
// Add remote
|
|
233
|
+
await git.addRemote('gitea', `${ctx.providerManager.giteaBaseUrl}/${giteaOwner}/${repoName}.git`);
|
|
234
|
+
giteaRemote = { name: 'gitea', refs: { push: `${ctx.providerManager.giteaBaseUrl}/${giteaOwner}/${repoName}.git`, fetch: '' } };
|
|
235
|
+
}
|
|
236
|
+
catch (err) {
|
|
237
|
+
results.traceability.errors.push({
|
|
238
|
+
provider: 'gitea',
|
|
239
|
+
action: 'ensure_repo',
|
|
240
|
+
error: err.message,
|
|
241
|
+
timestamp: new Date().toISOString(),
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
}
|
|
152
245
|
// 6. Push to GITHUB
|
|
153
246
|
if (githubRemote && ctx.providerManager.github) {
|
|
154
247
|
results.traceability.updateSteps.push({
|
|
155
|
-
step:
|
|
248
|
+
step: 6,
|
|
156
249
|
action: 'push_to_github',
|
|
157
250
|
timestamp: new Date().toISOString(),
|
|
158
251
|
remote: githubRemote.name,
|
|
@@ -204,7 +297,7 @@ class GitUpdateTool {
|
|
|
204
297
|
// 7. Push to GITEA
|
|
205
298
|
if (giteaRemote && ctx.providerManager.giteaBaseUrl) {
|
|
206
299
|
results.traceability.updateSteps.push({
|
|
207
|
-
step:
|
|
300
|
+
step: 7,
|
|
208
301
|
action: 'push_to_gitea',
|
|
209
302
|
timestamp: new Date().toISOString(),
|
|
210
303
|
remote: giteaRemote.name,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@andrebuzeli/git-mcp",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.2.0",
|
|
4
4
|
"description": "Professional MCP server for Git operations - STDIO UNIVERSAL: works in ANY IDE (Cursor, VSCode, Claude Desktop). Fully autonomous DUAL execution (GitHub + Gitea APIs) with automatic username detection. All tools execute on BOTH providers simultaneously. No manual parameters needed.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|