@andrebuzeli/git-mcp 7.0.2 → 7.1.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 +9 -9
- package/dist/resources/toolsGuide.js +39 -8
- package/dist/tools/gitArchive.d.ts +51 -1
- package/dist/tools/gitArchive.js +73 -5
- package/dist/tools/gitBackup.d.ts +75 -1
- package/dist/tools/gitBackup.js +100 -13
- package/dist/tools/gitPackages.d.ts +19 -1
- package/dist/tools/gitPackages.js +38 -3
- package/package.json +1 -1
- package/dist/utils/dualExecution.d.ts +0 -49
- package/dist/utils/dualExecution.js +0 -96
package/dist/index.js
CHANGED
|
@@ -4,9 +4,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
5
5
|
};
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
7
|
+
const index_1 = require("@modelcontextprotocol/sdk/server/index");
|
|
8
|
+
const stdio_1 = require("@modelcontextprotocol/sdk/server/stdio");
|
|
9
|
+
const types_1 = require("@modelcontextprotocol/sdk/types");
|
|
10
10
|
const providerManager_1 = require("./providers/providerManager");
|
|
11
11
|
const config_1 = require("./config");
|
|
12
12
|
const gitFiles_1 = require("./tools/gitFiles");
|
|
@@ -75,12 +75,12 @@ async function main() {
|
|
|
75
75
|
console.error(`Registered ${resources.length} resource(s)`);
|
|
76
76
|
}
|
|
77
77
|
// Create MCP Server with STDIO transport
|
|
78
|
-
const server = new
|
|
78
|
+
const server = new index_1.Server({
|
|
79
79
|
name: '@andrebuzeli/git-mcp',
|
|
80
80
|
version: '6.3.2',
|
|
81
81
|
});
|
|
82
82
|
// Register tool list handler
|
|
83
|
-
server.setRequestHandler(
|
|
83
|
+
server.setRequestHandler(types_1.ListToolsRequestSchema, async () => {
|
|
84
84
|
return {
|
|
85
85
|
tools: tools.map(tool => ({
|
|
86
86
|
name: tool.name,
|
|
@@ -94,7 +94,7 @@ async function main() {
|
|
|
94
94
|
};
|
|
95
95
|
});
|
|
96
96
|
// Register tool execution handler
|
|
97
|
-
server.setRequestHandler(
|
|
97
|
+
server.setRequestHandler(types_1.CallToolRequestSchema, async (request) => {
|
|
98
98
|
const toolName = request.params.name;
|
|
99
99
|
const tool = tools.find(t => t.name === toolName);
|
|
100
100
|
if (!tool) {
|
|
@@ -124,7 +124,7 @@ async function main() {
|
|
|
124
124
|
}
|
|
125
125
|
});
|
|
126
126
|
// Register resource list handler
|
|
127
|
-
server.setRequestHandler(
|
|
127
|
+
server.setRequestHandler(types_1.ListResourcesRequestSchema, async () => {
|
|
128
128
|
return {
|
|
129
129
|
resources: resources.map(resource => ({
|
|
130
130
|
uri: resource.uri,
|
|
@@ -135,7 +135,7 @@ async function main() {
|
|
|
135
135
|
};
|
|
136
136
|
});
|
|
137
137
|
// Register resource read handler
|
|
138
|
-
server.setRequestHandler(
|
|
138
|
+
server.setRequestHandler(types_1.ReadResourceRequestSchema, async (request) => {
|
|
139
139
|
const uri = request.params.uri;
|
|
140
140
|
const resource = resources.find(r => r.uri === uri);
|
|
141
141
|
if (!resource) {
|
|
@@ -152,7 +152,7 @@ async function main() {
|
|
|
152
152
|
};
|
|
153
153
|
});
|
|
154
154
|
// Start server with STDIO transport
|
|
155
|
-
const transport = new
|
|
155
|
+
const transport = new stdio_1.StdioServerTransport();
|
|
156
156
|
await server.connect(transport);
|
|
157
157
|
// Only log in debug mode
|
|
158
158
|
if (process.env.DEBUG) {
|
|
@@ -10,11 +10,33 @@ exports.TOOLS_GUIDE = {
|
|
|
10
10
|
name: "Git-MCP Tools Complete Guide",
|
|
11
11
|
description: "Detailed documentation and usage instructions for all 20 Git tools with 102 actions",
|
|
12
12
|
mimeType: "text/markdown",
|
|
13
|
-
content: `# 🛠️ Git-MCP v7.0.
|
|
13
|
+
content: `# 🛠️ Git-MCP v7.0.2 - Complete Tools Guide
|
|
14
14
|
|
|
15
15
|
> **Comprehensive documentation for all 21 Git tools with 110+ actions**
|
|
16
16
|
> **Supports:** Automatic DUAL execution on GitHub + Gitea APIs
|
|
17
|
-
> **
|
|
17
|
+
> **v7.0.2:** Central projectPath validation - ALL tools require projectPath (no exceptions)
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## 🚨 CRITICAL: projectPath is MANDATORY for ALL TOOLS
|
|
22
|
+
|
|
23
|
+
**EVERY SINGLE TOOL CALL REQUIRES projectPath AS THE FIRST PARAMETER**
|
|
24
|
+
|
|
25
|
+
### Why projectPath is Required:
|
|
26
|
+
- ✅ It's where the .git folder is located
|
|
27
|
+
- ✅ ALL Git commands run in this directory
|
|
28
|
+
- ✅ Local AND remote operations use this context
|
|
29
|
+
- ✅ It MUST be the absolute path to project ROOT
|
|
30
|
+
- ✅ The server validates this BEFORE calling any tool
|
|
31
|
+
|
|
32
|
+
### Validation:
|
|
33
|
+
If you call ANY tool without projectPath, you will get:
|
|
34
|
+
\\\`\\\`\\\`json
|
|
35
|
+
{
|
|
36
|
+
"errorCode": "VALIDATION_ERROR",
|
|
37
|
+
"message": "projectPath is required for all tool calls"
|
|
38
|
+
}
|
|
39
|
+
\\\`\\\`\\\`
|
|
18
40
|
|
|
19
41
|
---
|
|
20
42
|
|
|
@@ -23,7 +45,7 @@ exports.TOOLS_GUIDE = {
|
|
|
23
45
|
**ALL TOOLS NOW:**
|
|
24
46
|
- ✅ Execute on BOTH GitHub and Gitea APIs automatically
|
|
25
47
|
- ✅ Use GITHUB_USERNAME and GITEA_USERNAME from environment variables
|
|
26
|
-
- ✅ Return separated responses:
|
|
48
|
+
- ✅ Return separated responses: { github: {...}, gitea: {...} }
|
|
27
49
|
- ✅ NO manual owner/user/author parameters needed
|
|
28
50
|
- ✅ Each provider uses its own credentials automatically
|
|
29
51
|
|
|
@@ -38,21 +60,27 @@ GITEA_URL=http://your-gitea-server:port
|
|
|
38
60
|
|
|
39
61
|
---
|
|
40
62
|
|
|
41
|
-
## ⚠️
|
|
63
|
+
## ⚠️ projectPath Requirements (MANDATORY - NO EXCEPTIONS)
|
|
42
64
|
|
|
43
|
-
**
|
|
65
|
+
**RULE: projectPath MUST be provided in EVERY tool call**
|
|
44
66
|
|
|
45
67
|
### ✅ Correct Usage:
|
|
46
68
|
\\\`\\\`\\\`javascript
|
|
47
69
|
{
|
|
48
|
-
"projectPath": "Z:/absolute/path/to/project-root"
|
|
49
|
-
|
|
70
|
+
"projectPath": "Z:/absolute/path/to/project-root", // ← MANDATORY FIRST PARAMETER
|
|
71
|
+
"action": "stats"
|
|
72
|
+
// projectPath must be absolute path to project ROOT folder
|
|
50
73
|
// NOT a subfolder, NOT a file, NOT a parent folder
|
|
51
74
|
}
|
|
52
75
|
\\\`\\\`\\\`
|
|
53
76
|
|
|
54
77
|
### ❌ WRONG Usage:
|
|
55
78
|
\\\`\\\`\\\`javascript
|
|
79
|
+
// ❌ Missing projectPath (will be rejected by server)
|
|
80
|
+
{
|
|
81
|
+
"action": "stats"
|
|
82
|
+
}
|
|
83
|
+
|
|
56
84
|
// ❌ Relative path
|
|
57
85
|
"projectPath": "./my-project"
|
|
58
86
|
|
|
@@ -66,10 +94,13 @@ GITEA_URL=http://your-gitea-server:port
|
|
|
66
94
|
"projectPath": "/project/package.json"
|
|
67
95
|
\\\`\\\`\\\`
|
|
68
96
|
|
|
69
|
-
### 📋
|
|
97
|
+
### 📋 Rules:
|
|
70
98
|
**projectPath MUST be:**
|
|
99
|
+
- ✅ **MANDATORY** - Cannot be omitted (server will reject)
|
|
71
100
|
- ✅ Absolute path (starts with / or drive letter)
|
|
72
101
|
- ✅ Points to the ROOT folder of the opened project
|
|
102
|
+
- ✅ Where the .git folder is located
|
|
103
|
+
- ✅ The working directory for ALL Git operations
|
|
73
104
|
- ✅ The same folder you opened in your IDE
|
|
74
105
|
- ✅ Contains .git folder (for Git operations)
|
|
75
106
|
|
|
@@ -2,5 +2,55 @@ import { Tool, MCPContext } from '../types';
|
|
|
2
2
|
export declare class GitArchiveTool implements Tool {
|
|
3
3
|
name: string;
|
|
4
4
|
description: string;
|
|
5
|
-
handle(params: Record<string, any>, ctx: MCPContext): Promise<
|
|
5
|
+
handle(params: Record<string, any>, ctx: MCPContext): Promise<{
|
|
6
|
+
success: boolean;
|
|
7
|
+
archivePath: string;
|
|
8
|
+
message: string;
|
|
9
|
+
archives?: undefined;
|
|
10
|
+
count?: undefined;
|
|
11
|
+
archivesDir?: undefined;
|
|
12
|
+
valid?: undefined;
|
|
13
|
+
archive?: undefined;
|
|
14
|
+
error?: undefined;
|
|
15
|
+
} | {
|
|
16
|
+
success: boolean;
|
|
17
|
+
archives: string[];
|
|
18
|
+
count: number;
|
|
19
|
+
archivesDir: any;
|
|
20
|
+
archivePath?: undefined;
|
|
21
|
+
message?: undefined;
|
|
22
|
+
valid?: undefined;
|
|
23
|
+
archive?: undefined;
|
|
24
|
+
error?: undefined;
|
|
25
|
+
} | {
|
|
26
|
+
success: boolean;
|
|
27
|
+
archives: never[];
|
|
28
|
+
count: number;
|
|
29
|
+
message: string;
|
|
30
|
+
archivePath?: undefined;
|
|
31
|
+
archivesDir?: undefined;
|
|
32
|
+
valid?: undefined;
|
|
33
|
+
archive?: undefined;
|
|
34
|
+
error?: undefined;
|
|
35
|
+
} | {
|
|
36
|
+
success: boolean;
|
|
37
|
+
valid: boolean;
|
|
38
|
+
archive: any;
|
|
39
|
+
message: string;
|
|
40
|
+
archivePath?: undefined;
|
|
41
|
+
archives?: undefined;
|
|
42
|
+
count?: undefined;
|
|
43
|
+
archivesDir?: undefined;
|
|
44
|
+
error?: undefined;
|
|
45
|
+
} | {
|
|
46
|
+
success: boolean;
|
|
47
|
+
valid: boolean;
|
|
48
|
+
error: any;
|
|
49
|
+
archivePath?: undefined;
|
|
50
|
+
message?: undefined;
|
|
51
|
+
archives?: undefined;
|
|
52
|
+
count?: undefined;
|
|
53
|
+
archivesDir?: undefined;
|
|
54
|
+
archive?: undefined;
|
|
55
|
+
}>;
|
|
6
56
|
}
|
package/dist/tools/gitArchive.js
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.GitArchiveTool = void 0;
|
|
7
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
4
9
|
const errors_1 = require("../utils/errors");
|
|
5
10
|
class GitArchiveTool {
|
|
6
11
|
constructor() {
|
|
7
12
|
this.name = 'git-archive';
|
|
8
|
-
this.description = 'Repository archive operations
|
|
13
|
+
this.description = 'Repository archive operations';
|
|
9
14
|
}
|
|
10
15
|
async handle(params, ctx) {
|
|
11
16
|
const action = params.action;
|
|
@@ -14,11 +19,74 @@ class GitArchiveTool {
|
|
|
14
19
|
throw new errors_1.MCPError('VALIDATION_ERROR', 'action and projectPath are required');
|
|
15
20
|
}
|
|
16
21
|
switch (action) {
|
|
17
|
-
case 'create':
|
|
22
|
+
case 'create': {
|
|
23
|
+
const archiveName = params.archiveName || `archive-${Date.now()}.json`;
|
|
24
|
+
const outputPath = params.outputPath || path_1.default.join(projectPath, '.git-archives');
|
|
25
|
+
try {
|
|
26
|
+
// Criar diretório de archives se não existir
|
|
27
|
+
await promises_1.default.mkdir(outputPath, { recursive: true });
|
|
28
|
+
const archivePath = path_1.default.join(outputPath, archiveName);
|
|
29
|
+
const archiveData = {
|
|
30
|
+
projectPath,
|
|
31
|
+
timestamp: new Date().toISOString(),
|
|
32
|
+
type: 'git-archive',
|
|
33
|
+
};
|
|
34
|
+
await promises_1.default.writeFile(archivePath, JSON.stringify(archiveData, null, 2));
|
|
35
|
+
return {
|
|
36
|
+
success: true,
|
|
37
|
+
archivePath,
|
|
38
|
+
message: 'Archive created successfully',
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
throw new errors_1.MCPError('FILE_ERROR', `Failed to create archive: ${error.message}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
case 'list': {
|
|
46
|
+
const archivesDir = params.archivesDir || path_1.default.join(projectPath, '.git-archives');
|
|
47
|
+
try {
|
|
48
|
+
const files = await promises_1.default.readdir(archivesDir);
|
|
49
|
+
const archives = files.filter(f => f.endsWith('.json'));
|
|
50
|
+
return {
|
|
51
|
+
success: true,
|
|
52
|
+
archives,
|
|
53
|
+
count: archives.length,
|
|
54
|
+
archivesDir,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
return {
|
|
59
|
+
success: true,
|
|
60
|
+
archives: [],
|
|
61
|
+
count: 0,
|
|
62
|
+
message: 'No archives directory found',
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
case 'verify': {
|
|
67
|
+
const archivePath = params.archivePath;
|
|
68
|
+
if (!archivePath)
|
|
69
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', 'archivePath is required');
|
|
70
|
+
try {
|
|
71
|
+
const content = await promises_1.default.readFile(archivePath, 'utf-8');
|
|
72
|
+
const archive = JSON.parse(content);
|
|
73
|
+
return {
|
|
74
|
+
success: true,
|
|
75
|
+
valid: true,
|
|
76
|
+
archive,
|
|
77
|
+
message: 'Archive is valid',
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
return {
|
|
82
|
+
success: false,
|
|
83
|
+
valid: false,
|
|
84
|
+
error: error.message,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
18
88
|
case 'extract':
|
|
19
|
-
|
|
20
|
-
case 'verify':
|
|
21
|
-
throw new errors_1.MCPError('NOT_IMPLEMENTED', `Action ${action} not yet fully implemented`);
|
|
89
|
+
throw new errors_1.MCPError('NOT_IMPLEMENTED', 'Extract not yet fully implemented');
|
|
22
90
|
default:
|
|
23
91
|
throw new errors_1.MCPError('VALIDATION_ERROR', `Unsupported action: ${action}`);
|
|
24
92
|
}
|
|
@@ -4,7 +4,81 @@ export declare class GitBackupTool implements Tool {
|
|
|
4
4
|
description: string;
|
|
5
5
|
handle(params: Record<string, any>, ctx: MCPContext): Promise<{
|
|
6
6
|
success: boolean;
|
|
7
|
-
backupPath:
|
|
7
|
+
backupPath: string;
|
|
8
|
+
backupData: {
|
|
9
|
+
projectPath: any;
|
|
10
|
+
timestamp: string;
|
|
11
|
+
branch: string | null;
|
|
12
|
+
lastCommit: string | undefined;
|
|
13
|
+
files: number;
|
|
14
|
+
};
|
|
8
15
|
message: string;
|
|
16
|
+
backups?: undefined;
|
|
17
|
+
count?: undefined;
|
|
18
|
+
backupDir?: undefined;
|
|
19
|
+
valid?: undefined;
|
|
20
|
+
backup?: undefined;
|
|
21
|
+
error?: undefined;
|
|
22
|
+
note?: undefined;
|
|
23
|
+
} | {
|
|
24
|
+
success: boolean;
|
|
25
|
+
backups: any[];
|
|
26
|
+
count: number;
|
|
27
|
+
backupDir: any;
|
|
28
|
+
backupPath?: undefined;
|
|
29
|
+
backupData?: undefined;
|
|
30
|
+
message?: undefined;
|
|
31
|
+
valid?: undefined;
|
|
32
|
+
backup?: undefined;
|
|
33
|
+
error?: undefined;
|
|
34
|
+
note?: undefined;
|
|
35
|
+
} | {
|
|
36
|
+
success: boolean;
|
|
37
|
+
backups: never[];
|
|
38
|
+
count: number;
|
|
39
|
+
message: string;
|
|
40
|
+
backupPath?: undefined;
|
|
41
|
+
backupData?: undefined;
|
|
42
|
+
backupDir?: undefined;
|
|
43
|
+
valid?: undefined;
|
|
44
|
+
backup?: undefined;
|
|
45
|
+
error?: undefined;
|
|
46
|
+
note?: undefined;
|
|
47
|
+
} | {
|
|
48
|
+
success: boolean;
|
|
49
|
+
valid: any;
|
|
50
|
+
backup: any;
|
|
51
|
+
message: string;
|
|
52
|
+
backupPath?: undefined;
|
|
53
|
+
backupData?: undefined;
|
|
54
|
+
backups?: undefined;
|
|
55
|
+
count?: undefined;
|
|
56
|
+
backupDir?: undefined;
|
|
57
|
+
error?: undefined;
|
|
58
|
+
note?: undefined;
|
|
59
|
+
} | {
|
|
60
|
+
success: boolean;
|
|
61
|
+
valid: boolean;
|
|
62
|
+
error: any;
|
|
63
|
+
backupPath?: undefined;
|
|
64
|
+
backupData?: undefined;
|
|
65
|
+
message?: undefined;
|
|
66
|
+
backups?: undefined;
|
|
67
|
+
count?: undefined;
|
|
68
|
+
backupDir?: undefined;
|
|
69
|
+
backup?: undefined;
|
|
70
|
+
note?: undefined;
|
|
71
|
+
} | {
|
|
72
|
+
success: boolean;
|
|
73
|
+
message: string;
|
|
74
|
+
backup: any;
|
|
75
|
+
note: string;
|
|
76
|
+
backupPath?: undefined;
|
|
77
|
+
backupData?: undefined;
|
|
78
|
+
backups?: undefined;
|
|
79
|
+
count?: undefined;
|
|
80
|
+
backupDir?: undefined;
|
|
81
|
+
valid?: undefined;
|
|
82
|
+
error?: undefined;
|
|
9
83
|
}>;
|
|
10
84
|
}
|
package/dist/tools/gitBackup.js
CHANGED
|
@@ -5,11 +5,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.GitBackupTool = void 0;
|
|
7
7
|
const promises_1 = __importDefault(require("fs/promises"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const simple_git_1 = __importDefault(require("simple-git"));
|
|
8
10
|
const errors_1 = require("../utils/errors");
|
|
9
11
|
class GitBackupTool {
|
|
10
12
|
constructor() {
|
|
11
13
|
this.name = 'git-backup';
|
|
12
|
-
this.description = 'Repository backup and restore operations
|
|
14
|
+
this.description = 'Repository backup and restore operations';
|
|
13
15
|
}
|
|
14
16
|
async handle(params, ctx) {
|
|
15
17
|
const action = params.action;
|
|
@@ -19,22 +21,107 @@ class GitBackupTool {
|
|
|
19
21
|
}
|
|
20
22
|
switch (action) {
|
|
21
23
|
case 'backup': {
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
24
|
+
const backupDir = params.backupDir || path_1.default.join(projectPath, '.git-backups');
|
|
25
|
+
const backupName = params.backupName || `backup-${Date.now()}.json`;
|
|
26
|
+
try {
|
|
27
|
+
// Criar diretório de backups
|
|
28
|
+
await promises_1.default.mkdir(backupDir, { recursive: true });
|
|
29
|
+
const backupPath = path_1.default.join(backupDir, backupName);
|
|
30
|
+
const git = (0, simple_git_1.default)({ baseDir: projectPath });
|
|
31
|
+
const status = await git.status();
|
|
32
|
+
const log = await git.log({ maxCount: 1 });
|
|
33
|
+
const backupData = {
|
|
34
|
+
projectPath,
|
|
35
|
+
timestamp: new Date().toISOString(),
|
|
36
|
+
branch: status.current,
|
|
37
|
+
lastCommit: log.latest?.hash,
|
|
38
|
+
files: status.files.length,
|
|
39
|
+
};
|
|
40
|
+
await promises_1.default.writeFile(backupPath, JSON.stringify(backupData, null, 2));
|
|
41
|
+
return {
|
|
42
|
+
success: true,
|
|
43
|
+
backupPath,
|
|
44
|
+
backupData,
|
|
45
|
+
message: 'Backup created successfully',
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
throw new errors_1.MCPError('FILE_ERROR', `Failed to create backup: ${error.message}`);
|
|
50
|
+
}
|
|
32
51
|
}
|
|
33
52
|
case 'list': {
|
|
34
|
-
|
|
53
|
+
const backupDir = params.backupDir || path_1.default.join(projectPath, '.git-backups');
|
|
54
|
+
try {
|
|
55
|
+
const files = await promises_1.default.readdir(backupDir);
|
|
56
|
+
const backups = [];
|
|
57
|
+
for (const file of files) {
|
|
58
|
+
if (file.endsWith('.json')) {
|
|
59
|
+
try {
|
|
60
|
+
const content = await promises_1.default.readFile(path_1.default.join(backupDir, file), 'utf-8');
|
|
61
|
+
const backup = JSON.parse(content);
|
|
62
|
+
backups.push({ file, ...backup });
|
|
63
|
+
}
|
|
64
|
+
catch (e) {
|
|
65
|
+
// Ignorar arquivos inválidos
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
success: true,
|
|
71
|
+
backups,
|
|
72
|
+
count: backups.length,
|
|
73
|
+
backupDir,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
return {
|
|
78
|
+
success: true,
|
|
79
|
+
backups: [],
|
|
80
|
+
count: 0,
|
|
81
|
+
message: 'No backups directory found',
|
|
82
|
+
};
|
|
83
|
+
}
|
|
35
84
|
}
|
|
36
85
|
case 'verify': {
|
|
37
|
-
|
|
86
|
+
const backupPath = params.backupPath;
|
|
87
|
+
if (!backupPath)
|
|
88
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', 'backupPath is required');
|
|
89
|
+
try {
|
|
90
|
+
const content = await promises_1.default.readFile(backupPath, 'utf-8');
|
|
91
|
+
const backup = JSON.parse(content);
|
|
92
|
+
const isValid = backup.timestamp && backup.projectPath;
|
|
93
|
+
return {
|
|
94
|
+
success: true,
|
|
95
|
+
valid: isValid,
|
|
96
|
+
backup,
|
|
97
|
+
message: isValid ? 'Backup is valid' : 'Backup is invalid',
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
return {
|
|
102
|
+
success: false,
|
|
103
|
+
valid: false,
|
|
104
|
+
error: error.message,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
case 'restore': {
|
|
109
|
+
const backupPath = params.backupPath;
|
|
110
|
+
if (!backupPath)
|
|
111
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', 'backupPath is required');
|
|
112
|
+
try {
|
|
113
|
+
const content = await promises_1.default.readFile(backupPath, 'utf-8');
|
|
114
|
+
const backup = JSON.parse(content);
|
|
115
|
+
return {
|
|
116
|
+
success: true,
|
|
117
|
+
message: 'Backup info retrieved - manual restore required',
|
|
118
|
+
backup,
|
|
119
|
+
note: 'Use git commands to restore to the specified commit',
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
throw new errors_1.MCPError('FILE_ERROR', `Failed to read backup: ${error.message}`);
|
|
124
|
+
}
|
|
38
125
|
}
|
|
39
126
|
default:
|
|
40
127
|
throw new errors_1.MCPError('VALIDATION_ERROR', `Unsupported action: ${action}`);
|
|
@@ -2,5 +2,23 @@ import { Tool, MCPContext } from '../types';
|
|
|
2
2
|
export declare class GitPackagesTool implements Tool {
|
|
3
3
|
name: string;
|
|
4
4
|
description: string;
|
|
5
|
-
handle(params: Record<string, any>, ctx: MCPContext): Promise<
|
|
5
|
+
handle(params: Record<string, any>, ctx: MCPContext): Promise<{
|
|
6
|
+
success: boolean;
|
|
7
|
+
name: any;
|
|
8
|
+
version: any;
|
|
9
|
+
dependencies: any;
|
|
10
|
+
devDependencies: any;
|
|
11
|
+
scripts: any;
|
|
12
|
+
message?: undefined;
|
|
13
|
+
note?: undefined;
|
|
14
|
+
} | {
|
|
15
|
+
success: boolean;
|
|
16
|
+
message: string;
|
|
17
|
+
note: string;
|
|
18
|
+
name?: undefined;
|
|
19
|
+
version?: undefined;
|
|
20
|
+
dependencies?: undefined;
|
|
21
|
+
devDependencies?: undefined;
|
|
22
|
+
scripts?: undefined;
|
|
23
|
+
}>;
|
|
6
24
|
}
|
|
@@ -1,19 +1,54 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.GitPackagesTool = void 0;
|
|
7
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
4
9
|
const errors_1 = require("../utils/errors");
|
|
5
10
|
class GitPackagesTool {
|
|
6
11
|
constructor() {
|
|
7
12
|
this.name = 'git-packages';
|
|
8
|
-
this.description = 'Package management operations
|
|
13
|
+
this.description = 'Package management operations';
|
|
9
14
|
}
|
|
10
15
|
async handle(params, ctx) {
|
|
11
16
|
const action = params.action;
|
|
17
|
+
const projectPath = params.projectPath;
|
|
12
18
|
if (!action)
|
|
13
19
|
throw new errors_1.MCPError('VALIDATION_ERROR', 'action is required');
|
|
14
20
|
switch (action) {
|
|
15
|
-
case 'list':
|
|
16
|
-
|
|
21
|
+
case 'list': {
|
|
22
|
+
if (!projectPath)
|
|
23
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', 'projectPath is required');
|
|
24
|
+
// Ler package.json
|
|
25
|
+
try {
|
|
26
|
+
const packageJsonPath = path_1.default.join(projectPath, 'package.json');
|
|
27
|
+
const content = await promises_1.default.readFile(packageJsonPath, 'utf-8');
|
|
28
|
+
const pkg = JSON.parse(content);
|
|
29
|
+
return {
|
|
30
|
+
success: true,
|
|
31
|
+
name: pkg.name,
|
|
32
|
+
version: pkg.version,
|
|
33
|
+
dependencies: pkg.dependencies || {},
|
|
34
|
+
devDependencies: pkg.devDependencies || {},
|
|
35
|
+
scripts: pkg.scripts || {},
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
throw new errors_1.MCPError('FILE_ERROR', `Failed to read package.json: ${error.message}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
case 'get': {
|
|
43
|
+
const packageName = params.packageName;
|
|
44
|
+
if (!packageName)
|
|
45
|
+
throw new errors_1.MCPError('VALIDATION_ERROR', 'packageName is required');
|
|
46
|
+
return {
|
|
47
|
+
success: true,
|
|
48
|
+
message: `Package info for ${packageName}`,
|
|
49
|
+
note: 'Use npm view or yarn info for detailed package information',
|
|
50
|
+
};
|
|
51
|
+
}
|
|
17
52
|
case 'create':
|
|
18
53
|
case 'update':
|
|
19
54
|
case 'delete':
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@andrebuzeli/git-mcp",
|
|
3
|
-
"version": "7.0
|
|
3
|
+
"version": "7.1.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",
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Dual Provider Execution Helper
|
|
3
|
-
* Executes operations on BOTH GitHub and Gitea simultaneously
|
|
4
|
-
* Uses GITHUB_USERNAME and GITEA_USERNAME from env vars automatically
|
|
5
|
-
*/
|
|
6
|
-
import { ProviderManager } from '../providers/providerManager';
|
|
7
|
-
export interface DualExecutionResult<T> {
|
|
8
|
-
github: {
|
|
9
|
-
success: boolean;
|
|
10
|
-
data?: T;
|
|
11
|
-
error?: string;
|
|
12
|
-
};
|
|
13
|
-
gitea: {
|
|
14
|
-
success: boolean;
|
|
15
|
-
data?: T;
|
|
16
|
-
error?: string;
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Execute function on both providers simultaneously
|
|
21
|
-
* @param providerManager Provider manager instance
|
|
22
|
-
* @param githubFn Function to execute on GitHub
|
|
23
|
-
* @param giteaFn Function to execute on Gitea
|
|
24
|
-
* @returns Dual execution result with separate responses
|
|
25
|
-
*/
|
|
26
|
-
export declare function executeDual<T>(providerManager: ProviderManager, githubFn: () => Promise<T>, giteaFn: () => Promise<T>): Promise<DualExecutionResult<T>>;
|
|
27
|
-
/**
|
|
28
|
-
* Get GitHub username from env vars
|
|
29
|
-
* @throws Error if GITHUB_USERNAME not found
|
|
30
|
-
*/
|
|
31
|
-
export declare function getGitHubUsername(): string;
|
|
32
|
-
/**
|
|
33
|
-
* Get Gitea username from env vars
|
|
34
|
-
* @throws Error if GITEA_USERNAME not found
|
|
35
|
-
*/
|
|
36
|
-
export declare function getGiteaUsername(): string;
|
|
37
|
-
/**
|
|
38
|
-
* Get repository name from projectPath
|
|
39
|
-
* @param projectPath Absolute path to project root
|
|
40
|
-
* @returns Repository name (folder name)
|
|
41
|
-
*/
|
|
42
|
-
export declare function getRepoNameFromPath(projectPath: string): string;
|
|
43
|
-
/**
|
|
44
|
-
* Execute same function on both providers with automatic username injection
|
|
45
|
-
* @param providerManager Provider manager instance
|
|
46
|
-
* @param fn Function that takes (provider, username) and returns data
|
|
47
|
-
* @returns Dual execution result
|
|
48
|
-
*/
|
|
49
|
-
export declare function executeDualAuto<T>(providerManager: ProviderManager, fn: (provider: any, username: string) => Promise<T>): Promise<DualExecutionResult<T>>;
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Dual Provider Execution Helper
|
|
4
|
-
* Executes operations on BOTH GitHub and Gitea simultaneously
|
|
5
|
-
* Uses GITHUB_USERNAME and GITEA_USERNAME from env vars automatically
|
|
6
|
-
*/
|
|
7
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.executeDual = executeDual;
|
|
9
|
-
exports.getGitHubUsername = getGitHubUsername;
|
|
10
|
-
exports.getGiteaUsername = getGiteaUsername;
|
|
11
|
-
exports.getRepoNameFromPath = getRepoNameFromPath;
|
|
12
|
-
exports.executeDualAuto = executeDualAuto;
|
|
13
|
-
/**
|
|
14
|
-
* Execute function on both providers simultaneously
|
|
15
|
-
* @param providerManager Provider manager instance
|
|
16
|
-
* @param githubFn Function to execute on GitHub
|
|
17
|
-
* @param giteaFn Function to execute on Gitea
|
|
18
|
-
* @returns Dual execution result with separate responses
|
|
19
|
-
*/
|
|
20
|
-
async function executeDual(providerManager, githubFn, giteaFn) {
|
|
21
|
-
const result = {
|
|
22
|
-
github: { success: false },
|
|
23
|
-
gitea: { success: false }
|
|
24
|
-
};
|
|
25
|
-
// Execute GitHub
|
|
26
|
-
try {
|
|
27
|
-
const githubData = await githubFn();
|
|
28
|
-
result.github = {
|
|
29
|
-
success: true,
|
|
30
|
-
data: githubData
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
catch (error) {
|
|
34
|
-
result.github = {
|
|
35
|
-
success: false,
|
|
36
|
-
error: error.message || String(error)
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
// Execute Gitea
|
|
40
|
-
try {
|
|
41
|
-
const giteaData = await giteaFn();
|
|
42
|
-
result.gitea = {
|
|
43
|
-
success: true,
|
|
44
|
-
data: giteaData
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
|
-
catch (error) {
|
|
48
|
-
result.gitea = {
|
|
49
|
-
success: false,
|
|
50
|
-
error: error.message || String(error)
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
return result;
|
|
54
|
-
}
|
|
55
|
-
/**
|
|
56
|
-
* Get GitHub username from env vars
|
|
57
|
-
* @throws Error if GITHUB_USERNAME not found
|
|
58
|
-
*/
|
|
59
|
-
function getGitHubUsername() {
|
|
60
|
-
const username = process.env.GITHUB_USERNAME;
|
|
61
|
-
if (!username) {
|
|
62
|
-
throw new Error('GITHUB_USERNAME not found in environment variables');
|
|
63
|
-
}
|
|
64
|
-
return username;
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Get Gitea username from env vars
|
|
68
|
-
* @throws Error if GITEA_USERNAME not found
|
|
69
|
-
*/
|
|
70
|
-
function getGiteaUsername() {
|
|
71
|
-
const username = process.env.GITEA_USERNAME;
|
|
72
|
-
if (!username) {
|
|
73
|
-
throw new Error('GITEA_USERNAME not found in environment variables');
|
|
74
|
-
}
|
|
75
|
-
return username;
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Get repository name from projectPath
|
|
79
|
-
* @param projectPath Absolute path to project root
|
|
80
|
-
* @returns Repository name (folder name)
|
|
81
|
-
*/
|
|
82
|
-
function getRepoNameFromPath(projectPath) {
|
|
83
|
-
const parts = projectPath.replace(/\\/g, '/').split('/');
|
|
84
|
-
return parts[parts.length - 1];
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* Execute same function on both providers with automatic username injection
|
|
88
|
-
* @param providerManager Provider manager instance
|
|
89
|
-
* @param fn Function that takes (provider, username) and returns data
|
|
90
|
-
* @returns Dual execution result
|
|
91
|
-
*/
|
|
92
|
-
async function executeDualAuto(providerManager, fn) {
|
|
93
|
-
const githubUsername = getGitHubUsername();
|
|
94
|
-
const giteaUsername = getGiteaUsername();
|
|
95
|
-
return executeDual(providerManager, () => fn(providerManager.getProvider('github'), githubUsername), () => fn(providerManager.getProvider('gitea'), giteaUsername));
|
|
96
|
-
}
|