@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 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 20 Git tools
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.2.2',
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,3 @@
1
+ export declare function handleGitFix(args: any): Promise<{
2
+ content: any[];
3
+ }>;
@@ -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,8 @@
1
+ import { Tool } from '../types';
2
+ export declare class GitFixTool implements Tool {
3
+ name: string;
4
+ description: string;
5
+ handle(args: any): Promise<{
6
+ content: any[];
7
+ }>;
8
+ }
@@ -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.2.3",
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",