@andrebuzeli/git-mcp 6.2.3 → 6.3.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/gitFix.d.ts +3 -0
- package/dist/tools/gitFix.js +154 -0
- package/dist/tools/gitFix.tool.d.ts +8 -0
- package/dist/tools/gitFix.tool.js +73 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -29,6 +29,7 @@ const gitAnalytics_1 = require("./tools/gitAnalytics");
|
|
|
29
29
|
const gitUpload_1 = require("./tools/gitUpload");
|
|
30
30
|
const gitUpdate_1 = require("./tools/gitUpdate");
|
|
31
31
|
const gitHistory_1 = require("./tools/gitHistory");
|
|
32
|
+
const gitFix_tool_1 = require("./tools/gitFix.tool");
|
|
32
33
|
const toolsGuide_1 = __importDefault(require("./resources/toolsGuide"));
|
|
33
34
|
async function main() {
|
|
34
35
|
// Load optional mcp.json configuration (will populate process.env if values present)
|
|
@@ -40,7 +41,7 @@ async function main() {
|
|
|
40
41
|
if (process.env.DEBUG) {
|
|
41
42
|
console.error('Provider validation:', JSON.stringify(validation, null, 2));
|
|
42
43
|
}
|
|
43
|
-
// Register all
|
|
44
|
+
// Register all 21 Git tools
|
|
44
45
|
const tools = [
|
|
45
46
|
new gitWorkflow_1.GitWorkflowTool(),
|
|
46
47
|
new gitFiles_1.GitFilesTool(),
|
|
@@ -62,6 +63,7 @@ async function main() {
|
|
|
62
63
|
new gitUpload_1.GitUploadTool(),
|
|
63
64
|
new gitUpdate_1.GitUpdateTool(),
|
|
64
65
|
new gitHistory_1.GitHistoryTool(),
|
|
66
|
+
new gitFix_tool_1.GitFixTool(),
|
|
65
67
|
];
|
|
66
68
|
// Register resources
|
|
67
69
|
const resources = [
|
|
@@ -75,7 +77,7 @@ async function main() {
|
|
|
75
77
|
// Create MCP Server with STDIO transport
|
|
76
78
|
const server = new index_js_1.Server({
|
|
77
79
|
name: '@andrebuzeli/git-mcp',
|
|
78
|
-
version: '6.
|
|
80
|
+
version: '6.3.0',
|
|
79
81
|
});
|
|
80
82
|
// Register tool list handler
|
|
81
83
|
server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.handleGitFix = handleGitFix;
|
|
7
|
+
const simple_git_1 = __importDefault(require("simple-git"));
|
|
8
|
+
const path_1 = __importDefault(require("path"));
|
|
9
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
10
|
+
const fs_1 = require("fs");
|
|
11
|
+
async function handleGitFix(args) {
|
|
12
|
+
try {
|
|
13
|
+
const { projectPath, githubRepo, giteaRepo, autoDetect = true } = args;
|
|
14
|
+
if (!projectPath) {
|
|
15
|
+
throw new Error('projectPath é obrigatório');
|
|
16
|
+
}
|
|
17
|
+
const absolutePath = path_1.default.resolve(projectPath);
|
|
18
|
+
if (!(0, fs_1.existsSync)(absolutePath)) {
|
|
19
|
+
throw new Error(`Caminho não existe: ${absolutePath}`);
|
|
20
|
+
}
|
|
21
|
+
const git = (0, simple_git_1.default)(absolutePath);
|
|
22
|
+
const result = {
|
|
23
|
+
success: false,
|
|
24
|
+
projectPath: absolutePath,
|
|
25
|
+
fixed: [],
|
|
26
|
+
warnings: [],
|
|
27
|
+
errors: [],
|
|
28
|
+
remotes: {
|
|
29
|
+
before: [],
|
|
30
|
+
after: []
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
// Verificar se é um repositório Git
|
|
34
|
+
let isGitRepo = false;
|
|
35
|
+
try {
|
|
36
|
+
await git.status();
|
|
37
|
+
isGitRepo = true;
|
|
38
|
+
result.fixed.push('✅ Repositório Git válido encontrado');
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
if (err.message.includes('not a git repository')) {
|
|
42
|
+
result.warnings.push('⚠️ Não é um repositório Git - inicializando...');
|
|
43
|
+
await git.init();
|
|
44
|
+
result.fixed.push('✅ Git inicializado');
|
|
45
|
+
isGitRepo = true;
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
throw err;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// Capturar remotes antes
|
|
52
|
+
const remotesBefore = await git.getRemotes(true);
|
|
53
|
+
result.remotes.before = remotesBefore.map(r => ({ name: r.name, url: r.refs.fetch || '' }));
|
|
54
|
+
// Auto-detectar repos se solicitado
|
|
55
|
+
let finalGithubRepo = githubRepo;
|
|
56
|
+
let finalGiteaRepo = giteaRepo;
|
|
57
|
+
if (autoDetect && remotesBefore.length > 0) {
|
|
58
|
+
for (const remote of remotesBefore) {
|
|
59
|
+
const url = remote.refs.fetch || '';
|
|
60
|
+
if (url.includes('github.com') && !finalGithubRepo) {
|
|
61
|
+
const match = url.match(/github\.com[:/]([^/]+)\/([^/.]+)/);
|
|
62
|
+
if (match) {
|
|
63
|
+
finalGithubRepo = `${match[1]}/${match[2]}`;
|
|
64
|
+
result.fixed.push(`🔍 GitHub repo auto-detectado: ${finalGithubRepo}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
if ((url.includes('nas-ubuntu') || url.includes('gitea')) && !finalGiteaRepo) {
|
|
68
|
+
const match = url.match(/\/([^/]+)\/([^/.]+)(?:\.git)?$/);
|
|
69
|
+
if (match) {
|
|
70
|
+
finalGiteaRepo = `${match[1]}/${match[2]}`;
|
|
71
|
+
result.fixed.push(`🔍 Gitea repo auto-detectado: ${finalGiteaRepo}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// Obter username dos remotes existentes ou env vars
|
|
77
|
+
const githubUsername = process.env.GITHUB_USERNAME || 'andrebuzeli';
|
|
78
|
+
const giteaUsername = process.env.GITEA_USERNAME || 'andrebuzeli';
|
|
79
|
+
// Se não detectou repos, usar o nome da pasta
|
|
80
|
+
if (!finalGithubRepo) {
|
|
81
|
+
const folderName = path_1.default.basename(absolutePath);
|
|
82
|
+
finalGithubRepo = `${githubUsername}/${folderName}`;
|
|
83
|
+
result.warnings.push(`⚠️ GitHub repo não detectado - usando: ${finalGithubRepo}`);
|
|
84
|
+
}
|
|
85
|
+
if (!finalGiteaRepo) {
|
|
86
|
+
const folderName = path_1.default.basename(absolutePath);
|
|
87
|
+
finalGiteaRepo = `${giteaUsername}/${folderName}`;
|
|
88
|
+
result.warnings.push(`⚠️ Gitea repo não detectado - usando: ${finalGiteaRepo}`);
|
|
89
|
+
}
|
|
90
|
+
// Remover remotes antigos
|
|
91
|
+
const remotesToRemove = ['origin', 'github', 'gitea'];
|
|
92
|
+
for (const remoteName of remotesToRemove) {
|
|
93
|
+
const exists = remotesBefore.find(r => r.name === remoteName);
|
|
94
|
+
if (exists) {
|
|
95
|
+
await git.removeRemote(remoteName);
|
|
96
|
+
result.fixed.push(`🗑️ Removido remote antigo: ${remoteName}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// Adicionar novos remotes no padrão dual
|
|
100
|
+
const giteaUrl = process.env.GITEA_URL || 'http://nas-ubuntu:9999';
|
|
101
|
+
const githubUrl = `https://github.com/${finalGithubRepo}.git`;
|
|
102
|
+
const giteaRepoUrl = `${giteaUrl}/${finalGiteaRepo}.git`;
|
|
103
|
+
await git.addRemote('github', githubUrl);
|
|
104
|
+
result.fixed.push(`✅ Adicionado remote GitHub: ${githubUrl}`);
|
|
105
|
+
await git.addRemote('gitea', giteaRepoUrl);
|
|
106
|
+
result.fixed.push(`✅ Adicionado remote Gitea: ${giteaRepoUrl}`);
|
|
107
|
+
// Configurar origin como push múltiplo
|
|
108
|
+
await git.addRemote('origin', githubUrl);
|
|
109
|
+
await git.addConfig('remote.origin.pushurl', giteaRepoUrl, false, 'local');
|
|
110
|
+
result.fixed.push(`✅ Configurado origin para push dual (GitHub + Gitea)`);
|
|
111
|
+
// Capturar remotes depois
|
|
112
|
+
const remotesAfter = await git.getRemotes(true);
|
|
113
|
+
result.remotes.after = remotesAfter.map(r => ({ name: r.name, url: r.refs.fetch || '' }));
|
|
114
|
+
// Verificar se há commits
|
|
115
|
+
try {
|
|
116
|
+
await git.log();
|
|
117
|
+
result.fixed.push('✅ Histórico de commits preservado');
|
|
118
|
+
}
|
|
119
|
+
catch (err) {
|
|
120
|
+
result.warnings.push('⚠️ Sem commits ainda - faça o primeiro commit');
|
|
121
|
+
}
|
|
122
|
+
// Criar/atualizar .gitignore se necessário
|
|
123
|
+
const gitignorePath = path_1.default.join(absolutePath, '.gitignore');
|
|
124
|
+
if (!(0, fs_1.existsSync)(gitignorePath)) {
|
|
125
|
+
const defaultGitignore = `node_modules/
|
|
126
|
+
dist/
|
|
127
|
+
.env
|
|
128
|
+
*.log
|
|
129
|
+
.DS_Store
|
|
130
|
+
`;
|
|
131
|
+
await promises_1.default.writeFile(gitignorePath, defaultGitignore, 'utf-8');
|
|
132
|
+
result.fixed.push('✅ Criado .gitignore padrão');
|
|
133
|
+
}
|
|
134
|
+
result.success = true;
|
|
135
|
+
return {
|
|
136
|
+
content: [{
|
|
137
|
+
type: 'text',
|
|
138
|
+
text: JSON.stringify(result, null, 2)
|
|
139
|
+
}]
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
return {
|
|
144
|
+
content: [{
|
|
145
|
+
type: 'text',
|
|
146
|
+
text: JSON.stringify({
|
|
147
|
+
success: false,
|
|
148
|
+
error: error.message,
|
|
149
|
+
stack: error.stack
|
|
150
|
+
}, null, 2)
|
|
151
|
+
}]
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GitFixTool = void 0;
|
|
4
|
+
const gitFix_1 = require("./gitFix");
|
|
5
|
+
class GitFixTool {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.name = 'git-fix';
|
|
8
|
+
this.description = `Fix local Git repository to work with dual-provider system (GitHub + Gitea).
|
|
9
|
+
|
|
10
|
+
🔧 WHAT IT DOES:
|
|
11
|
+
- Converts existing Git repos to dual-provider system
|
|
12
|
+
- Auto-detects GitHub/Gitea remotes from existing configuration
|
|
13
|
+
- Removes old remotes and configures new dual-push system
|
|
14
|
+
- Initializes Git if not already a repository
|
|
15
|
+
- Creates standard .gitignore if missing
|
|
16
|
+
|
|
17
|
+
📋 PARAMETERS:
|
|
18
|
+
- projectPath (required): Absolute path to the Git repository
|
|
19
|
+
- githubRepo (optional): GitHub repo in format "owner/repo" (auto-detected if not provided)
|
|
20
|
+
- giteaRepo (optional): Gitea repo in format "owner/repo" (auto-detected if not provided)
|
|
21
|
+
- autoDetect (optional): Auto-detect repos from existing remotes (default: true)
|
|
22
|
+
|
|
23
|
+
🎯 WHEN TO USE:
|
|
24
|
+
- You have an existing Git repo not configured for dual-provider
|
|
25
|
+
- Need to migrate from single remote to dual-push system
|
|
26
|
+
- Want to standardize repo configuration for git-mcp tools
|
|
27
|
+
|
|
28
|
+
✅ WHAT GETS FIXED:
|
|
29
|
+
1. Verifies/initializes Git repository
|
|
30
|
+
2. Captures current remotes (before)
|
|
31
|
+
3. Auto-detects GitHub/Gitea repos from URLs
|
|
32
|
+
4. Removes old remotes (origin, github, gitea)
|
|
33
|
+
5. Adds new 'github' remote
|
|
34
|
+
6. Adds new 'gitea' remote
|
|
35
|
+
7. Configures 'origin' for dual-push (GitHub + Gitea)
|
|
36
|
+
8. Creates .gitignore if missing
|
|
37
|
+
9. Shows before/after comparison
|
|
38
|
+
|
|
39
|
+
📊 RESULT STRUCTURE:
|
|
40
|
+
{
|
|
41
|
+
success: boolean,
|
|
42
|
+
projectPath: string,
|
|
43
|
+
fixed: string[], // Actions performed
|
|
44
|
+
warnings: string[], // Non-critical issues
|
|
45
|
+
errors: string[], // Critical issues
|
|
46
|
+
remotes: {
|
|
47
|
+
before: [...], // Remotes before fix
|
|
48
|
+
after: [...] // Remotes after fix
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
💡 EXAMPLE:
|
|
53
|
+
{
|
|
54
|
+
"projectPath": "/path/to/my-project",
|
|
55
|
+
"autoDetect": true
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
🔍 AUTO-DETECTION:
|
|
59
|
+
- Scans existing remotes for github.com URLs → extracts owner/repo
|
|
60
|
+
- Scans existing remotes for Gitea URLs → extracts owner/repo
|
|
61
|
+
- Falls back to folder name if no remotes found
|
|
62
|
+
|
|
63
|
+
⚠️ REQUIREMENTS:
|
|
64
|
+
- GITHUB_USERNAME and GITEA_USERNAME env vars for fallback
|
|
65
|
+
- GITEA_URL env var (default: http://nas-ubuntu:9999)
|
|
66
|
+
- Git must be installed and accessible
|
|
67
|
+
`;
|
|
68
|
+
}
|
|
69
|
+
async handle(args) {
|
|
70
|
+
return (0, gitFix_1.handleGitFix)(args);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
exports.GitFixTool = GitFixTool;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@andrebuzeli/git-mcp",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.3.0",
|
|
4
4
|
"description": "Professional MCP server for Git operations - STDIO UNIVERSAL: works in ANY IDE (Cursor, VSCode, Claude Desktop). Fully autonomous with intelligent error handling. Auto-detects branches, owner, repo. User-friendly error messages. Dual-provider execution (GitHub + Gitea)",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|