@andre.buzeli/git-mcp 16.1.3 → 16.1.6
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 +3 -2
- package/package.json +14 -3
- package/src/index.js +38 -42
- package/src/resources/index.js +79 -41
- package/src/tools/git-branches.js +5 -2
- package/src/tools/git-clone.js +13 -2
- package/src/tools/git-config.js +5 -2
- package/src/tools/git-diff.js +27 -6
- package/src/tools/git-files.js +5 -2
- package/src/tools/git-help.js +8 -3
- package/src/tools/git-history.js +9 -4
- package/src/tools/git-ignore.js +5 -2
- package/src/tools/git-issues.js +5 -2
- package/src/tools/git-merge.js +12 -7
- package/src/tools/git-pulls.js +5 -2
- package/src/tools/git-remote.js +10 -3
- package/src/tools/git-reset.js +5 -2
- package/src/tools/git-stash.js +5 -2
- package/src/tools/git-sync.js +5 -2
- package/src/tools/git-tags.js +5 -2
- package/src/tools/git-workflow.js +97 -42
- package/src/tools/git-worktree.js +66 -38
- package/src/utils/errors.js +21 -0
- package/src/utils/gitAdapter.js +165 -125
- package/src/utils/retry.js +1 -1
- package/src/utils/worktreeResolver.js +189 -0
package/README.md
CHANGED
|
@@ -17,10 +17,11 @@ Servidor MCP (Model Context Protocol) para operações Git locais sem git instal
|
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
|
-
}
|
|
20
|
+
}
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
## Tools
|
|
23
|
+
## Tools
|
|
24
|
+
|
|
24
25
|
|
|
25
26
|
- git-workflow: init, status, add, remove, commit, ensure-remotes, push
|
|
26
27
|
- git-update: status -> add -> commit -> push (all-in-one)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@andre.buzeli/git-mcp",
|
|
3
|
-
"version": "16.1.
|
|
3
|
+
"version": "16.1.6",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "MCP server para Git com operações locais e sincronização paralela GitHub/Gitea",
|
|
6
6
|
"license": "MIT",
|
|
@@ -19,14 +19,25 @@
|
|
|
19
19
|
"git-mcpv2": "src/index.js"
|
|
20
20
|
},
|
|
21
21
|
"scripts": {
|
|
22
|
-
"start": "node src/index.js"
|
|
22
|
+
"start": "node src/index.js",
|
|
23
|
+
"test": "vitest run",
|
|
24
|
+
"test:unit": "vitest run tests/unit",
|
|
25
|
+
"test:integration": "vitest run --config tests/integration/vitest.config.js",
|
|
26
|
+
"test:e2e": "vitest run tests/e2e",
|
|
27
|
+
"test:property": "vitest run tests/property",
|
|
28
|
+
"test:watch": "vitest",
|
|
29
|
+
"test:coverage": "vitest run --coverage"
|
|
23
30
|
},
|
|
24
31
|
"dependencies": {
|
|
25
32
|
"@modelcontextprotocol/sdk": "^1.11.0",
|
|
26
33
|
"@octokit/rest": "^20.0.0",
|
|
27
|
-
"ajv": "^8.
|
|
34
|
+
"ajv": "^8.18.0",
|
|
28
35
|
"archiver": "^7.0.0",
|
|
29
36
|
"axios": "^1.7.7",
|
|
30
37
|
"zod": "^3.23.0"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"fast-check": "^4.6.0",
|
|
41
|
+
"vitest": "^4.1.0"
|
|
31
42
|
}
|
|
32
43
|
}
|
package/src/index.js
CHANGED
|
@@ -59,48 +59,44 @@ const server = new Server(
|
|
|
59
59
|
},
|
|
60
60
|
instructions: `# git-mcp — Instruções para AI Agents
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
{
|
|
100
|
-
\`\`\`
|
|
101
|
-
|
|
102
|
-
## Dica
|
|
103
|
-
Use git-help action="listTools" para ver todas as tools e actions disponíveis em tempo real.`
|
|
62
|
+
ATENÇÃO: NUNCA chame uma tool sem os parâmetros obrigatórios. Toda call incompleta retorna erro.
|
|
63
|
+
|
|
64
|
+
## Parâmetros obrigatórios em TODAS as tools (exceto git-help)
|
|
65
|
+
- "projectPath": caminho absoluto do projeto no sistema de arquivos do usuário. O servidor NÃO detecta automaticamente.
|
|
66
|
+
- "action": string com o nome da action a executar (ver enum no schema de cada tool)
|
|
67
|
+
|
|
68
|
+
## Exemplos prontos para uso — copie e substitua os valores
|
|
69
|
+
|
|
70
|
+
git-workflow (update): {"projectPath":"<PATH>","action":"update","message":"feat: descrição"}
|
|
71
|
+
git-workflow (status): {"projectPath":"<PATH>","action":"status"}
|
|
72
|
+
git-workflow (init): {"projectPath":"<PATH>","action":"init"}
|
|
73
|
+
git-workflow (push): {"projectPath":"<PATH>","action":"push"}
|
|
74
|
+
git-diff (show): {"projectPath":"<PATH>","action":"show"}
|
|
75
|
+
git-diff (compare): {"projectPath":"<PATH>","action":"compare","target":"main"}
|
|
76
|
+
git-branches (list): {"projectPath":"<PATH>","action":"list"}
|
|
77
|
+
git-branches (create): {"projectPath":"<PATH>","action":"create","branch":"feature/x"}
|
|
78
|
+
git-branches (checkout):{"projectPath":"<PATH>","action":"checkout","branch":"main"}
|
|
79
|
+
git-merge (merge): {"projectPath":"<PATH>","action":"merge","branch":"feature/x"}
|
|
80
|
+
git-tags (create): {"projectPath":"<PATH>","action":"create","tag":"v1.0.0"}
|
|
81
|
+
git-tags (push): {"projectPath":"<PATH>","action":"push","tag":"v1.0.0"}
|
|
82
|
+
git-stash (save): {"projectPath":"<PATH>","action":"save"}
|
|
83
|
+
git-stash (pop): {"projectPath":"<PATH>","action":"pop"}
|
|
84
|
+
git-reset (soft): {"projectPath":"<PATH>","action":"soft","ref":"HEAD~1"}
|
|
85
|
+
git-reset (hard): {"projectPath":"<PATH>","action":"hard","ref":"HEAD~1"}
|
|
86
|
+
git-history (log): {"projectPath":"<PATH>","action":"log"}
|
|
87
|
+
git-remote (ensure): {"projectPath":"<PATH>","action":"ensure"}
|
|
88
|
+
git-remote (list): {"projectPath":"<PATH>","action":"list"}
|
|
89
|
+
git-remote (release-create): {"projectPath":"<PATH>","action":"release-create","tag":"v1.0.0","name":"Release v1.0.0"}
|
|
90
|
+
git-worktree (list): {"projectPath":"<PATH>","action":"list"}
|
|
91
|
+
git-worktree (add): {"projectPath":"<PATH>","action":"add","branch":"feature/x"}
|
|
92
|
+
git-sync (pull): {"projectPath":"<PATH>","action":"pull"}
|
|
93
|
+
git-config (get): {"projectPath":"<PATH>","action":"get","key":"user.name"}
|
|
94
|
+
git-ignore (add): {"projectPath":"<PATH>","action":"add","patterns":["node_modules/"]}
|
|
95
|
+
git-files (read): {"projectPath":"<PATH>","action":"read","filepath":"package.json"}
|
|
96
|
+
git-issues (create): {"projectPath":"<PATH>","action":"create","title":"Bug: descrição"}
|
|
97
|
+
git-pulls (create): {"projectPath":"<PATH>","action":"create","head":"feature/x","base":"main","title":"feat: x"}
|
|
98
|
+
git-clone (clone): {"projectPath":"<PARENT_DIR>","action":"clone","url":"https://github.com/user/repo.git"}
|
|
99
|
+
git-help: {"listTools":true} ← única tool sem projectPath/action obrigatórios`
|
|
104
100
|
}
|
|
105
101
|
);
|
|
106
102
|
server.connect(transport);
|
package/src/resources/index.js
CHANGED
|
@@ -22,17 +22,21 @@ Operações Git essenciais.
|
|
|
22
22
|
|
|
23
23
|
| Action | Descrição | Parâmetros |
|
|
24
24
|
|--------|-----------|------------|
|
|
25
|
-
| **update** | **⭐ RECOMENDADO - Fluxo completo automatizado** | **message, files=["."], gitignore=["pattern"], force, skipIfClean, organization** |
|
|
26
|
-
| status | Ver arquivos modificados/staged |
|
|
25
|
+
| **update** | **⭐ RECOMENDADO - Fluxo completo automatizado** | **message (obrigatório), files=["."], gitignore=["pattern"], force, skipIfClean, channel, syncBranches, organization, isPublic, dryRun** |
|
|
26
|
+
| status | Ver arquivos modificados/staged | dryRun |
|
|
27
27
|
| add | Adicionar ao staging | files=["."] ou ["arquivo.js"] |
|
|
28
|
-
|
|
|
29
|
-
|
|
|
30
|
-
|
|
|
31
|
-
|
|
|
32
|
-
|
|
|
28
|
+
| remove | Remover do staging | files=["arquivo.js"] |
|
|
29
|
+
| commit | Criar commit | message="descrição" (obrigatório), dryRun |
|
|
30
|
+
| push | Enviar para GitHub+Gitea | force=true se histórico divergir, organization |
|
|
31
|
+
| init | Inicializar repo + criar remotes | createGitignore=true, isPublic, organization, dryRun |
|
|
32
|
+
| ensure-remotes | Configurar remotes | organization, isPublic, dryRun |
|
|
33
|
+
| clean | Remover arquivos não rastreados | dryRun |
|
|
34
|
+
| init-branch | Criar worktree/branch atalho | branch (obrigatório), channel |
|
|
33
35
|
|
|
34
36
|
**Exemplo update:** \`{ "projectPath": "/path", "action": "update", "message": "feat: nova func", "gitignore": ["*.log"] }\`
|
|
35
37
|
**Com organização:** \`{ "projectPath": "/path", "action": "init", "organization": "automacao-casa" }\`
|
|
38
|
+
**Com channel:** \`{ "projectPath": "/path", "action": "update", "message": "fix: patch", "channel": "beta" }\`
|
|
39
|
+
**Sync worktrees:** \`{ "projectPath": "/path", "action": "update", "message": "sync", "syncBranches": true }\`
|
|
36
40
|
|
|
37
41
|
---
|
|
38
42
|
|
|
@@ -51,20 +55,20 @@ Gerenciar branches.
|
|
|
51
55
|
|
|
52
56
|
---
|
|
53
57
|
|
|
54
|
-
## git-merge
|
|
58
|
+
## git-merge
|
|
55
59
|
Mesclar branches.
|
|
56
60
|
|
|
57
61
|
| Action | Descrição | Parâmetros |
|
|
58
62
|
|--------|-----------|------------|
|
|
59
|
-
| merge | Mesclar branch |
|
|
60
|
-
| status | Verificar
|
|
61
|
-
| abort | Abortar merge | - |
|
|
63
|
+
| merge | Mesclar branch na branch atual | branch="feature/x" (obrigatório), message="opcional", squash=true |
|
|
64
|
+
| status | Verificar se há merge em andamento | - |
|
|
65
|
+
| abort | Abortar merge com conflitos | - |
|
|
62
66
|
|
|
63
|
-
**
|
|
67
|
+
**Nota:** Faça checkout para a branch destino antes de executar merge. squash=true combina todos os commits em um.
|
|
64
68
|
|
|
65
69
|
---
|
|
66
70
|
|
|
67
|
-
## git-diff
|
|
71
|
+
## git-diff
|
|
68
72
|
Visualizar diferenças.
|
|
69
73
|
|
|
70
74
|
| Action | Descrição | Parâmetros |
|
|
@@ -75,14 +79,14 @@ Visualizar diferenças.
|
|
|
75
79
|
|
|
76
80
|
---
|
|
77
81
|
|
|
78
|
-
## git-clone
|
|
82
|
+
## git-clone
|
|
79
83
|
Clonar repositórios.
|
|
80
84
|
|
|
81
85
|
| Action | Descrição | Parâmetros |
|
|
82
86
|
|--------|-----------|------------|
|
|
83
|
-
| clone | Clonar repo | url="https://...",
|
|
87
|
+
| clone | Clonar repo | url="https://..." (obrigatório), name="pasta-destino" (opcional) |
|
|
84
88
|
|
|
85
|
-
**Opções:** branch="main", depth=1 (shallow clone)
|
|
89
|
+
**Opções:** branch="main", depth=1 (shallow clone). projectPath é o diretório PAI onde o repo será clonado.
|
|
86
90
|
|
|
87
91
|
---
|
|
88
92
|
|
|
@@ -92,9 +96,9 @@ Versionamento semântico.
|
|
|
92
96
|
| Action | Descrição | Parâmetros |
|
|
93
97
|
|--------|-----------|------------|
|
|
94
98
|
| list | Listar tags | - |
|
|
95
|
-
| create | Criar tag | tag="v1.0.0", message="opcional" |
|
|
96
|
-
| delete | Deletar tag | tag="v1.0.0" |
|
|
97
|
-
| push | Enviar para remotes | tag="v1.0.0" |
|
|
99
|
+
| create | Criar tag | tag="v1.0.0" (obrigatório), ref="HEAD" (opcional), message="opcional" (cria tag anotada) |
|
|
100
|
+
| delete | Deletar tag local | tag="v1.0.0" (obrigatório) |
|
|
101
|
+
| push | Enviar para remotes | tag="v1.0.0" (obrigatório) |
|
|
98
102
|
|
|
99
103
|
**Versões:** v1.0.0 (inicial), v1.1.0 (feature), v1.0.1 (bugfix), v2.0.0 (breaking)
|
|
100
104
|
|
|
@@ -106,10 +110,10 @@ Salvar mudanças temporariamente.
|
|
|
106
110
|
| Action | Descrição | Parâmetros |
|
|
107
111
|
|--------|-----------|------------|
|
|
108
112
|
| list | Ver stashes salvos | - |
|
|
109
|
-
| save | Salvar mudanças | message="WIP", includeUntracked=true |
|
|
110
|
-
| pop | Restaurar e remover | ref="stash@{0}" |
|
|
111
|
-
| apply | Restaurar sem remover | ref="stash@{0}" |
|
|
112
|
-
| drop | Remover sem restaurar | ref="stash@{0}" |
|
|
113
|
+
| save | Salvar mudanças | message="WIP" (opcional), includeUntracked=true (opcional) |
|
|
114
|
+
| pop | Restaurar e remover | ref="stash@{0}" (opcional, default: mais recente) |
|
|
115
|
+
| apply | Restaurar sem remover | ref="stash@{0}" (opcional, default: mais recente) |
|
|
116
|
+
| drop | Remover sem restaurar | ref="stash@{0}" (opcional, default: mais recente) |
|
|
113
117
|
| clear | Remover todos | - |
|
|
114
118
|
|
|
115
119
|
---
|
|
@@ -119,12 +123,13 @@ Desfazer commits. ⚠️ CUIDADO
|
|
|
119
123
|
|
|
120
124
|
| Action | Descrição | Parâmetros |
|
|
121
125
|
|--------|-----------|------------|
|
|
122
|
-
| soft | Mantém mudanças staged | ref="HEAD~1" |
|
|
123
|
-
| mixed | Mantém arquivos, remove staging | ref="HEAD~1" |
|
|
124
|
-
| hard | ⚠️ DESCARTA tudo | ref="HEAD~1" |
|
|
125
|
-
| hard-clean | ⚠️⚠️ DESCARTA + remove untracked | ref="HEAD" |
|
|
126
|
+
| soft | Mantém mudanças staged | ref="HEAD~1" (obrigatório) |
|
|
127
|
+
| mixed | Mantém arquivos, remove staging | ref="HEAD~1" (obrigatório) |
|
|
128
|
+
| hard | ⚠️ DESCARTA tudo | ref="HEAD~1" (obrigatório) |
|
|
129
|
+
| hard-clean | ⚠️⚠️ DESCARTA + remove untracked | ref="HEAD" (obrigatório) |
|
|
126
130
|
|
|
127
|
-
**Refs:** HEAD~1 (1 commit), HEAD~2 (2 commits), SHA específico
|
|
131
|
+
**Refs:** HEAD~1 (1 commit atrás), HEAD~2 (2 commits), SHA específico do commit
|
|
132
|
+
**Nota:** hard e hard-clean pedem confirmação antes de executar.
|
|
128
133
|
|
|
129
134
|
---
|
|
130
135
|
|
|
@@ -146,6 +151,8 @@ Operações em repos remotos GitHub/Gitea.
|
|
|
146
151
|
| fork-list | Listar forks | organization |
|
|
147
152
|
| star-set | Dar estrela | - |
|
|
148
153
|
| star-unset | Remover estrela | - |
|
|
154
|
+
| subscription-set | Ativar notificações | - |
|
|
155
|
+
| subscription-unset | Desativar notificações | - |
|
|
149
156
|
| contents-create | Criar arquivo via API | path="", content="", branch="", organization |
|
|
150
157
|
|
|
151
158
|
**Exemplo com organização:** \`{ "projectPath": "/path", "action": "ensure", "organization": "minha-org" }\`
|
|
@@ -171,9 +178,9 @@ Gerenciar issues.
|
|
|
171
178
|
|
|
172
179
|
| Action | Descrição | Parâmetros |
|
|
173
180
|
|--------|-----------|------------|
|
|
174
|
-
| create | Criar issue | title="Bug: ...", body="Descrição" |
|
|
175
|
-
| list | Listar issues |
|
|
176
|
-
| comment | Comentar | number=1, body="Comentário" |
|
|
181
|
+
| create | Criar issue | title="Bug: ..." (obrigatório), body="Descrição", organization |
|
|
182
|
+
| list | Listar issues | organization |
|
|
183
|
+
| comment | Comentar | number=1 (obrigatório), body="Comentário" (obrigatório), organization |
|
|
177
184
|
|
|
178
185
|
---
|
|
179
186
|
|
|
@@ -182,9 +189,9 @@ Gerenciar Pull Requests.
|
|
|
182
189
|
|
|
183
190
|
| Action | Descrição | Parâmetros |
|
|
184
191
|
|--------|-----------|------------|
|
|
185
|
-
| create | Criar PR | head="feature/x", base="main", title="" |
|
|
186
|
-
| list | Listar PRs |
|
|
187
|
-
| files | Ver arquivos do PR | number=1 |
|
|
192
|
+
| create | Criar PR | head="feature/x" (obrigatório), base="main" (obrigatório), title="", body="", organization |
|
|
193
|
+
| list | Listar PRs | organization |
|
|
194
|
+
| files | Ver arquivos do PR | number=1 (obrigatório), organization |
|
|
188
195
|
|
|
189
196
|
---
|
|
190
197
|
|
|
@@ -203,12 +210,13 @@ Configurações Git.
|
|
|
203
210
|
|
|
204
211
|
| Action | Descrição | Parâmetros |
|
|
205
212
|
|--------|-----------|------------|
|
|
206
|
-
| get | Obter valor | key="user.name" |
|
|
207
|
-
| set | Definir valor | key="user.name", value="Nome" |
|
|
208
|
-
| unset | Remover | key="user.name" |
|
|
213
|
+
| get | Obter valor | key="user.name" (obrigatório), scope="local" |
|
|
214
|
+
| set | Definir valor | key="user.name" (obrigatório), value="Nome", scope="local" |
|
|
215
|
+
| unset | Remover | key="user.name" (obrigatório), scope="local" |
|
|
209
216
|
| list | Listar todas | scope="local" |
|
|
210
217
|
|
|
211
|
-
**Keys:** user.name, user.email, core.autocrlf
|
|
218
|
+
**Keys comuns:** user.name, user.email, core.autocrlf, core.editor
|
|
219
|
+
**Scopes:** local (só este repo), global (todos os repos), system (todo o sistema). Default: local
|
|
212
220
|
|
|
213
221
|
---
|
|
214
222
|
|
|
@@ -237,9 +245,39 @@ Gerenciar .gitignore.
|
|
|
237
245
|
| Action | Descrição | Parâmetros |
|
|
238
246
|
|--------|-----------|------------|
|
|
239
247
|
| list | Ver padrões | - |
|
|
240
|
-
| create | Criar .gitignore | patterns=["node_modules/","*.log"] |
|
|
241
|
-
| add | Adicionar padrões | patterns=["dist/"] |
|
|
242
|
-
| remove | Remover padrões | patterns=["*.log"] |
|
|
248
|
+
| create | Criar .gitignore | patterns=["node_modules/","*.log"] (obrigatório) |
|
|
249
|
+
| add | Adicionar padrões | patterns=["dist/"] (obrigatório) |
|
|
250
|
+
| remove | Remover padrões | patterns=["*.log"] (obrigatório) |
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## git-worktree
|
|
255
|
+
Gerenciar múltiplos diretórios de trabalho (worktrees).
|
|
256
|
+
|
|
257
|
+
| Action | Descrição | Parâmetros |
|
|
258
|
+
|--------|-----------|------------|
|
|
259
|
+
| list | Listar worktrees ativos | - |
|
|
260
|
+
| add | Criar novo worktree | branch="nome" (obrigatório), path="caminho" (opcional), channel="production/beta/alpha", force |
|
|
261
|
+
| remove | Remover worktree | branch="nome" ou path="caminho" (um obrigatório), force |
|
|
262
|
+
| prune | Limpar worktrees deletados manualmente | - |
|
|
263
|
+
| setup | Configurar estrutura recomendada | - |
|
|
264
|
+
| set-channel | Definir canal de deploy da branch | branch="nome" (obrigatório), channel="production/beta/alpha" (obrigatório) |
|
|
265
|
+
|
|
266
|
+
**Channels:** production (branch normal), beta (push para branch-beta), alpha (push para branch-alpha)
|
|
267
|
+
**Nota:** path em add é relativo ao projectPath. Default: ../branch-name
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
## git-help
|
|
272
|
+
Orientação sobre qual tool usar.
|
|
273
|
+
|
|
274
|
+
| Parâmetro | Descrição |
|
|
275
|
+
|-----------|-----------|
|
|
276
|
+
| query="o que fazer" | Recomenda a tool certa para a intenção |
|
|
277
|
+
| listTools=true | Lista todas as tools com descrição e actions |
|
|
278
|
+
| showFlows=true | Mostra fluxos de trabalho comuns passo a passo |
|
|
279
|
+
|
|
280
|
+
**Nota:** Única tool que não exige projectPath.
|
|
243
281
|
|
|
244
282
|
---
|
|
245
283
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Ajv from "ajv";
|
|
2
|
-
import { asToolError, asToolResult, errorToResponse } from "../utils/errors.js";
|
|
2
|
+
import { asToolError, asToolResult, errorToResponse, handleEmptyCall } from "../utils/errors.js";
|
|
3
3
|
import { validateProjectPath } from "../utils/repoHelpers.js";
|
|
4
4
|
|
|
5
5
|
const ajv = new Ajv({ allErrors: true });
|
|
@@ -59,8 +59,11 @@ CONVENÇÕES DE NOMES:
|
|
|
59
59
|
- release/versao: Para releases`;
|
|
60
60
|
|
|
61
61
|
async function handle(args) {
|
|
62
|
+
const emptyHelp = handleEmptyCall(args, inputSchema, "git-branches", { projectPath: "/path/to/project", action: "list" });
|
|
63
|
+
if (emptyHelp) return emptyHelp;
|
|
64
|
+
|
|
62
65
|
const validate = ajv.compile(inputSchema);
|
|
63
|
-
if (!validate(args
|
|
66
|
+
if (!validate(args)) return asToolError("VALIDATION_ERROR", "Parâmetros inválidos", validate.errors);
|
|
64
67
|
const { projectPath, action } = args;
|
|
65
68
|
try {
|
|
66
69
|
validateProjectPath(projectPath);
|
package/src/tools/git-clone.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Ajv from "ajv";
|
|
2
|
-
import { asToolError, asToolResult, errorToResponse } from "../utils/errors.js";
|
|
2
|
+
import { asToolError, asToolResult, errorToResponse, handleEmptyCall } from "../utils/errors.js";
|
|
3
3
|
import { validateProjectPath } from "../utils/repoHelpers.js";
|
|
4
4
|
import { withRetry } from "../utils/retry.js";
|
|
5
5
|
|
|
@@ -55,8 +55,11 @@ EXEMPLO:
|
|
|
55
55
|
- Shallow clone (rápido): action='clone' url='...' depth=1`;
|
|
56
56
|
|
|
57
57
|
async function handle(args) {
|
|
58
|
+
const emptyHelp = handleEmptyCall(args, inputSchema, "git-clone", { projectPath: "/path/to/parent", action: "clone", url: "https://github.com/user/repo.git" });
|
|
59
|
+
if (emptyHelp) return emptyHelp;
|
|
60
|
+
|
|
58
61
|
const validate = ajv.compile(inputSchema);
|
|
59
|
-
if (!validate(args
|
|
62
|
+
if (!validate(args)) return asToolError("VALIDATION_ERROR", "Parâmetros inválidos", validate.errors);
|
|
60
63
|
|
|
61
64
|
// projectPath aqui é o diretório PAI
|
|
62
65
|
const { projectPath, action, url } = args;
|
|
@@ -67,6 +70,14 @@ EXEMPLO:
|
|
|
67
70
|
validateProjectPath(projectPath);
|
|
68
71
|
|
|
69
72
|
if (action === "clone") {
|
|
73
|
+
const validation = git.validateRemoteUrl(url);
|
|
74
|
+
if (!validation.valid) {
|
|
75
|
+
return asToolError("INVALID_URL", validation.error, {
|
|
76
|
+
url,
|
|
77
|
+
suggestion: validation.suggestion
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
70
81
|
await withRetry(() => git.clone(projectPath, url, {
|
|
71
82
|
name: args.name,
|
|
72
83
|
branch: args.branch,
|
package/src/tools/git-config.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Ajv from "ajv";
|
|
2
|
-
import { asToolError, asToolResult, errorToResponse } from "../utils/errors.js";
|
|
2
|
+
import { asToolError, asToolResult, errorToResponse, handleEmptyCall } from "../utils/errors.js";
|
|
3
3
|
import { validateProjectPath } from "../utils/repoHelpers.js";
|
|
4
4
|
import { withRetry } from "../utils/retry.js";
|
|
5
5
|
|
|
@@ -63,8 +63,11 @@ EXEMPLOS:
|
|
|
63
63
|
- Ver nome: action='get' key='user.name'`;
|
|
64
64
|
|
|
65
65
|
async function handle(args) {
|
|
66
|
+
const emptyHelp = handleEmptyCall(args, inputSchema, "git-config", { projectPath: "/path/to/project", action: "get", key: "user.name" });
|
|
67
|
+
if (emptyHelp) return emptyHelp;
|
|
68
|
+
|
|
66
69
|
const validate = ajv.compile(inputSchema);
|
|
67
|
-
if (!validate(args
|
|
70
|
+
if (!validate(args)) return asToolError("VALIDATION_ERROR", "Parâmetros inválidos", validate.errors);
|
|
68
71
|
const { projectPath, action } = args;
|
|
69
72
|
const scope = args.scope || "local";
|
|
70
73
|
try {
|
package/src/tools/git-diff.js
CHANGED
|
@@ -1,9 +1,23 @@
|
|
|
1
1
|
import Ajv from "ajv";
|
|
2
|
-
import { asToolError, asToolResult, errorToResponse } from "../utils/errors.js";
|
|
2
|
+
import { asToolError, asToolResult, errorToResponse, handleEmptyCall } from "../utils/errors.js";
|
|
3
3
|
import { validateProjectPath } from "../utils/repoHelpers.js";
|
|
4
4
|
|
|
5
5
|
const ajv = new Ajv({ allErrors: true });
|
|
6
6
|
|
|
7
|
+
const DIFF_MAX_CHARS = 100_000;
|
|
8
|
+
|
|
9
|
+
function applyDiffLimit(diff) {
|
|
10
|
+
if (!diff || diff.length <= DIFF_MAX_CHARS) {
|
|
11
|
+
return { diff: diff || "", truncated: false };
|
|
12
|
+
}
|
|
13
|
+
return {
|
|
14
|
+
diff: diff.substring(0, DIFF_MAX_CHARS),
|
|
15
|
+
truncated: true,
|
|
16
|
+
truncatedAt: DIFF_MAX_CHARS,
|
|
17
|
+
originalSize: diff.length
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
7
21
|
export function createGitDiffTool(git) {
|
|
8
22
|
const inputSchema = {
|
|
9
23
|
type: "object",
|
|
@@ -56,28 +70,35 @@ EXEMPLOS:
|
|
|
56
70
|
- Estatísticas de mudança: action='stat' target='HEAD~1'`;
|
|
57
71
|
|
|
58
72
|
async function handle(args) {
|
|
73
|
+
const emptyHelp = handleEmptyCall(args, inputSchema, "git-diff", { projectPath: "/path/to/project", action: "show" });
|
|
74
|
+
if (emptyHelp) return emptyHelp;
|
|
75
|
+
|
|
59
76
|
const validate = ajv.compile(inputSchema);
|
|
60
|
-
if (!validate(args
|
|
77
|
+
if (!validate(args)) return asToolError("VALIDATION_ERROR", "Parâmetros inválidos", validate.errors);
|
|
61
78
|
const { projectPath, action } = args;
|
|
62
79
|
|
|
63
80
|
try {
|
|
64
81
|
validateProjectPath(projectPath);
|
|
65
82
|
|
|
66
83
|
if (action === "show") {
|
|
67
|
-
const
|
|
84
|
+
const raw = await git.diff(projectPath, { staged: args.staged });
|
|
85
|
+
const { diff, ...truncInfo } = applyDiffLimit(raw);
|
|
68
86
|
return asToolResult({
|
|
69
87
|
diff: diff || "Nenhuma diferença encontrada",
|
|
70
|
-
staged: !!args.staged
|
|
88
|
+
staged: !!args.staged,
|
|
89
|
+
...truncInfo
|
|
71
90
|
});
|
|
72
91
|
}
|
|
73
92
|
|
|
74
93
|
if (action === "compare") {
|
|
75
94
|
if (!args.target) return asToolError("MISSING_PARAMETER", "target é obrigatório para compare", { parameter: "target", example: "main" });
|
|
76
|
-
const
|
|
95
|
+
const raw = await git.diff(projectPath, { target: args.target, source: args.source });
|
|
96
|
+
const { diff, ...truncInfo } = applyDiffLimit(raw);
|
|
77
97
|
return asToolResult({
|
|
78
98
|
diff: diff || "Nenhuma diferença encontrada",
|
|
79
99
|
target: args.target,
|
|
80
|
-
source: args.source || "HEAD"
|
|
100
|
+
source: args.source || "HEAD",
|
|
101
|
+
...truncInfo
|
|
81
102
|
});
|
|
82
103
|
}
|
|
83
104
|
|
package/src/tools/git-files.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Ajv from "ajv";
|
|
2
|
-
import { asToolError, asToolResult, errorToResponse } from "../utils/errors.js";
|
|
2
|
+
import { asToolError, asToolResult, errorToResponse, handleEmptyCall } from "../utils/errors.js";
|
|
3
3
|
import { validateProjectPath, withRetry } from "../utils/repoHelpers.js";
|
|
4
4
|
|
|
5
5
|
const ajv = new Ajv({ allErrors: true });
|
|
@@ -52,8 +52,11 @@ EXEMPLOS:
|
|
|
52
52
|
NOTA: Esta tool lê arquivos do histórico Git, não do sistema de arquivos.`;
|
|
53
53
|
|
|
54
54
|
async function handle(args) {
|
|
55
|
+
const emptyHelp = handleEmptyCall(args, inputSchema, "git-files", { projectPath: "/path/to/project", action: "list" });
|
|
56
|
+
if (emptyHelp) return emptyHelp;
|
|
57
|
+
|
|
55
58
|
const validate = ajv.compile(inputSchema);
|
|
56
|
-
if (!validate(args
|
|
59
|
+
if (!validate(args)) return asToolError("VALIDATION_ERROR", "Parâmetros inválidos", validate.errors);
|
|
57
60
|
const { projectPath, action } = args;
|
|
58
61
|
try {
|
|
59
62
|
validateProjectPath(projectPath);
|
package/src/tools/git-help.js
CHANGED
|
@@ -31,7 +31,7 @@ export function createGitHelpTool() {
|
|
|
31
31
|
},
|
|
32
32
|
"git-worktree": {
|
|
33
33
|
purpose: "Gerenciar worktrees (multibranch)",
|
|
34
|
-
actions: ["add", "list", "remove", "setup", "set-channel"],
|
|
34
|
+
actions: ["add", "list", "remove", "prune", "setup", "set-channel"],
|
|
35
35
|
useWhen: "Trabalhar em múltiplas branches/plataformas simultaneamente no mesmo repo"
|
|
36
36
|
},
|
|
37
37
|
"git-branches": {
|
|
@@ -76,8 +76,8 @@ export function createGitHelpTool() {
|
|
|
76
76
|
},
|
|
77
77
|
"git-remote": {
|
|
78
78
|
purpose: "Operações em GitHub/Gitea",
|
|
79
|
-
actions: ["list", "ensure", "release-create", "topics-set", "label-create"],
|
|
80
|
-
useWhen: "Criar release, configurar repositório remoto"
|
|
79
|
+
actions: ["list", "list-all", "list-orgs", "ensure", "release-create", "topics-set", "label-create", "milestone-create", "fork-create", "fork-list", "star-set", "star-unset", "subscription-set", "subscription-unset", "contents-create", "repo-delete"],
|
|
80
|
+
useWhen: "Criar release, configurar repositório remoto, gerenciar repos remotos"
|
|
81
81
|
},
|
|
82
82
|
"git-sync": {
|
|
83
83
|
purpose: "Sincronizar com remotes",
|
|
@@ -108,6 +108,11 @@ export function createGitHelpTool() {
|
|
|
108
108
|
purpose: "Gerenciar Pull Requests",
|
|
109
109
|
actions: ["create", "list", "files"],
|
|
110
110
|
useWhen: "Propor mudanças para review"
|
|
111
|
+
},
|
|
112
|
+
"git-help": {
|
|
113
|
+
purpose: "Orientação sobre qual tool usar e fluxos de trabalho",
|
|
114
|
+
actions: ["query", "listTools", "showFlows"],
|
|
115
|
+
useWhen: "Não sabe qual tool usar, quer ver lista de tools ou fluxos comuns. Única tool sem projectPath obrigatório."
|
|
111
116
|
}
|
|
112
117
|
};
|
|
113
118
|
|
package/src/tools/git-history.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Ajv from "ajv";
|
|
2
|
-
import { asToolError, asToolResult, errorToResponse } from "../utils/errors.js";
|
|
2
|
+
import { asToolError, asToolResult, errorToResponse, handleEmptyCall } from "../utils/errors.js";
|
|
3
3
|
import { validateProjectPath, withRetry } from "../utils/repoHelpers.js";
|
|
4
4
|
|
|
5
5
|
const ajv = new Ajv({ allErrors: true });
|
|
@@ -58,13 +58,17 @@ EXEMPLOS:
|
|
|
58
58
|
- Ver histórico de tag: action='log' ref='v1.0.0'`;
|
|
59
59
|
|
|
60
60
|
async function handle(args) {
|
|
61
|
+
const emptyHelp = handleEmptyCall(args, inputSchema, "git-history", { projectPath: "/path/to/project", action: "log" });
|
|
62
|
+
if (emptyHelp) return emptyHelp;
|
|
63
|
+
|
|
61
64
|
const validate = ajv.compile(inputSchema);
|
|
62
|
-
if (!validate(args
|
|
65
|
+
if (!validate(args)) return asToolError("VALIDATION_ERROR", "Parâmetros inválidos", validate.errors);
|
|
63
66
|
const { projectPath, action } = args;
|
|
64
67
|
try {
|
|
65
68
|
validateProjectPath(projectPath);
|
|
66
69
|
if (action === "log") {
|
|
67
|
-
const
|
|
70
|
+
const maxCount = args.maxCount || 50;
|
|
71
|
+
const items = await withRetry(() => git.log(projectPath, { ref: args.ref || "HEAD", maxCount }), 3, "history-log");
|
|
68
72
|
if (items.length === 0) {
|
|
69
73
|
return asToolResult({
|
|
70
74
|
commits: [],
|
|
@@ -83,7 +87,8 @@ EXEMPLOS:
|
|
|
83
87
|
date: c.date
|
|
84
88
|
})),
|
|
85
89
|
count: items.length,
|
|
86
|
-
ref: args.ref || "HEAD"
|
|
90
|
+
ref: args.ref || "HEAD",
|
|
91
|
+
hasMore: items.length === maxCount
|
|
87
92
|
});
|
|
88
93
|
}
|
|
89
94
|
return asToolError("VALIDATION_ERROR", `Ação '${action}' não suportada`, { availableActions: ["log"] });
|
package/src/tools/git-ignore.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Ajv from "ajv";
|
|
2
|
-
import { asToolError, asToolResult, errorToResponse } from "../utils/errors.js";
|
|
2
|
+
import { asToolError, asToolResult, errorToResponse, handleEmptyCall } from "../utils/errors.js";
|
|
3
3
|
import { validateProjectPath } from "../utils/repoHelpers.js";
|
|
4
4
|
import { withRetry } from "../utils/retry.js";
|
|
5
5
|
|
|
@@ -59,8 +59,11 @@ EXEMPLOS:
|
|
|
59
59
|
- Adicionar padrão: action='add' patterns=['*.tmp']`;
|
|
60
60
|
|
|
61
61
|
async function handle(args) {
|
|
62
|
+
const emptyHelp = handleEmptyCall(args, inputSchema, "git-ignore", { projectPath: "/path/to/project", action: "list" });
|
|
63
|
+
if (emptyHelp) return emptyHelp;
|
|
64
|
+
|
|
62
65
|
const validate = ajv.compile(inputSchema);
|
|
63
|
-
if (!validate(args
|
|
66
|
+
if (!validate(args)) return asToolError("VALIDATION_ERROR", "Parâmetros inválidos", validate.errors);
|
|
64
67
|
const { projectPath, action } = args;
|
|
65
68
|
const patterns = Array.isArray(args.patterns) ? args.patterns : [];
|
|
66
69
|
try {
|
package/src/tools/git-issues.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import Ajv from "ajv";
|
|
2
2
|
import axios from "axios";
|
|
3
|
-
import { asToolError, asToolResult, errorToResponse } from "../utils/errors.js";
|
|
3
|
+
import { asToolError, asToolResult, errorToResponse, handleEmptyCall } from "../utils/errors.js";
|
|
4
4
|
import { getRepoNameFromPath, validateProjectPath, withRetry } from "../utils/repoHelpers.js";
|
|
5
5
|
import { runBoth } from "../utils/providerExec.js";
|
|
6
6
|
|
|
@@ -66,8 +66,11 @@ BOAS PRÁTICAS:
|
|
|
66
66
|
- Use labels para categorizar (via git-remote label-create)`;
|
|
67
67
|
|
|
68
68
|
async function handle(args) {
|
|
69
|
+
const emptyHelp = handleEmptyCall(args, inputSchema, "git-issues", { projectPath: "/path/to/project", action: "list" });
|
|
70
|
+
if (emptyHelp) return emptyHelp;
|
|
71
|
+
|
|
69
72
|
const validate = ajv.compile(inputSchema);
|
|
70
|
-
if (!validate(args
|
|
73
|
+
if (!validate(args)) return asToolError("VALIDATION_ERROR", "Parâmetros inválidos", validate.errors);
|
|
71
74
|
validateProjectPath(args.projectPath);
|
|
72
75
|
const repo = getRepoNameFromPath(args.projectPath);
|
|
73
76
|
try {
|