@andrebuzeli/git-mcp 5.5.2 → 5.8.1

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.
@@ -10,16 +10,17 @@ const axios_1 = __importDefault(require("axios"));
10
10
  class GitReleaseTool {
11
11
  constructor() {
12
12
  this.name = 'git-release';
13
- this.description = 'Release management operations';
13
+ this.description = 'Release management operations - automatic dual-provider execution';
14
14
  }
15
15
  async handle(params, ctx) {
16
16
  const action = params.action;
17
17
  const projectPath = params.projectPath;
18
- if (!action || !projectPath) {
19
- throw new errors_1.MCPError('VALIDATION_ERROR', 'action and projectPath are required');
20
- }
21
- const provider = params.provider;
22
- const owner = params.owner || process.env.GITHUB_USERNAME || process.env.GITEA_USERNAME;
18
+ if (!action)
19
+ throw new errors_1.MCPError('VALIDATION_ERROR', 'action is required');
20
+ if (!projectPath)
21
+ throw new errors_1.MCPError('VALIDATION_ERROR', 'projectPath is required');
22
+ const githubOwner = params.owner || process.env.GITHUB_USERNAME;
23
+ const giteaOwner = params.owner || process.env.GITEA_USERNAME;
23
24
  const repo = params.repo;
24
25
  switch (action) {
25
26
  case 'create': {
@@ -28,69 +29,290 @@ class GitReleaseTool {
28
29
  throw new errors_1.MCPError('VALIDATION_ERROR', 'tagName is required');
29
30
  const git = (0, simple_git_1.default)({ baseDir: projectPath });
30
31
  await git.addAnnotatedTag(tagName, params.description || tagName);
31
- if (provider === 'github' && ctx.providerManager.github) {
32
- const result = await ctx.providerManager.github.rest.repos.createRelease({
33
- owner: owner,
34
- repo: repo,
35
- tag_name: tagName,
36
- name: params.releaseName || tagName,
37
- body: params.body,
38
- draft: params.draft || false,
39
- prerelease: params.prerelease || false,
40
- });
41
- return { success: true, release: result.data };
32
+ const results = { success: true, localTag: tagName, providers: {} };
33
+ if (ctx.providerManager.github) {
34
+ try {
35
+ const result = await ctx.providerManager.github.rest.repos.createRelease({
36
+ owner: githubOwner,
37
+ repo: repo,
38
+ tag_name: tagName,
39
+ name: params.releaseName || tagName,
40
+ body: params.body,
41
+ draft: params.draft || false,
42
+ prerelease: params.prerelease || false,
43
+ });
44
+ results.providers.github = { success: true, release: result.data };
45
+ }
46
+ catch (err) {
47
+ results.providers.github = { success: false, error: err.message };
48
+ }
42
49
  }
43
- if (provider === 'gitea' && ctx.providerManager.giteaBaseUrl) {
44
- const result = await axios_1.default.post(`${ctx.providerManager.giteaBaseUrl}/api/v1/repos/${owner}/${repo}/releases`, {
45
- tag_name: tagName,
46
- name: params.releaseName || tagName,
47
- body: params.body,
48
- draft: params.draft || false,
49
- prerelease: params.prerelease || false,
50
- }, { headers: { Authorization: `token ${ctx.providerManager.giteaToken}` } });
51
- return { success: true, release: result.data };
50
+ if (ctx.providerManager.giteaBaseUrl) {
51
+ try {
52
+ const result = await axios_1.default.post(`${ctx.providerManager.giteaBaseUrl}/api/v1/repos/${giteaOwner}/${repo}/releases`, {
53
+ tag_name: tagName,
54
+ name: params.releaseName || tagName,
55
+ body: params.body,
56
+ draft: params.draft || false,
57
+ prerelease: params.prerelease || false,
58
+ }, { headers: { Authorization: `token ${ctx.providerManager.giteaToken}` } });
59
+ results.providers.gitea = { success: true, release: result.data };
60
+ }
61
+ catch (err) {
62
+ results.providers.gitea = { success: false, error: err.message };
63
+ }
52
64
  }
53
- return { success: true, tag: tagName, message: 'Local tag created' };
65
+ return results;
54
66
  }
55
67
  case 'list': {
56
- if (provider === 'github' && ctx.providerManager.github) {
57
- const result = await ctx.providerManager.github.rest.repos.listReleases({
58
- owner: owner,
59
- repo: repo,
60
- });
61
- return { success: true, releases: result.data };
68
+ const results = { success: true, providers: {} };
69
+ if (ctx.providerManager.github) {
70
+ try {
71
+ const result = await ctx.providerManager.github.rest.repos.listReleases({
72
+ owner: githubOwner,
73
+ repo: repo,
74
+ });
75
+ results.providers.github = { success: true, releases: result.data };
76
+ }
77
+ catch (err) {
78
+ results.providers.github = { success: false, error: err.message };
79
+ }
62
80
  }
63
- if (provider === 'gitea' && ctx.providerManager.giteaBaseUrl) {
64
- const result = await axios_1.default.get(`${ctx.providerManager.giteaBaseUrl}/api/v1/repos/${owner}/${repo}/releases`, { headers: { Authorization: `token ${ctx.providerManager.giteaToken}` } });
65
- return { success: true, releases: result.data };
81
+ if (ctx.providerManager.giteaBaseUrl) {
82
+ try {
83
+ const result = await axios_1.default.get(`${ctx.providerManager.giteaBaseUrl}/api/v1/repos/${giteaOwner}/${repo}/releases`, { headers: { Authorization: `token ${ctx.providerManager.giteaToken}` } });
84
+ results.providers.gitea = { success: true, releases: result.data };
85
+ }
86
+ catch (err) {
87
+ results.providers.gitea = { success: false, error: err.message };
88
+ }
66
89
  }
67
- const git = (0, simple_git_1.default)({ baseDir: projectPath });
68
- const tags = await git.tags();
69
- return { success: true, tags: tags.all };
90
+ return results;
70
91
  }
71
92
  case 'get': {
72
93
  const tagName = params.tagName;
73
94
  if (!tagName)
74
95
  throw new errors_1.MCPError('VALIDATION_ERROR', 'tagName is required');
75
- if (provider === 'github' && ctx.providerManager.github) {
76
- const result = await ctx.providerManager.github.rest.repos.getReleaseByTag({
77
- owner: owner,
78
- repo: repo,
79
- tag: tagName,
80
- });
81
- return { success: true, release: result.data };
96
+ const results = { success: true, providers: {} };
97
+ if (ctx.providerManager.github) {
98
+ try {
99
+ const result = await ctx.providerManager.github.rest.repos.getReleaseByTag({
100
+ owner: githubOwner,
101
+ repo: repo,
102
+ tag: tagName,
103
+ });
104
+ results.providers.github = { success: true, release: result.data };
105
+ }
106
+ catch (err) {
107
+ results.providers.github = { success: false, error: err.message };
108
+ }
109
+ }
110
+ if (ctx.providerManager.giteaBaseUrl) {
111
+ try {
112
+ const result = await axios_1.default.get(`${ctx.providerManager.giteaBaseUrl}/api/v1/repos/${giteaOwner}/${repo}/releases/tags/${tagName}`, { headers: { Authorization: `token ${ctx.providerManager.giteaToken}` } });
113
+ results.providers.gitea = { success: true, release: result.data };
114
+ }
115
+ catch (err) {
116
+ results.providers.gitea = { success: false, error: err.message };
117
+ }
118
+ }
119
+ return results;
120
+ }
121
+ case 'update': {
122
+ const tagName = params.tagName;
123
+ if (!tagName)
124
+ throw new errors_1.MCPError('VALIDATION_ERROR', 'tagName is required');
125
+ const results = { success: true, providers: {} };
126
+ // GitHub
127
+ if (ctx.providerManager.github) {
128
+ try {
129
+ const releases = await ctx.providerManager.github.rest.repos.listReleases({
130
+ owner: githubOwner,
131
+ repo: repo,
132
+ });
133
+ const release = releases.data.find((r) => r.tag_name === tagName);
134
+ if (!release) {
135
+ results.providers.github = { success: false, error: 'Release not found' };
136
+ }
137
+ else {
138
+ const result = await ctx.providerManager.github.rest.repos.updateRelease({
139
+ owner: githubOwner,
140
+ repo: repo,
141
+ release_id: release.id,
142
+ name: params.releaseName,
143
+ body: params.body,
144
+ draft: params.draft,
145
+ prerelease: params.prerelease,
146
+ });
147
+ results.providers.github = { success: true, release: result.data };
148
+ }
149
+ }
150
+ catch (err) {
151
+ results.providers.github = { success: false, error: err.message };
152
+ }
153
+ }
154
+ // Gitea
155
+ if (ctx.providerManager.giteaBaseUrl) {
156
+ try {
157
+ const releases = await axios_1.default.get(`${ctx.providerManager.giteaBaseUrl}/api/v1/repos/${giteaOwner}/${repo}/releases`, { headers: { Authorization: `token ${ctx.providerManager.giteaToken}` } });
158
+ const release = releases.data.find((r) => r.tag_name === tagName);
159
+ if (!release) {
160
+ results.providers.gitea = { success: false, error: 'Release not found' };
161
+ }
162
+ else {
163
+ const result = await axios_1.default.patch(`${ctx.providerManager.giteaBaseUrl}/api/v1/repos/${giteaOwner}/${repo}/releases/${release.id}`, {
164
+ name: params.releaseName,
165
+ body: params.body,
166
+ draft: params.draft,
167
+ prerelease: params.prerelease,
168
+ }, { headers: { Authorization: `token ${ctx.providerManager.giteaToken}` } });
169
+ results.providers.gitea = { success: true, release: result.data };
170
+ }
171
+ }
172
+ catch (err) {
173
+ results.providers.gitea = { success: false, error: err.message };
174
+ }
175
+ }
176
+ return results;
177
+ }
178
+ case 'delete': {
179
+ const tagName = params.tagName;
180
+ if (!tagName)
181
+ throw new errors_1.MCPError('VALIDATION_ERROR', 'tagName is required');
182
+ const results = { success: true, providers: {} };
183
+ // GitHub
184
+ if (ctx.providerManager.github) {
185
+ try {
186
+ const releases = await ctx.providerManager.github.rest.repos.listReleases({
187
+ owner: githubOwner,
188
+ repo: repo,
189
+ });
190
+ const release = releases.data.find((r) => r.tag_name === tagName);
191
+ if (!release) {
192
+ results.providers.github = { success: false, error: 'Release not found' };
193
+ }
194
+ else {
195
+ await ctx.providerManager.github.rest.repos.deleteRelease({
196
+ owner: githubOwner,
197
+ repo: repo,
198
+ release_id: release.id,
199
+ });
200
+ results.providers.github = { success: true, deleted: true };
201
+ }
202
+ }
203
+ catch (err) {
204
+ results.providers.github = { success: false, error: err.message };
205
+ }
206
+ }
207
+ // Gitea
208
+ if (ctx.providerManager.giteaBaseUrl) {
209
+ try {
210
+ const releases = await axios_1.default.get(`${ctx.providerManager.giteaBaseUrl}/api/v1/repos/${giteaOwner}/${repo}/releases`, { headers: { Authorization: `token ${ctx.providerManager.giteaToken}` } });
211
+ const release = releases.data.find((r) => r.tag_name === tagName);
212
+ if (!release) {
213
+ results.providers.gitea = { success: false, error: 'Release not found' };
214
+ }
215
+ else {
216
+ await axios_1.default.delete(`${ctx.providerManager.giteaBaseUrl}/api/v1/repos/${giteaOwner}/${repo}/releases/${release.id}`, { headers: { Authorization: `token ${ctx.providerManager.giteaToken}` } });
217
+ results.providers.gitea = { success: true, deleted: true };
218
+ }
219
+ }
220
+ catch (err) {
221
+ results.providers.gitea = { success: false, error: err.message };
222
+ }
223
+ }
224
+ return results;
225
+ }
226
+ case 'publish': {
227
+ const tagName = params.tagName;
228
+ if (!tagName)
229
+ throw new errors_1.MCPError('VALIDATION_ERROR', 'tagName is required');
230
+ const results = { success: true, providers: {} };
231
+ // GitHub - publish = set draft: false
232
+ if (ctx.providerManager.github) {
233
+ try {
234
+ const releases = await ctx.providerManager.github.rest.repos.listReleases({
235
+ owner: githubOwner,
236
+ repo: repo,
237
+ });
238
+ const release = releases.data.find((r) => r.tag_name === tagName);
239
+ if (!release) {
240
+ results.providers.github = { success: false, error: 'Release not found' };
241
+ }
242
+ else {
243
+ const result = await ctx.providerManager.github.rest.repos.updateRelease({
244
+ owner: githubOwner,
245
+ repo: repo,
246
+ release_id: release.id,
247
+ draft: false,
248
+ });
249
+ results.providers.github = { success: true, release: result.data };
250
+ }
251
+ }
252
+ catch (err) {
253
+ results.providers.github = { success: false, error: err.message };
254
+ }
255
+ }
256
+ // Gitea - publish = set draft: false
257
+ if (ctx.providerManager.giteaBaseUrl) {
258
+ try {
259
+ const releases = await axios_1.default.get(`${ctx.providerManager.giteaBaseUrl}/api/v1/repos/${giteaOwner}/${repo}/releases`, { headers: { Authorization: `token ${ctx.providerManager.giteaToken}` } });
260
+ const release = releases.data.find((r) => r.tag_name === tagName);
261
+ if (!release) {
262
+ results.providers.gitea = { success: false, error: 'Release not found' };
263
+ }
264
+ else {
265
+ const result = await axios_1.default.patch(`${ctx.providerManager.giteaBaseUrl}/api/v1/repos/${giteaOwner}/${repo}/releases/${release.id}`, { draft: false }, { headers: { Authorization: `token ${ctx.providerManager.giteaToken}` } });
266
+ results.providers.gitea = { success: true, release: result.data };
267
+ }
268
+ }
269
+ catch (err) {
270
+ results.providers.gitea = { success: false, error: err.message };
271
+ }
272
+ }
273
+ return results;
274
+ }
275
+ case 'download': {
276
+ const tagName = params.tagName;
277
+ if (!tagName)
278
+ throw new errors_1.MCPError('VALIDATION_ERROR', 'tagName is required');
279
+ const results = { success: true, providers: {} };
280
+ // GitHub
281
+ if (ctx.providerManager.github) {
282
+ try {
283
+ const result = await ctx.providerManager.github.rest.repos.getReleaseByTag({
284
+ owner: githubOwner,
285
+ repo: repo,
286
+ tag: tagName,
287
+ });
288
+ const assets = result.data.assets.map((a) => ({
289
+ name: a.name,
290
+ url: a.browser_download_url,
291
+ size: a.size,
292
+ }));
293
+ results.providers.github = { success: true, release: result.data, assets, download_urls: assets };
294
+ }
295
+ catch (err) {
296
+ results.providers.github = { success: false, error: err.message };
297
+ }
82
298
  }
83
- if (provider === 'gitea' && ctx.providerManager.giteaBaseUrl) {
84
- const result = await axios_1.default.get(`${ctx.providerManager.giteaBaseUrl}/api/v1/repos/${owner}/${repo}/releases/tags/${tagName}`, { headers: { Authorization: `token ${ctx.providerManager.giteaToken}` } });
85
- return { success: true, release: result.data };
299
+ // Gitea
300
+ if (ctx.providerManager.giteaBaseUrl) {
301
+ try {
302
+ const result = await axios_1.default.get(`${ctx.providerManager.giteaBaseUrl}/api/v1/repos/${giteaOwner}/${repo}/releases/tags/${tagName}`, { headers: { Authorization: `token ${ctx.providerManager.giteaToken}` } });
303
+ const assets = result.data.assets?.map((a) => ({
304
+ name: a.name,
305
+ url: a.browser_download_url,
306
+ size: a.size,
307
+ })) || [];
308
+ results.providers.gitea = { success: true, release: result.data, assets, download_urls: assets };
309
+ }
310
+ catch (err) {
311
+ results.providers.gitea = { success: false, error: err.message };
312
+ }
86
313
  }
87
- throw new errors_1.MCPError('VALIDATION_ERROR', 'Provider required for get operation');
314
+ return results;
88
315
  }
89
- case 'update':
90
- case 'delete':
91
- case 'publish':
92
- case 'download':
93
- throw new errors_1.MCPError('NOT_IMPLEMENTED', `Action ${action} not yet fully implemented`);
94
316
  default:
95
317
  throw new errors_1.MCPError('VALIDATION_ERROR', `Unsupported action: ${action}`);
96
318
  }
@@ -0,0 +1,14 @@
1
+ import { Tool, MCPContext } from '../types';
2
+ /**
3
+ * Git Update Tool - Atualiza projeto completo em GitHub e Gitea automaticamente
4
+ * Modo DUAL automático com rastreabilidade completa
5
+ * Inclui: add, commit, push, sync, history tracking
6
+ */
7
+ export declare class GitUpdateTool implements Tool {
8
+ name: string;
9
+ description: string;
10
+ handle(params: Record<string, any>, ctx: MCPContext): Promise<any>;
11
+ private saveUpdateHistory;
12
+ private createRemoteHistory;
13
+ private formatHistoryIssue;
14
+ }