@andrebuzeli/git-mcp 13.7.0 → 14.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.
@@ -7,15 +7,47 @@ export function createGitSyncTool(git) {
7
7
  const inputSchema = {
8
8
  type: "object",
9
9
  properties: {
10
- projectPath: { type: "string" },
11
- action: { type: "string", enum: ["pull", "fetch"] },
12
- remote: { type: "string" },
13
- branch: { type: "string" }
10
+ projectPath: {
11
+ type: "string",
12
+ description: "Caminho absoluto do diretório do projeto"
13
+ },
14
+ action: {
15
+ type: "string",
16
+ enum: ["pull", "fetch"],
17
+ description: `Ação a executar:
18
+ - fetch: Baixa commits do remote sem aplicar (seguro, apenas atualiza refs remotas)
19
+ - pull: Baixa E aplica commits do remote (pode gerar conflitos)`
20
+ },
21
+ remote: {
22
+ type: "string",
23
+ description: "Nome do remote específico (github, gitea, origin). Se não especificado, tenta todos"
24
+ },
25
+ branch: {
26
+ type: "string",
27
+ description: "Branch para sincronizar. Default: branch atual"
28
+ }
14
29
  },
15
30
  required: ["projectPath", "action"],
16
- additionalProperties: true
31
+ additionalProperties: false
17
32
  };
18
33
 
34
+ const description = `Sincronização com repositórios remotos (GitHub/Gitea).
35
+
36
+ DIFERENÇA FETCH vs PULL:
37
+ - fetch: Seguro - apenas baixa, não modifica working directory
38
+ - pull: Baixa E aplica - pode gerar conflitos se houver mudanças locais
39
+
40
+ QUANDO USAR:
41
+ - fetch: Para ver se há atualizações sem aplicar
42
+ - pull: Para atualizar seu código local com as mudanças do remote
43
+
44
+ FLUXO RECOMENDADO:
45
+ 1. git-workflow status → verificar se tem mudanças locais
46
+ 2. git-sync fetch → baixar atualizações
47
+ 3. git-sync pull → aplicar atualizações (se não tiver conflitos)
48
+
49
+ NOTA: Se pull falhar com conflito, resolva manualmente e faça commit.`;
50
+
19
51
  async function handle(args) {
20
52
  const validate = ajv.compile(inputSchema);
21
53
  if (!validate(args || {})) return asToolError("VALIDATION_ERROR", "Parâmetros inválidos", validate.errors);
@@ -33,7 +65,7 @@ export function createGitSyncTool(git) {
33
65
  branch,
34
66
  fetched: successful.map(x => x.remote),
35
67
  failed: failed.map(x => ({ remote: x.remote, error: x.error })),
36
- message: successful.length === 0 ? "Nenhum remote alcançado. Verifique conexão e configuração." : undefined
68
+ message: successful.length === 0 ? "Nenhum remote alcançado. Use git-remote ensure para configurar." : `Fetch de ${successful.length} remote(s) concluído`
37
69
  });
38
70
  }
39
71
  if (action === "pull") {
@@ -47,14 +79,14 @@ export function createGitSyncTool(git) {
47
79
  branch,
48
80
  pulled: successful.map(x => x.remote),
49
81
  failed: failed.map(x => ({ remote: x.remote, error: x.error })),
50
- message: successful.length === 0 ? "Nenhum remote alcançado. Verifique conexão e configuração." : undefined
82
+ message: successful.length === 0 ? "Nenhum remote alcançado. Use git-remote ensure para configurar." : `Pull de ${successful.length} remote(s) concluído`
51
83
  });
52
84
  }
53
- return asToolError("VALIDATION_ERROR", `Ação não suportada: ${action}`, { availableActions: ["pull", "fetch"] });
85
+ return asToolError("VALIDATION_ERROR", `Ação '${action}' não suportada`, { availableActions: ["pull", "fetch"] });
54
86
  } catch (e) {
55
87
  return errorToResponse(e);
56
88
  }
57
89
  }
58
90
 
59
- return { name: "git-sync", description: "fetch/pull (opcionalmente múltiplos remotes)", inputSchema, handle };
91
+ return { name: "git-sync", description, inputSchema, handle };
60
92
  }
