@andre.buzeli/git-mcp 16.1.4 → 16.1.7
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 +1 -1
- package/src/index.js +38 -47
- package/src/prompts/index.js +44 -38
- package/src/tools/git-branches.js +5 -2
- package/src/tools/git-clone.js +5 -2
- package/src/tools/git-config.js +5 -2
- package/src/tools/git-diff.js +5 -2
- package/src/tools/git-files.js +5 -2
- package/src/tools/git-history.js +5 -2
- package/src/tools/git-ignore.js +5 -2
- package/src/tools/git-issues.js +5 -2
- package/src/tools/git-merge.js +5 -2
- package/src/tools/git-pulls.js +5 -2
- package/src/tools/git-remote.js +5 -2
- 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 +6 -2
- package/src/tools/git-worktree.js +5 -2
- package/src/utils/errors.js +21 -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
package/src/index.js
CHANGED
|
@@ -59,53 +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
|
-
| Ajuda sobre tools | git-help | - | query/listTools/showFlows |
|
|
101
|
-
|
|
102
|
-
## Exemplo Completo (ação mais comum)
|
|
103
|
-
\`\`\`json
|
|
104
|
-
{ "projectPath": "/caminho/do/projeto", "action": "update", "message": "feat: descrição das mudanças" }
|
|
105
|
-
\`\`\`
|
|
106
|
-
|
|
107
|
-
## Dica
|
|
108
|
-
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`
|
|
109
100
|
}
|
|
110
101
|
);
|
|
111
102
|
server.connect(transport);
|
package/src/prompts/index.js
CHANGED
|
@@ -530,37 +530,38 @@ Analise os commits e execute os passos para criar a release${assetsInstructions
|
|
|
530
530
|
type: "text",
|
|
531
531
|
text: `# Atualizar Projeto nos Providers
|
|
532
532
|
|
|
533
|
-
Você precisa atualizar
|
|
533
|
+
Você precisa atualizar o projeto Git atual nos providers remotos (GitHub/Gitea).
|
|
534
534
|
|
|
535
|
-
##
|
|
535
|
+
## AÇÃO IMEDIATA REQUERIDA
|
|
536
536
|
|
|
537
|
-
|
|
538
|
-
- **Branch atual**: ${context.branch || "N/A"}
|
|
539
|
-
- **Arquivos modificados**: ${context.modified?.length || 0}
|
|
540
|
-
- **Arquivos staged**: ${context.staged?.length || 0}
|
|
541
|
-
- **Commits não enviados**: ${context.unpushedCommits || "N/A"}
|
|
542
|
-
- **Remotes configurados**: ${context.remotes?.join(", ") || "Nenhum"}
|
|
537
|
+
Chame AGORA a tool \`git-workflow\` com os seguintes parâmetros:
|
|
543
538
|
|
|
544
|
-
|
|
545
|
-
|
|
539
|
+
- **projectPath**: caminho absoluto do projeto aberto no IDE (você já sabe qual é — é o projeto que o usuário está trabalhando)
|
|
540
|
+
- **action**: "update"
|
|
541
|
+
- **message**: mensagem de commit descritiva${context.userMessage ? ` — o usuário sugeriu: "${context.userMessage}"` : " — gere uma baseada no contexto"}
|
|
546
542
|
|
|
547
|
-
##
|
|
548
|
-
|
|
549
|
-
Execute a atualização completa utilizando uma única chamada com \`git-workflow\` action="update":
|
|
543
|
+
## Exemplo de chamada
|
|
550
544
|
|
|
551
545
|
\`\`\`json
|
|
552
546
|
{
|
|
553
|
-
"projectPath": "
|
|
547
|
+
"projectPath": "<CAMINHO_ABSOLUTO_DO_PROJETO>",
|
|
554
548
|
"action": "update",
|
|
555
|
-
"message": "
|
|
556
|
-
"gitignore": ["padrao_para_ignorar"], // Opcional
|
|
557
|
-
"organization": "nome-da-org" // Opcional: se informado, push vai para a org
|
|
549
|
+
"message": "feat: descrição das mudanças"
|
|
558
550
|
}
|
|
559
551
|
\`\`\`
|
|
560
552
|
|
|
561
|
-
|
|
553
|
+
## Status Coletado${context.projectPath && context.projectPath !== process.cwd() ? ` (projectPath: ${context.projectPath})` : " (projectPath não informado — use o do IDE)"}
|
|
554
|
+
|
|
555
|
+
- **É repositório Git?**: ${context.isGitRepo ? "Sim" : "Não"}
|
|
556
|
+
- **Branch atual**: ${context.branch || "N/A"}
|
|
557
|
+
- **Arquivos modificados**: ${context.modified?.length || 0}
|
|
558
|
+
- **Arquivos staged**: ${context.staged?.length || 0}
|
|
559
|
+
- **Remotes configurados**: ${context.remotes?.join(", ") || "Nenhum"}
|
|
560
|
+
|
|
561
|
+
## Arquivos Modificados
|
|
562
|
+
${context.modified?.map(f => `- ${f}`).join("\n") || "Nenhum"}
|
|
562
563
|
|
|
563
|
-
UTILIZANDO APENAS AS TOOLS DO GIT-MCP.`
|
|
564
|
+
NÃO explique o que vai fazer. Execute diretamente a tool \`git-workflow\` com action="update". UTILIZANDO APENAS AS TOOLS DO GIT-MCP.`
|
|
564
565
|
}
|
|
565
566
|
}]
|
|
566
567
|
}
|
|
@@ -836,26 +837,31 @@ async function gatherContext(promptName, args, git, pm) {
|
|
|
836
837
|
}
|
|
837
838
|
|
|
838
839
|
case "git-update": {
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
const
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
context.
|
|
856
|
-
|
|
857
|
-
context.unpushedCommits = "Desconhecido";
|
|
840
|
+
// Se projectPath não foi fornecido pelo usuário, não tenta coletar status
|
|
841
|
+
// (process.cwd() seria o diretório do servidor MCP, não do projeto do usuário)
|
|
842
|
+
const pathProvidedByUser = !!args.projectPath;
|
|
843
|
+
context.pathProvidedByUser = pathProvidedByUser;
|
|
844
|
+
|
|
845
|
+
if (pathProvidedByUser) {
|
|
846
|
+
const isGitRepo = await git.isRepo(projectPath).catch(() => false);
|
|
847
|
+
context.isGitRepo = isGitRepo;
|
|
848
|
+
|
|
849
|
+
if (isGitRepo) {
|
|
850
|
+
const status = await git.status(projectPath).catch(() => ({}));
|
|
851
|
+
const branch = await git.getCurrentBranch(projectPath).catch(() => null);
|
|
852
|
+
const remotes = await git.listRemotes(projectPath).catch(() => []);
|
|
853
|
+
|
|
854
|
+
context.branch = branch;
|
|
855
|
+
context.modified = status.modified || [];
|
|
856
|
+
context.staged = status.staged || [];
|
|
857
|
+
context.remotes = remotes.map(r => r.name || r.remote);
|
|
858
858
|
}
|
|
859
|
+
} else {
|
|
860
|
+
// Sem projectPath, não coletamos status — o modelo deve usar o path do IDE
|
|
861
|
+
context.isGitRepo = null;
|
|
862
|
+
context.modified = [];
|
|
863
|
+
context.staged = [];
|
|
864
|
+
context.remotes = [];
|
|
859
865
|
}
|
|
860
866
|
break;
|
|
861
867
|
}
|
|
@@ -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;
|
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,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 });
|
|
@@ -70,8 +70,11 @@ EXEMPLOS:
|
|
|
70
70
|
- Estatísticas de mudança: action='stat' target='HEAD~1'`;
|
|
71
71
|
|
|
72
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
|
+
|
|
73
76
|
const validate = ajv.compile(inputSchema);
|
|
74
|
-
if (!validate(args
|
|
77
|
+
if (!validate(args)) return asToolError("VALIDATION_ERROR", "Parâmetros inválidos", validate.errors);
|
|
75
78
|
const { projectPath, action } = args;
|
|
76
79
|
|
|
77
80
|
try {
|
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-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,8 +58,11 @@ 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);
|
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 {
|
package/src/tools/git-merge.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import Ajv from "ajv";
|
|
2
|
-
import { asToolError, asToolResult, errorToResponse, createError } from "../utils/errors.js";
|
|
2
|
+
import { asToolError, asToolResult, errorToResponse, createError, handleEmptyCall } from "../utils/errors.js";
|
|
3
3
|
import { validateProjectPath } from "../utils/repoHelpers.js";
|
|
4
4
|
|
|
5
5
|
const ajv = new Ajv({ allErrors: true });
|
|
@@ -68,8 +68,11 @@ SQUASH:
|
|
|
68
68
|
- Útil para manter histórico limpo`;
|
|
69
69
|
|
|
70
70
|
async function handle(args) {
|
|
71
|
+
const emptyHelp = handleEmptyCall(args, inputSchema, "git-merge", { projectPath: "/path/to/project", action: "status" });
|
|
72
|
+
if (emptyHelp) return emptyHelp;
|
|
73
|
+
|
|
71
74
|
const validate = ajv.compile(inputSchema);
|
|
72
|
-
if (!validate(args
|
|
75
|
+
if (!validate(args)) return asToolError("VALIDATION_ERROR", "Parâmetros inválidos", validate.errors);
|
|
73
76
|
const { projectPath, action } = args;
|
|
74
77
|
|
|
75
78
|
try {
|
package/src/tools/git-pulls.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
|
|
|
@@ -76,8 +76,11 @@ AÇÕES:
|
|
|
76
76
|
NOTA: O PR é criado em AMBOS os providers simultaneamente.`;
|
|
77
77
|
|
|
78
78
|
async function handle(args) {
|
|
79
|
+
const emptyHelp = handleEmptyCall(args, inputSchema, "git-pulls", { projectPath: "/path/to/project", action: "list" });
|
|
80
|
+
if (emptyHelp) return emptyHelp;
|
|
81
|
+
|
|
79
82
|
const validate = ajv.compile(inputSchema);
|
|
80
|
-
if (!validate(args
|
|
83
|
+
if (!validate(args)) return asToolError("VALIDATION_ERROR", "Parâmetros inválidos", validate.errors);
|
|
81
84
|
validateProjectPath(args.projectPath);
|
|
82
85
|
const repo = getRepoNameFromPath(args.projectPath);
|
|
83
86
|
try {
|
package/src/tools/git-remote.js
CHANGED
|
@@ -3,7 +3,7 @@ import axios from "axios";
|
|
|
3
3
|
import fs from "node:fs";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import archiver from "archiver";
|
|
6
|
-
import { asToolError, asToolResult, errorToResponse, mapExternalError } from "../utils/errors.js";
|
|
6
|
+
import { asToolError, asToolResult, errorToResponse, mapExternalError, handleEmptyCall } from "../utils/errors.js";
|
|
7
7
|
import { getRepoNameFromPath, validateProjectPath, withRetry } from "../utils/repoHelpers.js";
|
|
8
8
|
import { runBoth } from "../utils/providerExec.js";
|
|
9
9
|
import { sendLog, requestConfirmation } from "../utils/mcpNotify.js";
|
|
@@ -218,8 +218,11 @@ QUANDO USAR:
|
|
|
218
218
|
- Para configurar tópicos: use action='topics-set'`;
|
|
219
219
|
|
|
220
220
|
async function handle(args) {
|
|
221
|
+
const emptyHelp = handleEmptyCall(args, inputSchema, "git-remote", { projectPath: "/path/to/project", action: "list" });
|
|
222
|
+
if (emptyHelp) return emptyHelp;
|
|
223
|
+
|
|
221
224
|
const validate = ajv.compile(inputSchema);
|
|
222
|
-
if (!validate(args
|
|
225
|
+
if (!validate(args)) return asToolError("VALIDATION_ERROR", "Parâmetros inválidos", validate.errors);
|
|
223
226
|
const { projectPath, action } = args;
|
|
224
227
|
try {
|
|
225
228
|
validateProjectPath(projectPath);
|
package/src/tools/git-reset.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
|
import { sendLog, requestConfirmation } from "../utils/mcpNotify.js";
|
|
5
5
|
|
|
@@ -57,8 +57,11 @@ REFERÊNCIAS:
|
|
|
57
57
|
- abc1234: SHA específico do commit`;
|
|
58
58
|
|
|
59
59
|
async function handle(args) {
|
|
60
|
+
const emptyHelp = handleEmptyCall(args, inputSchema, "git-reset", { projectPath: "/path/to/project", action: "soft", ref: "HEAD~1" });
|
|
61
|
+
if (emptyHelp) return emptyHelp;
|
|
62
|
+
|
|
60
63
|
const validate = ajv.compile(inputSchema);
|
|
61
|
-
if (!validate(args
|
|
64
|
+
if (!validate(args)) return asToolError("VALIDATION_ERROR", "Parâmetros inválidos", validate.errors);
|
|
62
65
|
const { projectPath, action, ref } = args;
|
|
63
66
|
try {
|
|
64
67
|
validateProjectPath(projectPath);
|
package/src/tools/git-stash.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
|
|
|
@@ -67,8 +67,11 @@ AÇÕES:
|
|
|
67
67
|
- clear: Remover todos os stashes`;
|
|
68
68
|
|
|
69
69
|
async function handle(args) {
|
|
70
|
+
const emptyHelp = handleEmptyCall(args, inputSchema, "git-stash", { projectPath: "/path/to/project", action: "list" });
|
|
71
|
+
if (emptyHelp) return emptyHelp;
|
|
72
|
+
|
|
70
73
|
const validate = ajv.compile(inputSchema);
|
|
71
|
-
if (!validate(args
|
|
74
|
+
if (!validate(args)) return asToolError("VALIDATION_ERROR", "Parâmetros inválidos", validate.errors);
|
|
72
75
|
const { projectPath, action } = args;
|
|
73
76
|
try {
|
|
74
77
|
validateProjectPath(projectPath);
|
package/src/tools/git-sync.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 });
|
|
@@ -54,8 +54,11 @@ FLUXO RECOMENDADO:
|
|
|
54
54
|
NOTA: Se pull falhar com conflito, resolva manualmente e faça commit.`;
|
|
55
55
|
|
|
56
56
|
async function handle(args) {
|
|
57
|
+
const emptyHelp = handleEmptyCall(args, inputSchema, "git-sync", { projectPath: "/path/to/project", action: "fetch" });
|
|
58
|
+
if (emptyHelp) return emptyHelp;
|
|
59
|
+
|
|
57
60
|
const validate = ajv.compile(inputSchema);
|
|
58
|
-
if (!validate(args
|
|
61
|
+
if (!validate(args)) return asToolError("VALIDATION_ERROR", "Parâmetros inválidos", validate.errors);
|
|
59
62
|
const { projectPath, action } = args;
|
|
60
63
|
try {
|
|
61
64
|
validateProjectPath(projectPath);
|
package/src/tools/git-tags.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 });
|
|
@@ -61,8 +61,11 @@ FLUXO TÍPICO:
|
|
|
61
61
|
2. git-tags push tag='v1.0.0'`;
|
|
62
62
|
|
|
63
63
|
async function handle(args) {
|
|
64
|
+
const emptyHelp = handleEmptyCall(args, inputSchema, "git-tags", { projectPath: "/path/to/project", action: "list" });
|
|
65
|
+
if (emptyHelp) return emptyHelp;
|
|
66
|
+
|
|
64
67
|
const validate = ajv.compile(inputSchema);
|
|
65
|
-
if (!validate(args
|
|
68
|
+
if (!validate(args)) return asToolError("VALIDATION_ERROR", "Parâmetros inválidos", validate.errors);
|
|
66
69
|
const { projectPath, action } = args;
|
|
67
70
|
try {
|
|
68
71
|
validateProjectPath(projectPath);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Ajv from "ajv";
|
|
2
2
|
import fs from "fs";
|
|
3
3
|
import path from "path";
|
|
4
|
-
import { asToolError, asToolResult, errorToResponse, createError } from "../utils/errors.js";
|
|
4
|
+
import { asToolError, asToolResult, errorToResponse, createError, handleEmptyCall } from "../utils/errors.js";
|
|
5
5
|
import { getRepoNameFromPath, detectProjectType, GITIGNORE_TEMPLATES, validateProjectPath, withRetry } from "../utils/repoHelpers.js";
|
|
6
6
|
import { resolveWorktreeContext, isProtectedPath } from "../utils/worktreeResolver.js";
|
|
7
7
|
import { sendLog } from "../utils/mcpNotify.js";
|
|
@@ -134,8 +134,12 @@ EXEMPLOS DE USO:
|
|
|
134
134
|
• Ver mudanças: { "projectPath": "/path/to/project", "action": "status" }`;
|
|
135
135
|
|
|
136
136
|
async function handle(args) {
|
|
137
|
+
// Call vazia = modelo tentando descobrir o schema. Retorna help em vez de erro.
|
|
138
|
+
const emptyHelp = handleEmptyCall(args, inputSchema, "git-workflow", { projectPath: "/path/to/project", action: "update", message: "feat: descrição" });
|
|
139
|
+
if (emptyHelp) return emptyHelp;
|
|
140
|
+
|
|
137
141
|
const validate = ajv.compile(inputSchema);
|
|
138
|
-
if (!validate(args
|
|
142
|
+
if (!validate(args)) {
|
|
139
143
|
return asToolError("VALIDATION_ERROR", "Parâmetros inválidos", validate.errors);
|
|
140
144
|
}
|
|
141
145
|
const { projectPath, action } = args;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import Ajv from "ajv";
|
|
2
2
|
import fs from "fs";
|
|
3
3
|
import path from "path";
|
|
4
|
-
import { asToolError, asToolResult, errorToResponse } from "../utils/errors.js";
|
|
4
|
+
import { asToolError, asToolResult, errorToResponse, handleEmptyCall } from "../utils/errors.js";
|
|
5
5
|
import { validateProjectPath, withRetry } from "../utils/repoHelpers.js";
|
|
6
6
|
import { resolveWorktreeContext, isProtectedPath } from "../utils/worktreeResolver.js";
|
|
7
7
|
|
|
@@ -73,8 +73,11 @@ AÇÕES:
|
|
|
73
73
|
- set-channel: Configurar canal de deploy (prod/beta/alpha)`;
|
|
74
74
|
|
|
75
75
|
async function handle(args) {
|
|
76
|
+
const emptyHelp = handleEmptyCall(args, inputSchema, "git-worktree", { projectPath: "/path/to/project", action: "list" });
|
|
77
|
+
if (emptyHelp) return emptyHelp;
|
|
78
|
+
|
|
76
79
|
const validate = ajv.compile(inputSchema);
|
|
77
|
-
if (!validate(args
|
|
80
|
+
if (!validate(args)) return asToolError("VALIDATION_ERROR", "Parâmetros inválidos", validate.errors);
|
|
78
81
|
const { projectPath, action } = args;
|
|
79
82
|
let effectivePath = projectPath;
|
|
80
83
|
let worktreeCtx = null;
|
package/src/utils/errors.js
CHANGED
|
@@ -432,3 +432,24 @@ export function errorToResponse(error) {
|
|
|
432
432
|
const mapped = mapExternalError(error);
|
|
433
433
|
return asToolError(mapped.code, mapped.message, mapped.data);
|
|
434
434
|
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Detecta call vazia (sem projectPath/action) e retorna help em vez de erro seco.
|
|
438
|
+
* Isso evita que modelos façam "tool probing" — uma call vazia para descobrir o schema.
|
|
439
|
+
* @param {object} args - Argumentos recebidos
|
|
440
|
+
* @param {object} inputSchema - Schema da tool
|
|
441
|
+
* @param {string} toolName - Nome da tool
|
|
442
|
+
* @param {object} example - Exemplo de uso mínimo
|
|
443
|
+
* @returns {object|null} - Resposta de help, ou null se args não estão vazios
|
|
444
|
+
*/
|
|
445
|
+
export function handleEmptyCall(args, inputSchema, toolName, example) {
|
|
446
|
+
if (args && Object.keys(args).length > 0) return null;
|
|
447
|
+
return asToolResult({
|
|
448
|
+
help: true,
|
|
449
|
+
tool: toolName,
|
|
450
|
+
requiredParams: (inputSchema.required || []).join(", "),
|
|
451
|
+
example,
|
|
452
|
+
actions: inputSchema.properties?.action?.enum || [],
|
|
453
|
+
hint: `Sempre inclua ${(inputSchema.required || []).join(" e ")} na chamada.`
|
|
454
|
+
});
|
|
455
|
+
}
|