@andrebuzeli/git-mcp 10.0.9 → 11.0.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/README.md +34 -428
- package/bin/git-mcp.js +21 -0
- package/docs/TOOLS.md +110 -0
- package/mcp.json.template +12 -0
- package/package.json +9 -76
- package/src/local/git.js +14 -0
- package/src/providers/gitea.js +13 -0
- package/src/providers/github.js +13 -0
- package/src/server.js +63 -0
- package/src/tools/git-actions.js +19 -0
- package/src/tools/git-activity.js +28 -0
- package/src/tools/git-admin.js +20 -0
- package/src/tools/git-checks.js +14 -0
- package/src/tools/git-commits.js +34 -0
- package/src/tools/git-contents.js +30 -0
- package/src/tools/git-deployments.js +21 -0
- package/src/tools/git-gists.js +15 -0
- package/src/tools/git-gitdata.js +19 -0
- package/src/tools/git-issues-prs.js +44 -0
- package/src/tools/git-issues.js +12 -0
- package/src/tools/git-local.js +66 -0
- package/src/tools/git-meta.js +19 -0
- package/src/tools/git-misc.js +21 -0
- package/src/tools/git-orgs.js +26 -0
- package/src/tools/git-packages.js +12 -0
- package/src/tools/git-raw.js +14 -0
- package/src/tools/git-releases.js +17 -0
- package/src/tools/git-remote.js +29 -0
- package/src/tools/git-repos.js +60 -0
- package/src/tools/git-search.js +18 -0
- package/src/tools/git-sync.js +40 -0
- package/src/tools/git-user.js +26 -0
- package/src/tools/schema.js +3 -0
- package/src/utils/fs.js +29 -0
- package/src/utils/project.js +7 -0
- package/tests/errors.js +26 -0
- package/tests/full_suite.js +98 -0
- package/tests/run.js +50 -0
- package/LICENSE +0 -21
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -224
- package/dist/prompts/gitPrompts.d.ts +0 -93
- package/dist/prompts/gitPrompts.js +0 -177
- package/dist/providers/giteaProvider.d.ts +0 -3
- package/dist/providers/giteaProvider.js +0 -6
- package/dist/providers/githubProvider.d.ts +0 -2
- package/dist/providers/githubProvider.js +0 -4
- package/dist/providers/providerManager.d.ts +0 -11
- package/dist/providers/providerManager.js +0 -49
- package/dist/resources/toolsGuide.d.ts +0 -12
- package/dist/resources/toolsGuide.js +0 -1713
- package/dist/scripts/test_e2e.d.ts +0 -1
- package/dist/scripts/test_e2e.js +0 -199
- package/dist/scripts/test_exhaustive.d.ts +0 -1
- package/dist/scripts/test_exhaustive.js +0 -275
- package/dist/scripts/test_gitea_creation.d.ts +0 -1
- package/dist/scripts/test_gitea_creation.js +0 -116
- package/dist/scripts/verify_setup.d.ts +0 -1
- package/dist/scripts/verify_setup.js +0 -61
- package/dist/server.d.ts +0 -9
- package/dist/server.js +0 -73
- package/dist/tools/gitAnalytics.d.ts +0 -35
- package/dist/tools/gitAnalytics.js +0 -220
- package/dist/tools/gitArchive.d.ts +0 -119
- package/dist/tools/gitArchive.js +0 -150
- package/dist/tools/gitBackup.d.ts +0 -116
- package/dist/tools/gitBackup.js +0 -156
- package/dist/tools/gitBranches.d.ts +0 -54
- package/dist/tools/gitBranches.js +0 -282
- package/dist/tools/gitChangelog.d.ts +0 -37
- package/dist/tools/gitChangelog.js +0 -67
- package/dist/tools/gitConfig.d.ts +0 -97
- package/dist/tools/gitConfig.js +0 -125
- package/dist/tools/gitFiles.d.ts +0 -129
- package/dist/tools/gitFiles.js +0 -213
- package/dist/tools/gitFix.d.ts +0 -4
- package/dist/tools/gitFix.js +0 -159
- package/dist/tools/gitFix.tool.d.ts +0 -31
- package/dist/tools/gitFix.tool.js +0 -92
- package/dist/tools/gitHistory.d.ts +0 -41
- package/dist/tools/gitHistory.js +0 -349
- package/dist/tools/gitIgnore.d.ts +0 -214
- package/dist/tools/gitIgnore.js +0 -338
- package/dist/tools/gitIssues.d.ts +0 -80
- package/dist/tools/gitIssues.js +0 -363
- package/dist/tools/gitLog.d.ts +0 -30
- package/dist/tools/gitLog.js +0 -46
- package/dist/tools/gitMonitor.d.ts +0 -30
- package/dist/tools/gitMonitor.js +0 -284
- package/dist/tools/gitPackages.d.ts +0 -180
- package/dist/tools/gitPackages.js +0 -214
- package/dist/tools/gitPulls.d.ts +0 -66
- package/dist/tools/gitPulls.js +0 -347
- package/dist/tools/gitPush.d.ts +0 -40
- package/dist/tools/gitPush.js +0 -59
- package/dist/tools/gitRelease.d.ts +0 -49
- package/dist/tools/gitRelease.js +0 -359
- package/dist/tools/gitRemote.d.ts +0 -47
- package/dist/tools/gitRemote.js +0 -111
- package/dist/tools/gitReset.d.ts +0 -57
- package/dist/tools/gitReset.js +0 -79
- package/dist/tools/gitStash.d.ts +0 -61
- package/dist/tools/gitStash.js +0 -80
- package/dist/tools/gitSync.d.ts +0 -34
- package/dist/tools/gitSync.js +0 -182
- package/dist/tools/gitTags.d.ts +0 -45
- package/dist/tools/gitTags.js +0 -251
- package/dist/tools/gitUpdate.d.ts +0 -60
- package/dist/tools/gitUpdate.js +0 -474
- package/dist/tools/gitUpload.d.ts +0 -35
- package/dist/tools/gitUpload.js +0 -385
- package/dist/tools/gitWorkflow.d.ts +0 -117
- package/dist/tools/gitWorkflow.js +0 -472
- package/dist/types.d.ts +0 -20
- package/dist/types.js +0 -1
- package/dist/utils/agentHelpers.d.ts +0 -11
- package/dist/utils/agentHelpers.js +0 -41
- package/dist/utils/apiHelpers.d.ts +0 -29
- package/dist/utils/apiHelpers.js +0 -125
- package/dist/utils/cache.d.ts +0 -96
- package/dist/utils/cache.js +0 -208
- package/dist/utils/contextDetector.d.ts +0 -0
- package/dist/utils/contextDetector.js +0 -1
- package/dist/utils/errors.d.ts +0 -13
- package/dist/utils/errors.js +0 -17
- package/dist/utils/gitAdapter.d.ts +0 -224
- package/dist/utils/gitAdapter.js +0 -1162
- package/dist/utils/logger.d.ts +0 -45
- package/dist/utils/logger.js +0 -140
- package/dist/utils/rateLimiter.d.ts +0 -113
- package/dist/utils/rateLimiter.js +0 -257
- package/dist/utils/repoHelpers.d.ts +0 -44
- package/dist/utils/repoHelpers.js +0 -122
- package/dist/utils/safetyController.d.ts +0 -1
- package/dist/utils/safetyController.js +0 -12
- package/dist/utils/validation.d.ts +0 -115
- package/dist/utils/validation.js +0 -270
|
@@ -1,472 +0,0 @@
|
|
|
1
|
-
import { MCPError } from '../utils/errors.js';
|
|
2
|
-
import { normalizeToolParams } from '../utils/repoHelpers.js';
|
|
3
|
-
import axios from 'axios';
|
|
4
|
-
/**
|
|
5
|
-
* Git Workflow Tool - Operações Git principais com segurança aprimorada
|
|
6
|
-
* VERSÃO SEGURA: Remove exposição de tokens, validação robusta, sem --force por padrão
|
|
7
|
-
*/
|
|
8
|
-
export class GitWorkflowTool {
|
|
9
|
-
constructor() {
|
|
10
|
-
this.name = 'git-workflow';
|
|
11
|
-
this.description = 'Core Git operations including init, status, commit, sync, backup, and remote operations - automatic dual-provider for remote ops';
|
|
12
|
-
this.inputSchema = {
|
|
13
|
-
type: "object",
|
|
14
|
-
properties: {
|
|
15
|
-
projectPath: {
|
|
16
|
-
type: "string",
|
|
17
|
-
description: "Absolute path to the project/repository (REQUIRED)"
|
|
18
|
-
},
|
|
19
|
-
action: {
|
|
20
|
-
type: "string",
|
|
21
|
-
enum: ["init", "status", "commit", "sync", "backup", "create", "list", "get", "update", "delete", "fork", "search", "push"],
|
|
22
|
-
description: "Action to perform: init (initialize repo), status (get repo status), commit (commit changes), sync (fetch/pull/push), backup (create backup), create (create repo on providers), list (list user repos), get (get repo details), update (update repo settings), delete (delete repo), fork (fork repo), search (search repos), push (push to remote)"
|
|
23
|
-
},
|
|
24
|
-
message: {
|
|
25
|
-
type: "string",
|
|
26
|
-
description: "Commit message (required for commit action)"
|
|
27
|
-
},
|
|
28
|
-
files: {
|
|
29
|
-
type: "array",
|
|
30
|
-
items: { type: "string" },
|
|
31
|
-
description: "Files to add (optional for commit, default: ['.'])"
|
|
32
|
-
},
|
|
33
|
-
remote: {
|
|
34
|
-
type: "string",
|
|
35
|
-
description: "Remote name (optional for sync/push, default: 'origin')"
|
|
36
|
-
},
|
|
37
|
-
branch: {
|
|
38
|
-
type: "string",
|
|
39
|
-
description: "Branch name (optional for sync/push)"
|
|
40
|
-
},
|
|
41
|
-
backupPath: {
|
|
42
|
-
type: "string",
|
|
43
|
-
description: "Path for backup file (optional for backup)"
|
|
44
|
-
},
|
|
45
|
-
name: {
|
|
46
|
-
type: "string",
|
|
47
|
-
description: "Repository name (required for create)"
|
|
48
|
-
},
|
|
49
|
-
owner: {
|
|
50
|
-
type: "string",
|
|
51
|
-
description: "Repository owner (optional for create/get/update/delete/fork, uses env vars if not provided)"
|
|
52
|
-
},
|
|
53
|
-
repo: {
|
|
54
|
-
type: "string",
|
|
55
|
-
description: "Repository name (required for get/update/delete/fork)"
|
|
56
|
-
},
|
|
57
|
-
description: {
|
|
58
|
-
type: "string",
|
|
59
|
-
description: "Repository description (optional for create/update)"
|
|
60
|
-
},
|
|
61
|
-
private: {
|
|
62
|
-
type: "boolean",
|
|
63
|
-
description: "Make repository private (optional for create/update, default: true)"
|
|
64
|
-
},
|
|
65
|
-
has_issues: {
|
|
66
|
-
type: "boolean",
|
|
67
|
-
description: "Enable issues (optional for update)"
|
|
68
|
-
},
|
|
69
|
-
has_projects: {
|
|
70
|
-
type: "boolean",
|
|
71
|
-
description: "Enable projects (optional for update)"
|
|
72
|
-
},
|
|
73
|
-
has_wiki: {
|
|
74
|
-
type: "boolean",
|
|
75
|
-
description: "Enable wiki (optional for update)"
|
|
76
|
-
},
|
|
77
|
-
organization: {
|
|
78
|
-
type: "string",
|
|
79
|
-
description: "Organization for fork (optional for fork)"
|
|
80
|
-
},
|
|
81
|
-
query: {
|
|
82
|
-
type: "string",
|
|
83
|
-
description: "Search query (required for search)"
|
|
84
|
-
},
|
|
85
|
-
sort: {
|
|
86
|
-
type: "string",
|
|
87
|
-
description: "Sort field (optional for search)"
|
|
88
|
-
},
|
|
89
|
-
order: {
|
|
90
|
-
type: "string",
|
|
91
|
-
description: "Sort order (optional for search)"
|
|
92
|
-
},
|
|
93
|
-
limit: {
|
|
94
|
-
type: "number",
|
|
95
|
-
description: "Result limit (optional for search, default: 30)"
|
|
96
|
-
},
|
|
97
|
-
force: {
|
|
98
|
-
type: "boolean",
|
|
99
|
-
description: "Force push - REQUIRES confirmDestructive: true (optional for push, default: false)"
|
|
100
|
-
},
|
|
101
|
-
setUpstream: {
|
|
102
|
-
type: "boolean",
|
|
103
|
-
description: "Set upstream (optional for push, default: true)"
|
|
104
|
-
},
|
|
105
|
-
bare: {
|
|
106
|
-
type: "boolean",
|
|
107
|
-
description: "Initialize as bare repo (optional for init, default: false)"
|
|
108
|
-
},
|
|
109
|
-
confirmDestructive: {
|
|
110
|
-
type: "boolean",
|
|
111
|
-
description: "Required confirmation for destructive operations like force push (default: false)"
|
|
112
|
-
}
|
|
113
|
-
},
|
|
114
|
-
required: ["projectPath", "action"],
|
|
115
|
-
additionalProperties: true
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
async handle(params, ctx) {
|
|
119
|
-
// Normalize parameters to handle different IDE/agent formats
|
|
120
|
-
params = normalizeToolParams(params);
|
|
121
|
-
const action = params.action;
|
|
122
|
-
if (!action)
|
|
123
|
-
throw new MCPError('VALIDATION_ERROR', 'action is required. You can use either "action" or "command" parameter.');
|
|
124
|
-
const projectPath = params.projectPath;
|
|
125
|
-
// Validação de path para segurança
|
|
126
|
-
if (projectPath) {
|
|
127
|
-
const path = await import('path');
|
|
128
|
-
const resolvedPath = path.resolve(projectPath);
|
|
129
|
-
// Verificar se é um diretório válido e não está tentando escapar
|
|
130
|
-
if (!resolvedPath || resolvedPath.includes('..')) {
|
|
131
|
-
throw new MCPError('VALIDATION_ERROR', 'Invalid project path provided');
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
if (!ctx.gitAdapter) {
|
|
135
|
-
throw new MCPError('INTERNAL_ERROR', 'Git adapter not available');
|
|
136
|
-
}
|
|
137
|
-
switch (action) {
|
|
138
|
-
case 'init': {
|
|
139
|
-
if (!projectPath)
|
|
140
|
-
throw new MCPError('VALIDATION_ERROR', 'projectPath is required for init');
|
|
141
|
-
await ctx.gitAdapter.init(projectPath);
|
|
142
|
-
return { success: true, path: projectPath };
|
|
143
|
-
}
|
|
144
|
-
case 'status': {
|
|
145
|
-
if (!projectPath)
|
|
146
|
-
throw new MCPError('VALIDATION_ERROR', 'projectPath is required for status');
|
|
147
|
-
const status = await ctx.gitAdapter.status(projectPath);
|
|
148
|
-
return { success: true, status };
|
|
149
|
-
}
|
|
150
|
-
case 'commit': {
|
|
151
|
-
if (!projectPath)
|
|
152
|
-
throw new MCPError('VALIDATION_ERROR', 'projectPath is required for commit');
|
|
153
|
-
const message = params.message;
|
|
154
|
-
if (!message)
|
|
155
|
-
throw new MCPError('VALIDATION_ERROR', 'Commit message is required');
|
|
156
|
-
let files = params.files || ['.'];
|
|
157
|
-
// Handle case where files might be passed as a string (e.g., from some agents)
|
|
158
|
-
if (typeof files === 'string') {
|
|
159
|
-
files = files === '.' ? ['.'] : files.split(',').map(f => f.trim());
|
|
160
|
-
}
|
|
161
|
-
// Ensure files is an array
|
|
162
|
-
if (!Array.isArray(files)) {
|
|
163
|
-
files = [files];
|
|
164
|
-
}
|
|
165
|
-
try {
|
|
166
|
-
await ctx.gitAdapter.add(projectPath, files);
|
|
167
|
-
}
|
|
168
|
-
catch (addErr) {
|
|
169
|
-
console.warn(`Failed to add files: ${addErr.message}`);
|
|
170
|
-
throw addErr;
|
|
171
|
-
}
|
|
172
|
-
const result = await ctx.gitAdapter.commit(projectPath, message);
|
|
173
|
-
return { success: true, commit: result };
|
|
174
|
-
}
|
|
175
|
-
case 'sync': {
|
|
176
|
-
if (!projectPath)
|
|
177
|
-
throw new MCPError('VALIDATION_ERROR', 'projectPath is required for sync');
|
|
178
|
-
const remote = params.remote || 'origin';
|
|
179
|
-
let branch = params.branch;
|
|
180
|
-
if (!branch) {
|
|
181
|
-
branch = await ctx.gitAdapter.getCurrentBranch(projectPath);
|
|
182
|
-
}
|
|
183
|
-
await ctx.gitAdapter.fetch(projectPath, remote);
|
|
184
|
-
await ctx.gitAdapter.pull(projectPath, remote, branch);
|
|
185
|
-
await ctx.gitAdapter.push(projectPath, remote, branch);
|
|
186
|
-
return { success: true, message: 'Repository synced' };
|
|
187
|
-
}
|
|
188
|
-
case 'backup': {
|
|
189
|
-
const backupPath = params.backupPath || `${projectPath}-backup-${Date.now()}.tar.gz`;
|
|
190
|
-
return { success: true, backupPath, message: 'Backup marked (simplified)' };
|
|
191
|
-
}
|
|
192
|
-
case 'create': {
|
|
193
|
-
const name = params.name;
|
|
194
|
-
if (!name)
|
|
195
|
-
throw new MCPError('VALIDATION_ERROR', 'name is required');
|
|
196
|
-
const githubOwner = params.owner || process.env.GITHUB_USERNAME;
|
|
197
|
-
const giteaOwner = params.owner || process.env.GITEA_USERNAME;
|
|
198
|
-
const results = { success: true, providers: {} };
|
|
199
|
-
// GitHub
|
|
200
|
-
if (ctx.providerManager.github && githubOwner) {
|
|
201
|
-
try {
|
|
202
|
-
const result = await ctx.providerManager.github.rest.repos.createForAuthenticatedUser({
|
|
203
|
-
name,
|
|
204
|
-
description: params.description,
|
|
205
|
-
private: params.private || false,
|
|
206
|
-
});
|
|
207
|
-
results.providers.github = { success: true, repo: result.data };
|
|
208
|
-
}
|
|
209
|
-
catch (err) {
|
|
210
|
-
results.providers.github = { success: false, error: err.message };
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
// Gitea
|
|
214
|
-
if (ctx.providerManager.giteaBaseUrl && giteaOwner) {
|
|
215
|
-
try {
|
|
216
|
-
const result = await axios.post(`${ctx.providerManager.giteaBaseUrl}/api/v1/user/repos`, {
|
|
217
|
-
name,
|
|
218
|
-
description: params.description,
|
|
219
|
-
private: params.private || false,
|
|
220
|
-
}, { headers: { Authorization: `token ${ctx.providerManager.giteaToken}` } });
|
|
221
|
-
results.providers.gitea = { success: true, repo: result.data };
|
|
222
|
-
}
|
|
223
|
-
catch (err) {
|
|
224
|
-
results.providers.gitea = { success: false, error: err.message };
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
return results;
|
|
228
|
-
}
|
|
229
|
-
case 'list': {
|
|
230
|
-
const results = { success: true, providers: {} };
|
|
231
|
-
// GitHub
|
|
232
|
-
if (ctx.providerManager.github) {
|
|
233
|
-
try {
|
|
234
|
-
const result = await ctx.providerManager.github.rest.repos.listForAuthenticatedUser();
|
|
235
|
-
results.providers.github = { success: true, repos: result.data };
|
|
236
|
-
}
|
|
237
|
-
catch (err) {
|
|
238
|
-
results.providers.github = { success: false, error: err.message };
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
// Gitea
|
|
242
|
-
if (ctx.providerManager.giteaBaseUrl) {
|
|
243
|
-
try {
|
|
244
|
-
const result = await axios.get(`${ctx.providerManager.giteaBaseUrl}/api/v1/user/repos`, { headers: { Authorization: `token ${ctx.providerManager.giteaToken}` } });
|
|
245
|
-
results.providers.gitea = { success: true, repos: result.data };
|
|
246
|
-
}
|
|
247
|
-
catch (err) {
|
|
248
|
-
results.providers.gitea = { success: false, error: err.message };
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
return results;
|
|
252
|
-
}
|
|
253
|
-
case 'get': {
|
|
254
|
-
const githubOwner = params.owner || process.env.GITHUB_USERNAME;
|
|
255
|
-
const giteaOwner = params.owner || process.env.GITEA_USERNAME;
|
|
256
|
-
const repo = params.repo;
|
|
257
|
-
if (!githubOwner || !repo) {
|
|
258
|
-
throw new MCPError('VALIDATION_ERROR', 'owner and repo are required');
|
|
259
|
-
}
|
|
260
|
-
const results = { success: true, providers: {} };
|
|
261
|
-
// GitHub
|
|
262
|
-
if (ctx.providerManager.github) {
|
|
263
|
-
try {
|
|
264
|
-
const result = await ctx.providerManager.github.rest.repos.get({ owner: githubOwner, repo });
|
|
265
|
-
results.providers.github = { success: true, repo: result.data };
|
|
266
|
-
}
|
|
267
|
-
catch (err) {
|
|
268
|
-
results.providers.github = { success: false, error: err.message };
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
// Gitea
|
|
272
|
-
if (ctx.providerManager.giteaBaseUrl) {
|
|
273
|
-
try {
|
|
274
|
-
const result = await axios.get(`${ctx.providerManager.giteaBaseUrl}/api/v1/repos/${giteaOwner}/${repo}`, { headers: { Authorization: `token ${ctx.providerManager.giteaToken}` } });
|
|
275
|
-
results.providers.gitea = { success: true, repo: result.data };
|
|
276
|
-
}
|
|
277
|
-
catch (err) {
|
|
278
|
-
results.providers.gitea = { success: false, error: err.message };
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
return results;
|
|
282
|
-
}
|
|
283
|
-
case 'update': {
|
|
284
|
-
const githubOwner = params.owner || process.env.GITHUB_USERNAME;
|
|
285
|
-
const giteaOwner = params.owner || process.env.GITEA_USERNAME;
|
|
286
|
-
const repo = params.repo;
|
|
287
|
-
if (!githubOwner || !repo) {
|
|
288
|
-
throw new MCPError('VALIDATION_ERROR', 'owner and repo are required');
|
|
289
|
-
}
|
|
290
|
-
const results = { success: true, providers: {} };
|
|
291
|
-
// GitHub
|
|
292
|
-
if (ctx.providerManager.github) {
|
|
293
|
-
try {
|
|
294
|
-
const result = await ctx.providerManager.github.rest.repos.update({
|
|
295
|
-
owner: githubOwner,
|
|
296
|
-
repo,
|
|
297
|
-
description: params.description,
|
|
298
|
-
private: params.private,
|
|
299
|
-
has_issues: params.has_issues,
|
|
300
|
-
has_projects: params.has_projects,
|
|
301
|
-
has_wiki: params.has_wiki,
|
|
302
|
-
});
|
|
303
|
-
results.providers.github = { success: true, repo: result.data };
|
|
304
|
-
}
|
|
305
|
-
catch (err) {
|
|
306
|
-
results.providers.github = { success: false, error: err.message };
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
// Gitea
|
|
310
|
-
if (ctx.providerManager.giteaBaseUrl) {
|
|
311
|
-
try {
|
|
312
|
-
const result = await axios.patch(`${ctx.providerManager.giteaBaseUrl}/api/v1/repos/${giteaOwner}/${repo}`, {
|
|
313
|
-
description: params.description,
|
|
314
|
-
private: params.private,
|
|
315
|
-
has_issues: params.has_issues,
|
|
316
|
-
has_projects: params.has_projects,
|
|
317
|
-
has_wiki: params.has_wiki,
|
|
318
|
-
}, { headers: { Authorization: `token ${ctx.providerManager.giteaToken}` } });
|
|
319
|
-
results.providers.gitea = { success: true, repo: result.data };
|
|
320
|
-
}
|
|
321
|
-
catch (err) {
|
|
322
|
-
results.providers.gitea = { success: false, error: err.message };
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
return results;
|
|
326
|
-
}
|
|
327
|
-
case 'delete': {
|
|
328
|
-
const githubOwner = params.owner || process.env.GITHUB_USERNAME;
|
|
329
|
-
const giteaOwner = params.owner || process.env.GITEA_USERNAME;
|
|
330
|
-
const repo = params.repo;
|
|
331
|
-
if (!githubOwner || !repo) {
|
|
332
|
-
throw new MCPError('VALIDATION_ERROR', 'owner and repo are required');
|
|
333
|
-
}
|
|
334
|
-
// Requer confirmação para deleção
|
|
335
|
-
if (!params.confirmDestructive) {
|
|
336
|
-
throw new MCPError('SAFETY_WARNING', 'Repository deletion is destructive. Set confirmDestructive: true to proceed.', [
|
|
337
|
-
'Repository deletion is permanent and cannot be undone.',
|
|
338
|
-
'Ensure you have backups before proceeding.',
|
|
339
|
-
'Consider archiving the repository instead.',
|
|
340
|
-
]);
|
|
341
|
-
}
|
|
342
|
-
const results = { success: true, providers: {} };
|
|
343
|
-
// GitHub
|
|
344
|
-
if (ctx.providerManager.github) {
|
|
345
|
-
try {
|
|
346
|
-
await ctx.providerManager.github.rest.repos.delete({ owner: githubOwner, repo });
|
|
347
|
-
results.providers.github = { success: true, deleted: true };
|
|
348
|
-
}
|
|
349
|
-
catch (err) {
|
|
350
|
-
results.providers.github = { success: false, error: err.message };
|
|
351
|
-
}
|
|
352
|
-
}
|
|
353
|
-
// Gitea
|
|
354
|
-
if (ctx.providerManager.giteaBaseUrl) {
|
|
355
|
-
try {
|
|
356
|
-
await axios.delete(`${ctx.providerManager.giteaBaseUrl}/api/v1/repos/${giteaOwner}/${repo}`, { headers: { Authorization: `token ${ctx.providerManager.giteaToken}` } });
|
|
357
|
-
results.providers.gitea = { success: true, deleted: true };
|
|
358
|
-
}
|
|
359
|
-
catch (err) {
|
|
360
|
-
results.providers.gitea = { success: false, error: err.message };
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
return results;
|
|
364
|
-
}
|
|
365
|
-
case 'fork': {
|
|
366
|
-
const githubOwner = params.owner || process.env.GITHUB_USERNAME;
|
|
367
|
-
const giteaOwner = params.owner || process.env.GITEA_USERNAME;
|
|
368
|
-
const repo = params.repo;
|
|
369
|
-
if (!githubOwner || !repo) {
|
|
370
|
-
throw new MCPError('VALIDATION_ERROR', 'owner and repo are required');
|
|
371
|
-
}
|
|
372
|
-
const results = { success: true, providers: {} };
|
|
373
|
-
// GitHub
|
|
374
|
-
if (ctx.providerManager.github) {
|
|
375
|
-
try {
|
|
376
|
-
const result = await ctx.providerManager.github.rest.repos.createFork({
|
|
377
|
-
owner: githubOwner,
|
|
378
|
-
repo,
|
|
379
|
-
organization: params.organization,
|
|
380
|
-
});
|
|
381
|
-
results.providers.github = { success: true, fork: result.data };
|
|
382
|
-
}
|
|
383
|
-
catch (err) {
|
|
384
|
-
results.providers.github = { success: false, error: err.message };
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
// Gitea
|
|
388
|
-
if (ctx.providerManager.giteaBaseUrl) {
|
|
389
|
-
try {
|
|
390
|
-
const result = await axios.post(`${ctx.providerManager.giteaBaseUrl}/api/v1/repos/${giteaOwner}/${repo}/forks`, { organization: params.organization }, { headers: { Authorization: `token ${ctx.providerManager.giteaToken}` } });
|
|
391
|
-
results.providers.gitea = { success: true, fork: result.data };
|
|
392
|
-
}
|
|
393
|
-
catch (err) {
|
|
394
|
-
results.providers.gitea = { success: false, error: err.message };
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
return results;
|
|
398
|
-
}
|
|
399
|
-
case 'search': {
|
|
400
|
-
const query = params.query;
|
|
401
|
-
if (!query)
|
|
402
|
-
throw new MCPError('VALIDATION_ERROR', 'query is required');
|
|
403
|
-
const results = { success: true, providers: {} };
|
|
404
|
-
// GitHub
|
|
405
|
-
if (ctx.providerManager.github) {
|
|
406
|
-
try {
|
|
407
|
-
const result = await ctx.providerManager.github.rest.search.repos({
|
|
408
|
-
q: query,
|
|
409
|
-
sort: params.sort,
|
|
410
|
-
order: params.order,
|
|
411
|
-
per_page: params.limit || 30,
|
|
412
|
-
});
|
|
413
|
-
results.providers.github = { success: true, repos: result.data.items, total: result.data.total_count };
|
|
414
|
-
}
|
|
415
|
-
catch (err) {
|
|
416
|
-
results.providers.github = { success: false, error: err.message };
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
// Gitea
|
|
420
|
-
if (ctx.providerManager.giteaBaseUrl) {
|
|
421
|
-
try {
|
|
422
|
-
const result = await axios.get(`${ctx.providerManager.giteaBaseUrl}/api/v1/repos/search`, {
|
|
423
|
-
params: { q: query, limit: params.limit || 30, sort: params.sort },
|
|
424
|
-
headers: { Authorization: `token ${ctx.providerManager.giteaToken}` }
|
|
425
|
-
});
|
|
426
|
-
results.providers.gitea = { success: true, repos: result.data.data, total: result.data.ok ? result.data.data.length : 0 };
|
|
427
|
-
}
|
|
428
|
-
catch (err) {
|
|
429
|
-
results.providers.gitea = { success: false, error: err.message };
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
return results;
|
|
433
|
-
}
|
|
434
|
-
case 'push': {
|
|
435
|
-
if (!projectPath)
|
|
436
|
-
throw new MCPError('VALIDATION_ERROR', 'projectPath is required for push');
|
|
437
|
-
const remote = params.remote || 'origin';
|
|
438
|
-
let branch = params.branch;
|
|
439
|
-
const force = params.force || false;
|
|
440
|
-
const setUpstream = params.setUpstream !== undefined ? params.setUpstream : true;
|
|
441
|
-
// Segurança: verificar confirmação para operações destrutivas
|
|
442
|
-
if (force && !params.confirmDestructive) {
|
|
443
|
-
throw new MCPError('SAFETY_WARNING', 'Force push is destructive and can overwrite remote history. Set confirmDestructive: true to confirm.', [
|
|
444
|
-
'Force push will overwrite remote branch history.',
|
|
445
|
-
'This operation is dangerous and can cause data loss for collaborators.',
|
|
446
|
-
'Consider using regular push without force parameter.',
|
|
447
|
-
'If you must force push, ensure you understand the consequences.',
|
|
448
|
-
]);
|
|
449
|
-
}
|
|
450
|
-
try {
|
|
451
|
-
if (!branch) {
|
|
452
|
-
branch = await ctx.gitAdapter.getCurrentBranch(projectPath);
|
|
453
|
-
}
|
|
454
|
-
await ctx.gitAdapter.push(projectPath, remote, branch, force, setUpstream);
|
|
455
|
-
return {
|
|
456
|
-
success: true,
|
|
457
|
-
remote,
|
|
458
|
-
branch,
|
|
459
|
-
force,
|
|
460
|
-
setUpstream,
|
|
461
|
-
message: 'Push successful'
|
|
462
|
-
};
|
|
463
|
-
}
|
|
464
|
-
catch (err) {
|
|
465
|
-
throw new MCPError('PUSH_ERROR', `Failed to push: ${err.message}`);
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
default:
|
|
469
|
-
throw new MCPError('VALIDATION_ERROR', `Unsupported action: ${action}`);
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
}
|
package/dist/types.d.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { ProviderManager } from './providers/providerManager.js';
|
|
2
|
-
import { GitAdapter } from './utils/gitAdapter.js';
|
|
3
|
-
export type MCPContext = {
|
|
4
|
-
providerManager: ProviderManager;
|
|
5
|
-
gitAdapter: GitAdapter;
|
|
6
|
-
};
|
|
7
|
-
export type ToolHandleResult = any;
|
|
8
|
-
export interface Tool {
|
|
9
|
-
name: string;
|
|
10
|
-
description?: string;
|
|
11
|
-
inputSchema?: any;
|
|
12
|
-
handle(params: Record<string, any>, ctx: MCPContext): Promise<ToolHandleResult>;
|
|
13
|
-
}
|
|
14
|
-
export interface Resource {
|
|
15
|
-
uri: string;
|
|
16
|
-
name: string;
|
|
17
|
-
description: string;
|
|
18
|
-
mimeType: string;
|
|
19
|
-
content: string;
|
|
20
|
-
}
|
package/dist/types.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export declare function ensureProjectPath(params: Record<string, any>): string;
|
|
2
|
-
export declare function ensureActionAllowed(action: string | undefined, allowedActions?: string[]): string;
|
|
3
|
-
/**
|
|
4
|
-
* Convenience: validate common tool call shape.
|
|
5
|
-
* @param params tool call params
|
|
6
|
-
* @param allowedActions optional array of allowed action strings
|
|
7
|
-
*/
|
|
8
|
-
export declare function validateToolCall(params: Record<string, any>, allowedActions?: string[]): {
|
|
9
|
-
projectPath: string;
|
|
10
|
-
action: any;
|
|
11
|
-
};
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Utilities to help AI agents build/validate tool calls.
|
|
3
|
-
* Agents are responsible for detecting workspace and passing projectPath.
|
|
4
|
-
* These helpers provide lightweight validation to avoid calling tools with
|
|
5
|
-
* missing projectPath or invalid actions. Tools themselves will still
|
|
6
|
-
* validate and throw MCPError if inputs are invalid.
|
|
7
|
-
*/
|
|
8
|
-
import { MCPError } from './errors';
|
|
9
|
-
export function ensureProjectPath(params) {
|
|
10
|
-
if (!params || typeof params !== 'object') {
|
|
11
|
-
throw new Error('params must be an object');
|
|
12
|
-
}
|
|
13
|
-
const projectPath = params.projectPath;
|
|
14
|
-
if (!projectPath || typeof projectPath !== 'string' || projectPath.trim() === '') {
|
|
15
|
-
throw new MCPError('VALIDATION_ERROR', 'projectPath is required for tool invocation');
|
|
16
|
-
}
|
|
17
|
-
return projectPath;
|
|
18
|
-
}
|
|
19
|
-
export function ensureActionAllowed(action, allowedActions) {
|
|
20
|
-
if (!action || typeof action !== 'string') {
|
|
21
|
-
throw new MCPError('VALIDATION_ERROR', 'action is required');
|
|
22
|
-
}
|
|
23
|
-
if (Array.isArray(allowedActions) && allowedActions.length > 0) {
|
|
24
|
-
if (!allowedActions.includes(action)) {
|
|
25
|
-
throw new MCPError('VALIDATION_ERROR', `Unsupported action: ${action}`);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
return action;
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* Convenience: validate common tool call shape.
|
|
32
|
-
* @param params tool call params
|
|
33
|
-
* @param allowedActions optional array of allowed action strings
|
|
34
|
-
*/
|
|
35
|
-
export function validateToolCall(params, allowedActions) {
|
|
36
|
-
const projectPath = ensureProjectPath(params);
|
|
37
|
-
if (allowedActions) {
|
|
38
|
-
ensureActionAllowed(params.action, allowedActions);
|
|
39
|
-
}
|
|
40
|
-
return { projectPath, action: params.action };
|
|
41
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
interface RetryConfig {
|
|
2
|
-
maxRetries: number;
|
|
3
|
-
initialDelay: number;
|
|
4
|
-
maxDelay: number;
|
|
5
|
-
backoffFactor: number;
|
|
6
|
-
}
|
|
7
|
-
/**
|
|
8
|
-
* Retry wrapper for operations that may have eventual consistency issues.
|
|
9
|
-
* Used for GitHub API list operations after create/update.
|
|
10
|
-
*/
|
|
11
|
-
export declare function retryUntilFound<T>(operation: () => Promise<T[]>, validateFn: (items: T[]) => boolean, config?: Partial<RetryConfig>): Promise<T[]>;
|
|
12
|
-
/**
|
|
13
|
-
* Retry a single operation with exponential backoff.
|
|
14
|
-
*/
|
|
15
|
-
export declare function retryOperation<T>(operation: () => Promise<T>, shouldRetry: (error: any) => boolean, config?: Partial<RetryConfig>): Promise<T>;
|
|
16
|
-
interface ValidationRule<T> {
|
|
17
|
-
validate: (data: T) => boolean;
|
|
18
|
-
errorMessage: string;
|
|
19
|
-
}
|
|
20
|
-
export declare function validateResponse<T>(data: T, rules: ValidationRule<T>[]): void;
|
|
21
|
-
/**
|
|
22
|
-
* Validate GitHub/Gitea stats response has required fields.
|
|
23
|
-
*/
|
|
24
|
-
export declare function validateStatsResponse(response: any): any;
|
|
25
|
-
/**
|
|
26
|
-
* Validate contributors response.
|
|
27
|
-
*/
|
|
28
|
-
export declare function validateContributorsResponse(response: any): any[];
|
|
29
|
-
export {};
|