@cyanheads/git-mcp-server 2.2.0 → 2.2.2
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/mcp-server/tools/gitAdd/logic.js +26 -45
- package/dist/mcp-server/tools/gitAdd/registration.js +6 -5
- package/dist/mcp-server/tools/gitBranch/logic.js +34 -51
- package/dist/mcp-server/tools/gitBranch/registration.js +7 -7
- package/dist/mcp-server/tools/gitCheckout/logic.js +15 -37
- package/dist/mcp-server/tools/gitCheckout/registration.js +7 -7
- package/dist/mcp-server/tools/gitCherryPick/logic.js +9 -28
- package/dist/mcp-server/tools/gitCherryPick/registration.js +7 -7
- package/dist/mcp-server/tools/gitClean/logic.js +9 -19
- package/dist/mcp-server/tools/gitClean/registration.js +7 -7
- package/dist/mcp-server/tools/gitClearWorkingDir/logic.js +4 -11
- package/dist/mcp-server/tools/gitClearWorkingDir/registration.js +7 -7
- package/dist/mcp-server/tools/gitClone/logic.js +10 -29
- package/dist/mcp-server/tools/gitClone/registration.js +7 -7
- package/dist/mcp-server/tools/gitCommit/logic.js +22 -52
- package/dist/mcp-server/tools/gitCommit/registration.js +7 -7
- package/dist/mcp-server/tools/gitDiff/logic.js +21 -37
- package/dist/mcp-server/tools/gitDiff/registration.js +7 -7
- package/dist/mcp-server/tools/gitFetch/logic.js +4 -20
- package/dist/mcp-server/tools/gitFetch/registration.js +7 -7
- package/dist/mcp-server/tools/gitInit/logic.js +10 -26
- package/dist/mcp-server/tools/gitInit/registration.js +7 -7
- package/dist/mcp-server/tools/gitLog/logic.js +19 -32
- package/dist/mcp-server/tools/gitLog/registration.js +7 -7
- package/dist/mcp-server/tools/gitMerge/logic.js +9 -28
- package/dist/mcp-server/tools/gitMerge/registration.js +7 -7
- package/dist/mcp-server/tools/gitPull/logic.js +4 -23
- package/dist/mcp-server/tools/gitPull/registration.js +7 -7
- package/dist/mcp-server/tools/gitPush/logic.js +9 -28
- package/dist/mcp-server/tools/gitPush/registration.js +7 -7
- package/dist/mcp-server/tools/gitRebase/logic.js +9 -28
- package/dist/mcp-server/tools/gitRebase/registration.js +7 -7
- package/dist/mcp-server/tools/gitRemote/logic.js +22 -38
- package/dist/mcp-server/tools/gitRemote/registration.js +7 -7
- package/dist/mcp-server/tools/gitReset/logic.js +5 -21
- package/dist/mcp-server/tools/gitReset/registration.js +7 -7
- package/dist/mcp-server/tools/gitSetWorkingDir/logic.js +8 -25
- package/dist/mcp-server/tools/gitSetWorkingDir/registration.js +7 -7
- package/dist/mcp-server/tools/gitShow/logic.js +3 -19
- package/dist/mcp-server/tools/gitShow/registration.js +7 -7
- package/dist/mcp-server/tools/gitStash/logic.js +14 -30
- package/dist/mcp-server/tools/gitStash/registration.js +7 -7
- package/dist/mcp-server/tools/gitStatus/logic.js +3 -13
- package/dist/mcp-server/tools/gitStatus/registration.js +7 -7
- package/dist/mcp-server/tools/gitTag/logic.js +6 -25
- package/dist/mcp-server/tools/gitTag/registration.js +7 -7
- package/dist/mcp-server/tools/gitWorktree/logic.js +5 -21
- package/dist/mcp-server/tools/gitWorktree/registration.js +7 -7
- package/dist/mcp-server/tools/gitWrapupInstructions/logic.js +5 -7
- package/dist/mcp-server/tools/gitWrapupInstructions/registration.js +8 -8
- package/package.json +5 -5
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
* @module src/mcp-server/tools/gitStatus/registration
|
|
4
4
|
*/
|
|
5
5
|
import { ErrorHandler, logger, requestContextService } from "../../../utils/index.js";
|
|
6
|
-
import { McpError, BaseErrorCode } from "../../../types-global/errors.js";
|
|
7
6
|
import { getGitStatus, GitStatusInputSchema, GitStatusOutputSchema, } from "./logic.js";
|
|
8
7
|
const TOOL_NAME = "git_status";
|
|
9
8
|
const TOOL_DESCRIPTION = "Retrieves the status of a Git repository. Returns a JSON object detailing the current branch, cleanliness, and changes. Staged and unstaged changes are grouped by status (e.g., Added, Modified), alongside lists of untracked and conflicted files.";
|
|
@@ -45,18 +44,19 @@ export const registerGitStatusTool = async (server, getWorkingDirectory, getSess
|
|
|
45
44
|
}
|
|
46
45
|
catch (error) {
|
|
47
46
|
logger.error(`Error in ${TOOL_NAME} handler`, { error, ...handlerContext });
|
|
48
|
-
const
|
|
47
|
+
const mcpError = ErrorHandler.handleError(error, {
|
|
49
48
|
operation: `tool:${TOOL_NAME}`,
|
|
50
49
|
context: handlerContext,
|
|
51
50
|
input: params,
|
|
52
51
|
});
|
|
53
|
-
const mcpError = handledError instanceof McpError
|
|
54
|
-
? handledError
|
|
55
|
-
: new McpError(BaseErrorCode.INTERNAL_ERROR, "An unexpected error occurred.", { originalError: handledError });
|
|
56
52
|
return {
|
|
57
53
|
isError: true,
|
|
58
|
-
content: [{ type: "text", text: mcpError.message }],
|
|
59
|
-
structuredContent:
|
|
54
|
+
content: [{ type: "text", text: `Error: ${mcpError.message}` }],
|
|
55
|
+
structuredContent: {
|
|
56
|
+
code: mcpError.code,
|
|
57
|
+
message: mcpError.message,
|
|
58
|
+
details: mcpError.details,
|
|
59
|
+
},
|
|
60
60
|
};
|
|
61
61
|
}
|
|
62
62
|
});
|
|
@@ -63,30 +63,11 @@ export async function gitTagLogic(params, context) {
|
|
|
63
63
|
args.push("-d", params.tagName);
|
|
64
64
|
break;
|
|
65
65
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
return { success: true, mode: params.mode, tags };
|
|
72
|
-
}
|
|
73
|
-
return { success: true, mode: params.mode, message: `Tag '${params.tagName}' ${params.mode}d successfully.`, tagName: params.tagName };
|
|
74
|
-
}
|
|
75
|
-
catch (error) {
|
|
76
|
-
const errorMessage = error.stderr || error.message || "";
|
|
77
|
-
logger.error(`Failed to execute git tag command`, { ...context, operation, errorMessage });
|
|
78
|
-
if (errorMessage.toLowerCase().includes("not a git repository")) {
|
|
79
|
-
throw new McpError(BaseErrorCode.NOT_FOUND, `Path is not a Git repository: ${targetPath}`);
|
|
80
|
-
}
|
|
81
|
-
if (params.mode === "create" && errorMessage.toLowerCase().includes("already exists")) {
|
|
82
|
-
throw new McpError(BaseErrorCode.CONFLICT, `Tag '${params.tagName}' already exists.`);
|
|
83
|
-
}
|
|
84
|
-
if (params.mode === "delete" && errorMessage.toLowerCase().includes("not found")) {
|
|
85
|
-
throw new McpError(BaseErrorCode.NOT_FOUND, `Tag '${params.tagName}' not found.`);
|
|
86
|
-
}
|
|
87
|
-
if (params.mode === "create" && params.commitRef && /unknown revision or path not in the working tree/i.test(errorMessage)) {
|
|
88
|
-
throw new McpError(BaseErrorCode.NOT_FOUND, `Commit reference '${params.commitRef}' not found.`);
|
|
89
|
-
}
|
|
90
|
-
throw new McpError(BaseErrorCode.INTERNAL_ERROR, `Git tag ${params.mode} failed: ${errorMessage}`);
|
|
66
|
+
logger.debug(`Executing command: git ${args.join(" ")}`, { ...context, operation });
|
|
67
|
+
const { stdout } = await execFileAsync("git", args);
|
|
68
|
+
if (params.mode === 'list') {
|
|
69
|
+
const tags = stdout.trim().split("\n").filter(Boolean);
|
|
70
|
+
return { success: true, mode: params.mode, tags };
|
|
91
71
|
}
|
|
72
|
+
return { success: true, mode: params.mode, message: `Tag '${params.tagName}' ${params.mode}d successfully.`, tagName: params.tagName };
|
|
92
73
|
}
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
* @module src/mcp-server/tools/gitTag/registration
|
|
4
4
|
*/
|
|
5
5
|
import { ErrorHandler, logger, requestContextService } from "../../../utils/index.js";
|
|
6
|
-
import { McpError, BaseErrorCode } from "../../../types-global/errors.js";
|
|
7
6
|
import { gitTagLogic, GitTagInputSchema, GitTagOutputSchema, GitTagBaseSchema, } from "./logic.js";
|
|
8
7
|
const TOOL_NAME = "git_tag";
|
|
9
8
|
const TOOL_DESCRIPTION = "Manages Git tags. Supports listing existing tags, creating new lightweight or annotated tags against specific commits, and deleting local tags. Returns results as a JSON object.";
|
|
@@ -47,18 +46,19 @@ export const registerGitTagTool = async (server, getWorkingDirectory, getSession
|
|
|
47
46
|
}
|
|
48
47
|
catch (error) {
|
|
49
48
|
logger.error(`Error in ${TOOL_NAME} handler`, { error, ...handlerContext });
|
|
50
|
-
const
|
|
49
|
+
const mcpError = ErrorHandler.handleError(error, {
|
|
51
50
|
operation: `tool:${TOOL_NAME}`,
|
|
52
51
|
context: handlerContext,
|
|
53
52
|
input: params,
|
|
54
53
|
});
|
|
55
|
-
const mcpError = handledError instanceof McpError
|
|
56
|
-
? handledError
|
|
57
|
-
: new McpError(BaseErrorCode.INTERNAL_ERROR, "An unexpected error occurred.", { originalError: handledError });
|
|
58
54
|
return {
|
|
59
55
|
isError: true,
|
|
60
|
-
content: [{ type: "text", text: mcpError.message }],
|
|
61
|
-
structuredContent:
|
|
56
|
+
content: [{ type: "text", text: `Error: ${mcpError.message}` }],
|
|
57
|
+
structuredContent: {
|
|
58
|
+
code: mcpError.code,
|
|
59
|
+
message: mcpError.message,
|
|
60
|
+
details: mcpError.details,
|
|
61
|
+
},
|
|
62
62
|
};
|
|
63
63
|
}
|
|
64
64
|
});
|
|
@@ -129,26 +129,10 @@ export async function gitWorktreeLogic(params, context) {
|
|
|
129
129
|
return baseArgs;
|
|
130
130
|
};
|
|
131
131
|
const args = buildArgs();
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
return { success: true, mode: params.mode, worktrees: parsePorcelainWorktreeList(stdout) };
|
|
137
|
-
}
|
|
138
|
-
return { success: true, mode: params.mode, message: stdout.trim() || `Worktree ${params.mode} operation successful.` };
|
|
139
|
-
}
|
|
140
|
-
catch (error) {
|
|
141
|
-
const errorMessage = error.stderr || error.message || "";
|
|
142
|
-
logger.error(`Failed to execute git worktree command`, { ...context, operation, errorMessage });
|
|
143
|
-
if (errorMessage.toLowerCase().includes("not a git repository")) {
|
|
144
|
-
throw new McpError(BaseErrorCode.NOT_FOUND, `Path is not a Git repository: ${targetPath}`);
|
|
145
|
-
}
|
|
146
|
-
if (params.mode === "add" && errorMessage.includes("already exists")) {
|
|
147
|
-
throw new McpError(BaseErrorCode.CONFLICT, `Path '${params.worktreePath}' already exists or is a worktree.`);
|
|
148
|
-
}
|
|
149
|
-
if (params.mode === "remove" && errorMessage.includes("has unclean changes")) {
|
|
150
|
-
throw new McpError(BaseErrorCode.CONFLICT, `Worktree '${params.worktreePath}' has uncommitted changes. Use force=true to remove.`);
|
|
151
|
-
}
|
|
152
|
-
throw new McpError(BaseErrorCode.INTERNAL_ERROR, `Git worktree ${params.mode} failed: ${errorMessage}`);
|
|
132
|
+
logger.debug(`Executing command: git ${args.join(" ")}`, { ...context, operation });
|
|
133
|
+
const { stdout } = await execFileAsync("git", args);
|
|
134
|
+
if (params.mode === 'list' && params.verbose) {
|
|
135
|
+
return { success: true, mode: params.mode, worktrees: parsePorcelainWorktreeList(stdout) };
|
|
153
136
|
}
|
|
137
|
+
return { success: true, mode: params.mode, message: stdout.trim() || `Worktree ${params.mode} operation successful.` };
|
|
154
138
|
}
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
* @module src/mcp-server/tools/gitWorktree/registration
|
|
4
4
|
*/
|
|
5
5
|
import { ErrorHandler, logger, requestContextService } from "../../../utils/index.js";
|
|
6
|
-
import { McpError, BaseErrorCode } from "../../../types-global/errors.js";
|
|
7
6
|
import { gitWorktreeLogic, GitWorktreeInputSchema, GitWorktreeOutputSchema, GitWorktreeBaseSchema, } from "./logic.js";
|
|
8
7
|
const TOOL_NAME = "git_worktree";
|
|
9
8
|
const TOOL_DESCRIPTION = "Manages Git worktrees. Supports listing, adding, removing, moving, and pruning worktrees. Returns results as a JSON object.";
|
|
@@ -47,18 +46,19 @@ export const registerGitWorktreeTool = async (server, getWorkingDirectory, getSe
|
|
|
47
46
|
}
|
|
48
47
|
catch (error) {
|
|
49
48
|
logger.error(`Error in ${TOOL_NAME} handler`, { error, ...handlerContext });
|
|
50
|
-
const
|
|
49
|
+
const mcpError = ErrorHandler.handleError(error, {
|
|
51
50
|
operation: `tool:${TOOL_NAME}`,
|
|
52
51
|
context: handlerContext,
|
|
53
52
|
input: params,
|
|
54
53
|
});
|
|
55
|
-
const mcpError = handledError instanceof McpError
|
|
56
|
-
? handledError
|
|
57
|
-
: new McpError(BaseErrorCode.INTERNAL_ERROR, "An unexpected error occurred.", { originalError: handledError });
|
|
58
54
|
return {
|
|
59
55
|
isError: true,
|
|
60
|
-
content: [{ type: "text", text: mcpError.message }],
|
|
61
|
-
structuredContent:
|
|
56
|
+
content: [{ type: "text", text: `Error: ${mcpError.message}` }],
|
|
57
|
+
structuredContent: {
|
|
58
|
+
code: mcpError.code,
|
|
59
|
+
message: mcpError.message,
|
|
60
|
+
details: mcpError.details,
|
|
61
|
+
},
|
|
62
62
|
};
|
|
63
63
|
}
|
|
64
64
|
});
|
|
@@ -9,6 +9,7 @@ import { getGitStatus, GitStatusOutputSchema } from "../gitStatus/logic.js";
|
|
|
9
9
|
export const GitWrapupInstructionsInputSchema = z.object({
|
|
10
10
|
acknowledgement: z.enum(["Y", "y", "Yes", "yes"]).describe("Acknowledgement to initiate the wrap-up workflow."),
|
|
11
11
|
updateAgentMetaFiles: z.enum(["Y", "y", "Yes", "yes"]).optional().describe("Include an instruction to update agent-specific meta files."),
|
|
12
|
+
createTag: z.boolean().optional().describe("If true, instructs the agent to create a Git tag after committing all changes. Only set to true if given permission to do so."),
|
|
12
13
|
});
|
|
13
14
|
// 2. DEFINE the Zod response schema.
|
|
14
15
|
export const GitWrapupInstructionsOutputSchema = z.object({
|
|
@@ -37,17 +38,14 @@ export async function getWrapupInstructions(params, context) {
|
|
|
37
38
|
if (params.updateAgentMetaFiles) {
|
|
38
39
|
finalInstructions += `\nExtra request: review and update if needed the .clinerules and claude.md files if present.`;
|
|
39
40
|
}
|
|
41
|
+
if (params.createTag) {
|
|
42
|
+
finalInstructions += `\n5. After all changes are committed and confirmed via 'git_status', use the 'git_tag' tool to create a new annotated tag. The tag name should follow semantic versioning (e.g., v1.2.3), and the annotation message should summarize the key changes in this wrap-up.`;
|
|
43
|
+
}
|
|
40
44
|
let statusResult;
|
|
41
45
|
let statusError;
|
|
42
46
|
const workingDir = context.getWorkingDirectory();
|
|
43
47
|
if (workingDir) {
|
|
44
|
-
|
|
45
|
-
statusResult = await getGitStatus({ path: "." }, context);
|
|
46
|
-
}
|
|
47
|
-
catch (error) {
|
|
48
|
-
logger.warning(`Failed to get git status for wrapup instructions: ${error.message}`, { ...context, operation });
|
|
49
|
-
statusError = error.message;
|
|
50
|
-
}
|
|
48
|
+
statusResult = await getGitStatus({ path: "." }, context);
|
|
51
49
|
}
|
|
52
50
|
else {
|
|
53
51
|
statusError = "No working directory set for session, git status skipped.";
|
|
@@ -3,10 +3,9 @@
|
|
|
3
3
|
* @module src/mcp-server/tools/gitWrapupInstructions/registration
|
|
4
4
|
*/
|
|
5
5
|
import { ErrorHandler, logger, requestContextService } from "../../../utils/index.js";
|
|
6
|
-
import { McpError, BaseErrorCode } from "../../../types-global/errors.js";
|
|
7
6
|
import { getWrapupInstructions, GitWrapupInstructionsInputSchema, GitWrapupInstructionsOutputSchema, } from "./logic.js";
|
|
8
7
|
const TOOL_NAME = "git_wrapup_instructions";
|
|
9
|
-
const TOOL_DESCRIPTION = "Provides a standard Git wrap-up workflow. This involves reviewing changes with `git_diff`, updating documentation (README, CHANGELOG), and making logical, descriptive commits using the `git_commit` tool. The tool's response also includes the current `git status` output. You should set the working directory using `git_set_working_dir` before running this tool.";
|
|
8
|
+
const TOOL_DESCRIPTION = "Provides a standard Git wrap-up workflow. This involves reviewing changes with `git_diff`, updating documentation (README, CHANGELOG), and making logical, descriptive commits using the `git_commit` tool. Can optionally include instructions to create a Git tag after committing. The tool's response also includes the current `git status` output. You should set the working directory using `git_set_working_dir` before running this tool.";
|
|
10
9
|
/**
|
|
11
10
|
* Registers the git_wrapup_instructions tool with the MCP server instance.
|
|
12
11
|
* @param server The MCP server instance.
|
|
@@ -45,18 +44,19 @@ export const registerGitWrapupInstructionsTool = async (server, getWorkingDirect
|
|
|
45
44
|
}
|
|
46
45
|
catch (error) {
|
|
47
46
|
logger.error(`Error in ${TOOL_NAME} handler`, { error, ...handlerContext });
|
|
48
|
-
const
|
|
47
|
+
const mcpError = ErrorHandler.handleError(error, {
|
|
49
48
|
operation: `tool:${TOOL_NAME}`,
|
|
50
49
|
context: handlerContext,
|
|
51
50
|
input: params,
|
|
52
51
|
});
|
|
53
|
-
const mcpError = handledError instanceof McpError
|
|
54
|
-
? handledError
|
|
55
|
-
: new McpError(BaseErrorCode.INTERNAL_ERROR, "An unexpected error occurred.", { originalError: handledError });
|
|
56
52
|
return {
|
|
57
53
|
isError: true,
|
|
58
|
-
content: [{ type: "text", text: mcpError.message }],
|
|
59
|
-
structuredContent:
|
|
54
|
+
content: [{ type: "text", text: `Error: ${mcpError.message}` }],
|
|
55
|
+
structuredContent: {
|
|
56
|
+
code: mcpError.code,
|
|
57
|
+
message: mcpError.message,
|
|
58
|
+
details: mcpError.details,
|
|
59
|
+
},
|
|
60
60
|
};
|
|
61
61
|
}
|
|
62
62
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cyanheads/git-mcp-server",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.2",
|
|
4
4
|
"description": "An MCP (Model Context Protocol) server enabling LLMs and AI agents to interact with Git repositories. Provides tools for comprehensive Git operations including clone, commit, branch, diff, log, status, push, pull, merge, rebase, worktree, tag management, and more, via the MCP standard. STDIO & HTTP.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"files": [
|
|
@@ -35,16 +35,16 @@
|
|
|
35
35
|
"clean": "ts-node --esm scripts/clean.ts"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"@hono/node-server": "^1.
|
|
39
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
40
|
-
"@types/node": "^24.0.
|
|
38
|
+
"@hono/node-server": "^1.17.1",
|
|
39
|
+
"@modelcontextprotocol/sdk": "^1.16.0",
|
|
40
|
+
"@types/node": "^24.0.15",
|
|
41
41
|
"@types/sanitize-html": "^2.16.0",
|
|
42
42
|
"@types/validator": "^13.15.2",
|
|
43
43
|
"chrono-node": "2.8.0",
|
|
44
44
|
"dotenv": "16.6.1",
|
|
45
45
|
"hono": "^4.8.5",
|
|
46
46
|
"jose": "^6.0.12",
|
|
47
|
-
"openai": "^5.
|
|
47
|
+
"openai": "^5.10.1",
|
|
48
48
|
"partial-json": "^0.1.7",
|
|
49
49
|
"sanitize-html": "^2.17.0",
|
|
50
50
|
"tiktoken": "^1.0.21",
|