@@ -7,16 +7,54 @@ export function createGitTagsTool(git) {
7
7
  const inputSchema = {
8
8
  type: "object",
9
9
  properties: {
10
- projectPath: { type: "string" },
11
- action: { type: "string", enum: ["list", "create", "delete", "push"] },
12
- tag: { type: "string" },
13
- ref: { type: "string" },
14
- message: { type: "string" }
10
+ projectPath: {
11
+ type: "string",
12
+ description: "Caminho absoluto do diretório do projeto"
13
+ },
14
+ action: {
15
+ type: "string",
16
+ enum: ["list", "create", "delete", "push"],
17
+ description: `Ação a executar:
18
+ - list: Lista todas as tags existentes
19
+ - create: Cria nova tag no commit atual ou especificado
20
+ - delete: Remove uma tag local
21
+ - push: Envia tag para GitHub e Gitea`
22
+ },
23
+ tag: {
24
+ type: "string",
25
+ description: "Nome da tag. Use versionamento semântico: v1.0.0, v1.1.0, v2.0.0"
26
+ },
27
+ ref: {
28
+ type: "string",
29
+ description: "Commit/branch para criar tag (opcional, default: HEAD)"
30
+ },
31
+ message: {
32
+ type: "string",
33
+ description: "Mensagem da tag anotada (opcional). Se fornecido, cria tag anotada"
34
+ }
15
35
  },
16
36
  required: ["projectPath", "action"],
17
- additionalProperties: true
37
+ additionalProperties: false
18
38
  };
19
39
 
40
+ const description = `Gerenciamento de tags Git para versionamento.
41
+
42
+ AÇÕES DISPONÍVEIS:
43
+ - list: Ver todas as tags existentes
44
+ - create: Criar nova tag de versão
45
+ - delete: Remover tag local
46
+ - push: Enviar tag para GitHub e Gitea
47
+
48
+ VERSIONAMENTO SEMÂNTICO:
49
+ - v1.0.0: Versão inicial
50
+ - v1.1.0: Nova funcionalidade (minor)
51
+ - v1.0.1: Correção de bug (patch)
52
+ - v2.0.0: Breaking change (major)
53
+
54
+ FLUXO TÍPICO:
55
+ 1. git-tags create tag='v1.0.0' message='Release inicial'
56
+ 2. git-tags push tag='v1.0.0'`;
57
+
20
58
  async function handle(args) {
21
59
  const validate = ajv.compile(inputSchema);
22
60
  if (!validate(args || {})) return asToolError("VALIDATION_ERROR", "Parâmetros inválidos", validate.errors);
@@ -27,38 +65,32 @@ export function createGitTagsTool(git) {
27
65
  return asToolResult({ tags, count: tags.length });
28
66
  }
29
67
  if (action === "create") {
30
- const tag = args.tag;
31
- if (!tag) return asToolError("MISSING_PARAMETER", "tag é obrigatório", { parameter: "tag" });
32
- // Auto-verificação: checar se já existe
68
+ if (!args.tag) return asToolError("MISSING_PARAMETER", "tag é obrigatório", { parameter: "tag" });
33
69
  const existing = await git.listTags(projectPath);
34
- if (existing.includes(tag)) {
35
- return asToolError("TAG_ALREADY_EXISTS", `Tag '${tag}' já existe`, { tag, existingTags: existing });
70
+ if (existing.includes(args.tag)) {
71
+ return asToolError("TAG_ALREADY_EXISTS", `Tag '${args.tag}' já existe`, { tag: args.tag, existingTags: existing });
36
72
  }
37
- await git.createTag(projectPath, tag, args.ref || "HEAD", args.message);
38
- return asToolResult({ success: true, tag, ref: args.ref || "HEAD" });
73
+ await git.createTag(projectPath, args.tag, args.ref || "HEAD", args.message);
74
+ return asToolResult({ success: true, tag: args.tag, ref: args.ref || "HEAD", message: `Tag '${args.tag}' criada. Use action='push' para enviar ao GitHub/Gitea.` });
39
75
  }
40
76
  if (action === "delete") {
41
- const tag = args.tag;
42
- if (!tag) return asToolError("MISSING_PARAMETER", "tag é obrigatório", { parameter: "tag" });
43
- // Auto-verificação: checar se existe
77
+ if (!args.tag) return asToolError("MISSING_PARAMETER", "tag é obrigatório", { parameter: "tag" });
44
78
  const existing = await git.listTags(projectPath);
45
- if (!existing.includes(tag)) {
46
- return asToolError("TAG_NOT_FOUND", `Tag '${tag}' não encontrada`, { tag, existingTags: existing });
79
+ if (!existing.includes(args.tag)) {
80
+ return asToolError("TAG_NOT_FOUND", `Tag '${args.tag}' não encontrada`, { tag: args.tag, existingTags: existing });
47
81
  }
48
- await git.deleteTag(projectPath, tag);
49
- return asToolResult({ success: true, tag });
82
+ await git.deleteTag(projectPath, args.tag);
83
+ return asToolResult({ success: true, tag: args.tag, deleted: true });
50
84
  }
51
85
  if (action === "push") {
52
- const tag = args.tag;
53
- if (!tag) return asToolError("MISSING_PARAMETER", "tag é obrigatório", { parameter: "tag" });
54
- // Auto-verificação: checar se existe
86
+ if (!args.tag) return asToolError("MISSING_PARAMETER", "tag é obrigatório", { parameter: "tag" });
55
87
  const existing = await git.listTags(projectPath);
56
- if (!existing.includes(tag)) {
57
- return asToolError("TAG_NOT_FOUND", `Tag '${tag}' não existe localmente. Crie primeiro com action='create'`, { tag, existingTags: existing });
88
+ if (!existing.includes(args.tag)) {
89
+ return asToolError("TAG_NOT_FOUND", `Tag '${args.tag}' não existe localmente. Crie primeiro com action='create'`, { tag: args.tag, existingTags: existing });
58
90
  }
59
91
  const results = await Promise.allSettled([
60
- git.pushTag(projectPath, "github", tag),
61
- git.pushTag(projectPath, "gitea", tag)
92
+ git.pushTag(projectPath, "github", args.tag),
93
+ git.pushTag(projectPath, "gitea", args.tag)
62
94
  ]);
63
95
  const pushed = [];
64
96
  const failed = [];
@@ -67,13 +99,13 @@ export function createGitTagsTool(git) {
67
99
  if (results[1].status === "fulfilled") pushed.push("gitea");
68
100
  else failed.push({ remote: "gitea", error: results[1].reason?.message });
69
101
 
70
- return asToolResult({ success: pushed.length > 0, tag, pushed, failed });
102
+ return asToolResult({ success: pushed.length > 0, tag: args.tag, pushed, failed });
71
103
  }
72
- return asToolError("VALIDATION_ERROR", `Ação não suportada: ${action}`, { availableActions: ["list", "create", "delete", "push"] });
104
+ return asToolError("VALIDATION_ERROR", `Ação '${action}' não suportada`, { availableActions: ["list", "create", "delete", "push"] });
73
105
  } catch (e) {
74
106
  return errorToResponse(e);
75
107
  }
76
108
  }
77
109
 
78
- return { name: "git-tags", description: "Gerencia tags e push paralelo", inputSchema, handle };
110
+ return { name: "git-tags", description, inputSchema, handle };
79
111
  }
@@ -8,16 +8,56 @@ export function createGitWorkflowTool(pm, git) {
8
8
  const inputSchema = {
9
9
  type: "object",
10
10
  properties: {
11
- projectPath: { type: "string", description: "Caminho absoluto do projeto" },
12
- action: { type: "string", enum: ["init", "status", "add", "remove", "commit", "push", "pull", "sync", "ensure-remotes"], description: "Ação" },
13
- files: { type: "array", items: { type: "string" } },
14
- message: { type: "string" },
15
- force: { type: "boolean", description: "Force push (para resolver divergências de histórico)" }
11
+ projectPath: {
12
+ type: "string",
13
+ description: "Caminho absoluto do diretório do projeto (ex: 'C:/Users/user/projeto' ou '/home/user/projeto')"
14
+ },
15
+ action: {
16
+ type: "string",
17
+ enum: ["init", "status", "add", "remove", "commit", "push", "ensure-remotes"],
18
+ description: `Ação a executar:
19
+ - init: Inicializa repositório git local E cria repos no GitHub/Gitea automaticamente
20
+ - status: Retorna arquivos modificados, staged, untracked (use ANTES de commit para ver o que mudou)
21
+ - add: Adiciona arquivos ao staging (use ANTES de commit)
22
+ - remove: Remove arquivos do staging
23
+ - commit: Cria commit com os arquivos staged (use DEPOIS de add)
24
+ - push: Envia commits para GitHub E Gitea em paralelo (use DEPOIS de commit)
25
+ - ensure-remotes: Configura remotes GitHub e Gitea (use se push falhar por falta de remote)`
26
+ },
27
+ files: {
28
+ type: "array",
29
+ items: { type: "string" },
30
+ description: "Lista de arquivos para add/remove. Use ['.'] para todos os arquivos. Ex: ['src/index.js', 'package.json']"
31
+ },
32
+ message: {
33
+ type: "string",
34
+ description: "Mensagem do commit. Obrigatório para action='commit'. Ex: 'feat: adiciona nova funcionalidade'"
35
+ },
36
+ force: {
37
+ type: "boolean",
38
+ description: "Force push (use apenas se push normal falhar com erro de histórico divergente). Default: false"
39
+ }
16
40
  },
17
41
  required: ["projectPath", "action"],
18
- additionalProperties: true
42
+ additionalProperties: false
19
43
  };
20
44
 
45
+ const description = `Operações Git essenciais com sincronização automática GitHub + Gitea.
46
+
47
+ FLUXO TÍPICO DE TRABALHO:
48
+ 1. git-workflow status → ver arquivos modificados
49
+ 2. git-workflow add → adicionar arquivos ao staging
50
+ 3. git-workflow commit → criar commit
51
+ 4. git-workflow push → enviar para GitHub e Gitea
52
+
53
+ QUANDO USAR CADA ACTION:
54
+ - status: Para verificar estado atual do repositório
55
+ - add: Quando há arquivos modificados para commitar
56
+ - commit: Após add, para salvar as mudanças
57
+ - push: Após commit, para sincronizar com remotes
58
+ - init: Apenas uma vez, para novos projetos
59
+ - ensure-remotes: Se push falhar por falta de configuração`;
60
+
21
61
  async function handle(args) {
22
62
  const validate = ajv.compile(inputSchema);
23
63
  if (!validate(args || {})) {
@@ -29,7 +69,7 @@ export function createGitWorkflowTool(pm, git) {
29
69
  await git.init(projectPath);
30
70
  const repo = getRepoNameFromPath(projectPath);
31
71
  const ensured = await pm.ensureRepos({ repoName: repo, createIfMissing: true });
32
- return asToolResult({ success: true, ensured, message: "Repositório inicializado" });
72
+ return asToolResult({ success: true, ensured, message: "Repositório inicializado localmente e nos providers" });
33
73
  }
34
74
  if (action === "status") {
35
75
  const st = await git.status(projectPath);
@@ -38,7 +78,7 @@ export function createGitWorkflowTool(pm, git) {
38
78
  if (action === "add") {
39
79
  const files = Array.isArray(args.files) && args.files.length ? args.files : ["."];
40
80
  await git.add(projectPath, files);
41
- return asToolResult({ success: true, files });
81
+ return asToolResult({ success: true, files, nextStep: "Use action='commit' com message para criar o commit" });
42
82
  }
43
83
  if (action === "remove") {
44
84
  const files = Array.isArray(args.files) ? args.files : [];
@@ -46,9 +86,11 @@ export function createGitWorkflowTool(pm, git) {
46
86
  return asToolResult({ success: true, files });
47
87
  }
48
88
  if (action === "commit") {
49
- const msg = args.message || "update";
50
- const sha = await git.commit(projectPath, msg);
51
- return asToolResult({ success: true, sha, message: msg });
89
+ if (!args.message) {
90
+ return asToolError("MISSING_PARAMETER", "message é obrigatório para commit", { parameter: "message" });
91
+ }
92
+ const sha = await git.commit(projectPath, args.message);
93
+ return asToolResult({ success: true, sha, message: args.message, nextStep: "Use action='push' para enviar ao GitHub/Gitea" });
52
94
  }
53
95
  if (action === "ensure-remotes") {
54
96
  const repo = getRepoNameFromPath(projectPath);
@@ -59,20 +101,18 @@ export function createGitWorkflowTool(pm, git) {
59
101
  const base = pm.giteaUrl?.replace(/\/$/, "") || "";
60
102
  const giteaUrl = geOwner && base ? `${base}/${geOwner}/${repo}.git` : "";
61
103
  await git.ensureRemotes(projectPath, { githubUrl, giteaUrl });
62
- return asToolResult({ success: true, ensured, remotes: { githubUrl, giteaUrl } });
104
+ const remotes = await git.listRemotes(projectPath);
105
+ return asToolResult({ success: true, ensured, remotes, nextStep: "Agora pode usar action='push'" });
63
106
  }
64
107
  if (action === "push") {
65
108
  const branch = await git.getCurrentBranch(projectPath);
66
109
  const force = !!args.force;
67
- await git.pushParallel(projectPath, branch, force);
68
- return asToolResult({ success: true, branch, remotes: ["github", "gitea"], force });
69
- }
70
- if (action === "sync" || action === "pull") {
71
- // Basic implementation: fetch + status; full merge/pull can be added
72
- return asToolResult({ success: true, message: "Operação de pull/sync não-op realizada" });
110
+ const result = await git.pushParallel(projectPath, branch, force);
111
+ return asToolResult({ success: true, branch, ...result });
73
112
  }
74
- return asToolError("VALIDATION_ERROR", `Ação não suportada: ${action}`, {
75
- availableActions: ["init", "status", "add", "remove", "commit", "push", "pull", "sync", "ensure-remotes"]
113
+ return asToolError("VALIDATION_ERROR", `Ação '${action}' não suportada`, {
114
+ availableActions: ["init", "status", "add", "remove", "commit", "push", "ensure-remotes"],
115
+ suggestion: "Use uma das actions disponíveis"
76
116
  });
77
117
  } catch (e) {
78
118
  return errorToResponse(e);
@@ -81,9 +121,8 @@ export function createGitWorkflowTool(pm, git) {
81
121
 
82
122
  return {
83
123
  name: "git-workflow",
84
- description: "Operações Git locais e remotas em paralelo (GitHub + Gitea)",
124
+ description,
85
125
  inputSchema,
86
126
  handle
87
127
  };
88
128
  }
89
-