@cyanheads/git-mcp-server 2.1.7 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/mcp-server/server.js +69 -228
- package/dist/mcp-server/tools/gitAdd/index.js +2 -4
- package/dist/mcp-server/tools/gitAdd/logic.js +17 -74
- package/dist/mcp-server/tools/gitAdd/registration.js +38 -59
- package/dist/mcp-server/tools/gitBranch/index.js +3 -5
- package/dist/mcp-server/tools/gitBranch/logic.js +118 -296
- package/dist/mcp-server/tools/gitBranch/registration.js +52 -66
- package/dist/mcp-server/tools/gitCheckout/index.js +2 -3
- package/dist/mcp-server/tools/gitCheckout/logic.js +47 -122
- package/dist/mcp-server/tools/gitCheckout/registration.js +53 -72
- package/dist/mcp-server/tools/gitCherryPick/index.js +3 -5
- package/dist/mcp-server/tools/gitCherryPick/logic.js +55 -162
- package/dist/mcp-server/tools/gitCherryPick/registration.js +52 -67
- package/dist/mcp-server/tools/gitClean/index.js +3 -5
- package/dist/mcp-server/tools/gitClean/logic.js +44 -143
- package/dist/mcp-server/tools/gitClean/registration.js +52 -92
- package/dist/mcp-server/tools/gitClearWorkingDir/index.js +3 -5
- package/dist/mcp-server/tools/gitClearWorkingDir/logic.js +19 -26
- package/dist/mcp-server/tools/gitClearWorkingDir/registration.js +55 -73
- package/dist/mcp-server/tools/gitClone/index.js +2 -4
- package/dist/mcp-server/tools/gitClone/logic.js +50 -171
- package/dist/mcp-server/tools/gitClone/registration.js +51 -42
- package/dist/mcp-server/tools/gitCommit/index.js +2 -4
- package/dist/mcp-server/tools/gitCommit/logic.js +90 -295
- package/dist/mcp-server/tools/gitCommit/registration.js +52 -73
- package/dist/mcp-server/tools/gitDiff/index.js +2 -3
- package/dist/mcp-server/tools/gitDiff/logic.js +78 -254
- package/dist/mcp-server/tools/gitDiff/registration.js +53 -68
- package/dist/mcp-server/tools/gitFetch/index.js +2 -3
- package/dist/mcp-server/tools/gitFetch/logic.js +47 -129
- package/dist/mcp-server/tools/gitFetch/registration.js +54 -66
- package/dist/mcp-server/tools/gitInit/index.js +3 -5
- package/dist/mcp-server/tools/gitInit/logic.js +46 -152
- package/dist/mcp-server/tools/gitInit/registration.js +52 -104
- package/dist/mcp-server/tools/gitLog/index.js +2 -3
- package/dist/mcp-server/tools/gitLog/logic.js +75 -257
- package/dist/mcp-server/tools/gitLog/registration.js +54 -66
- package/dist/mcp-server/tools/gitMerge/index.js +3 -5
- package/dist/mcp-server/tools/gitMerge/logic.js +52 -179
- package/dist/mcp-server/tools/gitMerge/registration.js +52 -71
- package/dist/mcp-server/tools/gitPull/index.js +2 -3
- package/dist/mcp-server/tools/gitPull/logic.js +48 -146
- package/dist/mcp-server/tools/gitPull/registration.js +53 -75
- package/dist/mcp-server/tools/gitPush/index.js +2 -3
- package/dist/mcp-server/tools/gitPush/logic.js +73 -181
- package/dist/mcp-server/tools/gitPush/registration.js +53 -75
- package/dist/mcp-server/tools/gitRebase/index.js +3 -5
- package/dist/mcp-server/tools/gitRebase/logic.js +73 -202
- package/dist/mcp-server/tools/gitRebase/registration.js +52 -70
- package/dist/mcp-server/tools/gitRemote/index.js +3 -5
- package/dist/mcp-server/tools/gitRemote/logic.js +85 -193
- package/dist/mcp-server/tools/gitRemote/registration.js +52 -65
- package/dist/mcp-server/tools/gitReset/index.js +2 -3
- package/dist/mcp-server/tools/gitReset/logic.js +37 -121
- package/dist/mcp-server/tools/gitReset/registration.js +53 -60
- package/dist/mcp-server/tools/gitSetWorkingDir/index.js +3 -5
- package/dist/mcp-server/tools/gitSetWorkingDir/logic.js +45 -133
- package/dist/mcp-server/tools/gitSetWorkingDir/registration.js +55 -85
- package/dist/mcp-server/tools/gitShow/index.js +3 -5
- package/dist/mcp-server/tools/gitShow/logic.js +33 -122
- package/dist/mcp-server/tools/gitShow/registration.js +52 -74
- package/dist/mcp-server/tools/gitStash/index.js +3 -5
- package/dist/mcp-server/tools/gitStash/logic.js +70 -214
- package/dist/mcp-server/tools/gitStash/registration.js +52 -77
- package/dist/mcp-server/tools/gitStatus/index.js +2 -4
- package/dist/mcp-server/tools/gitStatus/logic.js +82 -229
- package/dist/mcp-server/tools/gitStatus/registration.js +52 -66
- package/dist/mcp-server/tools/gitTag/index.js +3 -5
- package/dist/mcp-server/tools/gitTag/logic.js +66 -188
- package/dist/mcp-server/tools/gitTag/registration.js +54 -73
- package/dist/mcp-server/tools/gitWorktree/index.js +3 -5
- package/dist/mcp-server/tools/gitWorktree/logic.js +112 -322
- package/dist/mcp-server/tools/gitWorktree/registration.js +54 -58
- package/dist/mcp-server/tools/gitWrapupInstructions/index.js +5 -3
- package/dist/mcp-server/tools/gitWrapupInstructions/logic.js +26 -38
- package/dist/mcp-server/tools/gitWrapupInstructions/registration.js +54 -70
- package/dist/mcp-server/transports/httpTransport.js +2 -3
- package/package.json +12 -12
|
@@ -1,175 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Defines the core logic, schemas, and types for the git_init tool.
|
|
3
|
+
* @module src/mcp-server/tools/gitInit/logic
|
|
4
|
+
*/
|
|
1
5
|
import { execFile } from "child_process";
|
|
2
6
|
import fs from "fs/promises";
|
|
3
7
|
import path from "path";
|
|
4
8
|
import { promisify } from "util";
|
|
5
9
|
import { z } from "zod";
|
|
6
|
-
|
|
7
|
-
import {
|
|
8
|
-
// Import utils from barrel (RequestContext from ../utils/internal/requestContext.js)
|
|
9
|
-
import { BaseErrorCode, McpError } from "../../../types-global/errors.js"; // Keep direct import for types-global
|
|
10
|
-
// Import utils from barrel (sanitization from ../utils/security/sanitization.js)
|
|
11
|
-
import { sanitization } from "../../../utils/index.js";
|
|
10
|
+
import { logger, sanitization } from "../../../utils/index.js";
|
|
11
|
+
import { McpError, BaseErrorCode } from "../../../types-global/errors.js";
|
|
12
12
|
const execFileAsync = promisify(execFile);
|
|
13
|
-
//
|
|
13
|
+
// 1. DEFINE the Zod input schema.
|
|
14
14
|
export const GitInitInputSchema = z.object({
|
|
15
|
-
path: z
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
.boolean()
|
|
27
|
-
.default(false)
|
|
28
|
-
.describe("Create a bare repository (no working directory)."),
|
|
29
|
-
quiet: z
|
|
30
|
-
.boolean()
|
|
31
|
-
.default(false)
|
|
32
|
-
.describe("Only print error and warning messages; all other output will be suppressed."),
|
|
15
|
+
path: z.string().default(".").describe("Path where the new Git repository should be initialized."),
|
|
16
|
+
initialBranch: z.string().optional().describe("The name for the initial branch (e.g., 'main')."),
|
|
17
|
+
bare: z.boolean().default(false).describe("Create a bare repository with no working directory."),
|
|
18
|
+
quiet: z.boolean().default(false).describe("Suppress all output except for errors and warnings."),
|
|
19
|
+
});
|
|
20
|
+
// 2. DEFINE the Zod response schema.
|
|
21
|
+
export const GitInitOutputSchema = z.object({
|
|
22
|
+
success: z.boolean().describe("Indicates if the command was successful."),
|
|
23
|
+
message: z.string().describe("A summary message of the result."),
|
|
24
|
+
path: z.string().describe("The path where the repository was initialized."),
|
|
25
|
+
gitDirExists: z.boolean().describe("Confirms the .git directory was created."),
|
|
33
26
|
});
|
|
34
27
|
/**
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* @param {GitInitInput} input - The validated input object.
|
|
38
|
-
* @param {RequestContext} context - The request context for logging and error handling.
|
|
39
|
-
* @returns {Promise<GitInitResult>} A promise that resolves with the structured init result.
|
|
40
|
-
* @throws {McpError} Throws an McpError if path validation fails or the git command fails unexpectedly.
|
|
28
|
+
* 4. IMPLEMENT the core logic function.
|
|
29
|
+
* @throws {McpError} If the logic encounters an unrecoverable issue.
|
|
41
30
|
*/
|
|
42
|
-
export async function gitInitLogic(
|
|
31
|
+
export async function gitInitLogic(params, context) {
|
|
43
32
|
const operation = "gitInitLogic";
|
|
44
|
-
logger.debug(`Executing ${operation}`, { ...context,
|
|
45
|
-
|
|
33
|
+
logger.debug(`Executing ${operation}`, { ...context, params });
|
|
34
|
+
const targetPath = sanitization.sanitizePath(params.path, { allowAbsolute: true }).sanitizedPath;
|
|
35
|
+
const parentDir = path.dirname(targetPath);
|
|
46
36
|
try {
|
|
47
|
-
|
|
48
|
-
targetPath = sanitization.sanitizePath(input.path, {
|
|
49
|
-
allowAbsolute: true,
|
|
50
|
-
}).sanitizedPath;
|
|
51
|
-
logger.debug("Sanitized path", {
|
|
52
|
-
...context,
|
|
53
|
-
operation,
|
|
54
|
-
sanitizedPath: targetPath,
|
|
55
|
-
});
|
|
56
|
-
// Ensure the target directory exists before trying to init inside it
|
|
57
|
-
// git init creates the directory if it doesn't exist, but we might want to ensure the parent exists
|
|
58
|
-
const parentDir = path.dirname(targetPath);
|
|
59
|
-
try {
|
|
60
|
-
await fs.access(parentDir, fs.constants.W_OK); // Check write access in parent
|
|
61
|
-
}
|
|
62
|
-
catch (accessError) {
|
|
63
|
-
logger.error(`Parent directory check failed for ${targetPath}`, {
|
|
64
|
-
...context,
|
|
65
|
-
operation,
|
|
66
|
-
error: accessError.message,
|
|
67
|
-
});
|
|
68
|
-
if (accessError.code === "ENOENT") {
|
|
69
|
-
throw new McpError(BaseErrorCode.VALIDATION_ERROR, `Parent directory does not exist: ${parentDir}`, { context, operation });
|
|
70
|
-
}
|
|
71
|
-
throw new McpError(BaseErrorCode.VALIDATION_ERROR, `Cannot access parent directory: ${parentDir}. Error: ${accessError.message}`, { context, operation });
|
|
72
|
-
}
|
|
37
|
+
await fs.access(parentDir, fs.constants.W_OK);
|
|
73
38
|
}
|
|
74
39
|
catch (error) {
|
|
75
|
-
|
|
76
|
-
...context,
|
|
77
|
-
operation,
|
|
78
|
-
error,
|
|
79
|
-
});
|
|
80
|
-
if (error instanceof McpError)
|
|
81
|
-
throw error;
|
|
82
|
-
throw new McpError(BaseErrorCode.VALIDATION_ERROR, `Invalid path: ${error instanceof Error ? error.message : String(error)}`, { context, operation, originalError: error });
|
|
40
|
+
throw new McpError(BaseErrorCode.VALIDATION_ERROR, `Cannot access parent directory: ${parentDir}`);
|
|
83
41
|
}
|
|
42
|
+
const args = ["init"];
|
|
43
|
+
if (params.quiet)
|
|
44
|
+
args.push("--quiet");
|
|
45
|
+
if (params.bare)
|
|
46
|
+
args.push("--bare");
|
|
47
|
+
args.push(`--initial-branch=${params.initialBranch || 'main'}`);
|
|
48
|
+
args.push(targetPath);
|
|
84
49
|
try {
|
|
85
|
-
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
args.push("--bare");
|
|
92
|
-
}
|
|
93
|
-
// Determine the initial branch name, defaulting to 'main' if not provided
|
|
94
|
-
const branchNameToUse = input.initialBranch || "main";
|
|
95
|
-
args.push("-b", branchNameToUse);
|
|
96
|
-
// Add the target directory path at the end
|
|
97
|
-
args.push(targetPath);
|
|
98
|
-
logger.debug(`Executing command: git ${args.join(" ")}`, {
|
|
99
|
-
...context,
|
|
100
|
-
operation,
|
|
101
|
-
});
|
|
102
|
-
const { stdout, stderr } = await execFileAsync("git", args);
|
|
103
|
-
if (stderr && !input.quiet) {
|
|
104
|
-
// Log stderr as warning but proceed, as init might still succeed (e.g., reinitializing)
|
|
105
|
-
logger.warning(`Git init command produced stderr`, {
|
|
106
|
-
...context,
|
|
107
|
-
operation,
|
|
108
|
-
stderr,
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
if (stdout && !input.quiet) {
|
|
112
|
-
// Log stdout at debug level for cleaner info logs
|
|
113
|
-
logger.debug(`Git init command produced stdout`, {
|
|
114
|
-
...context,
|
|
115
|
-
operation,
|
|
116
|
-
stdout,
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
// Verify .git directory exists (or equivalent for bare repo)
|
|
120
|
-
const gitDirPath = input.bare ? targetPath : path.join(targetPath, ".git");
|
|
121
|
-
let gitDirExists = false;
|
|
122
|
-
try {
|
|
123
|
-
await fs.access(gitDirPath);
|
|
124
|
-
gitDirExists = true;
|
|
125
|
-
}
|
|
126
|
-
catch (e) {
|
|
127
|
-
logger.warning(`Could not verify existence of ${gitDirPath} after git init`, { ...context, operation });
|
|
128
|
-
}
|
|
129
|
-
const successMessage = `Successfully initialized Git repository in ${targetPath}`;
|
|
130
|
-
logger.info(successMessage, {
|
|
131
|
-
...context,
|
|
132
|
-
operation,
|
|
133
|
-
path: targetPath,
|
|
134
|
-
bare: input.bare,
|
|
135
|
-
initialBranch: input.initialBranch || "default",
|
|
136
|
-
});
|
|
137
|
-
return {
|
|
138
|
-
success: true,
|
|
139
|
-
message: stdout.trim() || successMessage, // Return stdout to user if available
|
|
140
|
-
path: targetPath,
|
|
141
|
-
gitDirExists: gitDirExists,
|
|
142
|
-
};
|
|
50
|
+
logger.debug(`Executing command: git ${args.join(" ")}`, { ...context, operation });
|
|
51
|
+
const { stdout } = await execFileAsync("git", args);
|
|
52
|
+
const gitDirPath = params.bare ? targetPath : path.join(targetPath, ".git");
|
|
53
|
+
const gitDirExists = await fs.access(gitDirPath).then(() => true).catch(() => false);
|
|
54
|
+
const successMessage = stdout.trim() || `Successfully initialized Git repository in ${targetPath}`;
|
|
55
|
+
return { success: true, message: successMessage, path: targetPath, gitDirExists };
|
|
143
56
|
}
|
|
144
57
|
catch (error) {
|
|
145
58
|
const errorMessage = error.stderr || error.message || "";
|
|
146
|
-
logger.error(`Failed to execute git init command`, {
|
|
147
|
-
...context,
|
|
148
|
-
operation,
|
|
149
|
-
path: targetPath,
|
|
150
|
-
error: errorMessage,
|
|
151
|
-
stderr: error.stderr,
|
|
152
|
-
stdout: error.stdout,
|
|
153
|
-
});
|
|
154
|
-
// Handle specific error cases
|
|
155
|
-
if (errorMessage.toLowerCase().includes("already exists") &&
|
|
156
|
-
errorMessage.toLowerCase().includes("git repository")) {
|
|
157
|
-
// Reinitializing is often okay, treat as success but mention it.
|
|
158
|
-
logger.info(`Repository already exists, reinitialized: ${targetPath}`, {
|
|
159
|
-
...context,
|
|
160
|
-
operation,
|
|
161
|
-
});
|
|
162
|
-
return {
|
|
163
|
-
success: true, // Treat reinitialization as success
|
|
164
|
-
message: `Reinitialized existing Git repository in ${targetPath}`,
|
|
165
|
-
path: targetPath,
|
|
166
|
-
gitDirExists: true, // Assume it exists if reinit message appears
|
|
167
|
-
};
|
|
168
|
-
}
|
|
59
|
+
logger.error(`Failed to execute git init command`, { ...context, operation, errorMessage });
|
|
169
60
|
if (errorMessage.toLowerCase().includes("permission denied")) {
|
|
170
|
-
throw new McpError(BaseErrorCode.FORBIDDEN, `Permission denied to initialize repository at: ${targetPath}
|
|
61
|
+
throw new McpError(BaseErrorCode.FORBIDDEN, `Permission denied to initialize repository at: ${targetPath}`);
|
|
62
|
+
}
|
|
63
|
+
// Re-initializing is not an error, so we check for it and return a success response.
|
|
64
|
+
if (errorMessage.toLowerCase().includes("reinitialized existing git repository")) {
|
|
65
|
+
return { success: true, message: `Reinitialized existing Git repository in ${targetPath}`, path: targetPath, gitDirExists: true };
|
|
171
66
|
}
|
|
172
|
-
|
|
173
|
-
throw new McpError(BaseErrorCode.INTERNAL_ERROR, `Failed to initialize repository at: ${targetPath}. Error: ${errorMessage}`, { context, operation, originalError: error });
|
|
67
|
+
throw new McpError(BaseErrorCode.INTERNAL_ERROR, `Failed to initialize repository: ${errorMessage}`);
|
|
174
68
|
}
|
|
175
69
|
}
|
|
@@ -1,112 +1,60 @@
|
|
|
1
|
-
import path from "path";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
import { BaseErrorCode, McpError } from "../../../types-global/errors.js";
|
|
4
|
-
import { ErrorHandler, logger, requestContextService, sanitization, } from "../../../utils/index.js";
|
|
5
|
-
import { GitInitInputSchema, gitInitLogic, } from "./logic.js";
|
|
6
|
-
const TOOL_NAME = "git_init";
|
|
7
|
-
const TOOL_DESCRIPTION = "Initializes a new Git repository at the specified path. If path is relative or omitted, it resolves against the session working directory (if you have set the git_working_dir). Can optionally set the initial branch name and create a bare repository.";
|
|
8
|
-
const RegistrationSchema = GitInitInputSchema.extend({
|
|
9
|
-
path: z.string().min(1).optional().default("."),
|
|
10
|
-
}).shape;
|
|
11
|
-
// --- Module-level State Accessors ---
|
|
12
|
-
// These will be populated by the initialize function called from server.ts
|
|
13
|
-
let _getWorkingDirectory = () => undefined;
|
|
14
|
-
let _getSessionIdFromContext = () => undefined;
|
|
15
1
|
/**
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* with a way to access session-specific state (like the working directory)
|
|
19
|
-
* without needing direct access to the server or transport layer internals.
|
|
20
|
-
*
|
|
21
|
-
* @param getWorkingDirectory - Function to retrieve the working directory for a given session ID.
|
|
22
|
-
* @param getSessionIdFromContext - Function to extract the session ID from a tool's execution context.
|
|
2
|
+
* @fileoverview Handles registration and error handling for the git_init tool.
|
|
3
|
+
* @module src/mcp-server/tools/gitInit/registration
|
|
23
4
|
*/
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
5
|
+
import { ErrorHandler, logger, requestContextService } from "../../../utils/index.js";
|
|
6
|
+
import { McpError, BaseErrorCode } from "../../../types-global/errors.js";
|
|
7
|
+
import { gitInitLogic, GitInitInputSchema, GitInitOutputSchema, } from "./logic.js";
|
|
8
|
+
const TOOL_NAME = "git_init";
|
|
9
|
+
const TOOL_DESCRIPTION = "Initializes a new Git repository at the specified path. If path is relative or omitted, it resolves against the session working directory (if you have set the git_working_dir). Can optionally set the initial branch name and create a bare repository.";
|
|
29
10
|
/**
|
|
30
|
-
* Registers the git_init tool with the MCP server.
|
|
31
|
-
*
|
|
32
|
-
* @param
|
|
33
|
-
* @returns {Promise<void>}
|
|
34
|
-
* @throws {Error} If registration fails.
|
|
11
|
+
* Registers the git_init tool with the MCP server instance.
|
|
12
|
+
* @param server The MCP server instance.
|
|
13
|
+
* @param getSessionId Function to get the session ID from context.
|
|
35
14
|
*/
|
|
36
|
-
export const registerGitInitTool = async (server) => {
|
|
15
|
+
export const registerGitInitTool = async (server, getSessionId) => {
|
|
37
16
|
const operation = "registerGitInitTool";
|
|
38
17
|
const context = requestContextService.createRequestContext({ operation });
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
logger.info(`Executing tool: ${TOOL_NAME}`, requestContext);
|
|
55
|
-
return await ErrorHandler.tryCatch(async () => {
|
|
56
|
-
// Use the initialized accessor to get the working directory
|
|
57
|
-
const sessionWorkingDirectory = _getWorkingDirectory(sessionId);
|
|
58
|
-
const inputPath = validatedArgs.path;
|
|
59
|
-
let resolvedPath;
|
|
60
|
-
try {
|
|
61
|
-
if (path.isAbsolute(inputPath)) {
|
|
62
|
-
resolvedPath = sanitization.sanitizePath(inputPath, {
|
|
63
|
-
allowAbsolute: true,
|
|
64
|
-
}).sanitizedPath;
|
|
65
|
-
logger.debug(`Using absolute path: ${resolvedPath}`, requestContext);
|
|
66
|
-
}
|
|
67
|
-
else if (sessionWorkingDirectory) {
|
|
68
|
-
resolvedPath = sanitization.sanitizePath(path.resolve(sessionWorkingDirectory, inputPath), { allowAbsolute: true }).sanitizedPath;
|
|
69
|
-
logger.debug(`Resolved relative path '${inputPath}' to absolute path: ${resolvedPath} using session CWD`, requestContext);
|
|
70
|
-
}
|
|
71
|
-
else {
|
|
72
|
-
// This case should now only be hit if the path is relative AND there's no session CWD set.
|
|
73
|
-
logger.error(`Relative path '${inputPath}' provided but no session working directory is set.`, requestContext);
|
|
74
|
-
throw new McpError(BaseErrorCode.VALIDATION_ERROR, `Relative path '${inputPath}' provided but no session working directory is set. Please provide an absolute path or set a working directory using git_set_working_dir.`, { context: requestContext, operation: toolOperation });
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
catch (error) {
|
|
78
|
-
logger.error("Path resolution or sanitization failed", {
|
|
79
|
-
...requestContext,
|
|
80
|
-
operation: toolOperation,
|
|
81
|
-
error,
|
|
82
|
-
});
|
|
83
|
-
if (error instanceof McpError)
|
|
84
|
-
throw error;
|
|
85
|
-
throw new McpError(BaseErrorCode.VALIDATION_ERROR, `Invalid path processing: ${error instanceof Error ? error.message : String(error)}`, {
|
|
86
|
-
context: requestContext,
|
|
87
|
-
operation: toolOperation,
|
|
88
|
-
originalError: error,
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
const logicArgs = {
|
|
92
|
-
...validatedArgs,
|
|
93
|
-
path: resolvedPath,
|
|
94
|
-
};
|
|
95
|
-
const initResult = await gitInitLogic(logicArgs, requestContext);
|
|
96
|
-
const resultContent = {
|
|
97
|
-
type: "text",
|
|
98
|
-
text: JSON.stringify(initResult, null, 2), // Pretty-print JSON
|
|
99
|
-
contentType: "application/json",
|
|
100
|
-
};
|
|
101
|
-
logger.info(`Tool ${TOOL_NAME} executed successfully, returning JSON`, requestContext);
|
|
102
|
-
return { content: [resultContent] };
|
|
103
|
-
}, {
|
|
104
|
-
operation: toolOperation,
|
|
105
|
-
context: requestContext,
|
|
106
|
-
input: validatedArgs,
|
|
107
|
-
errorCode: BaseErrorCode.INTERNAL_ERROR,
|
|
108
|
-
});
|
|
18
|
+
server.registerTool(TOOL_NAME, {
|
|
19
|
+
title: "Git Initialize",
|
|
20
|
+
description: TOOL_DESCRIPTION,
|
|
21
|
+
inputSchema: GitInitInputSchema.shape,
|
|
22
|
+
outputSchema: GitInitOutputSchema.shape,
|
|
23
|
+
annotations: {
|
|
24
|
+
readOnlyHint: false,
|
|
25
|
+
destructiveHint: true, // Creates a .git directory
|
|
26
|
+
idempotentHint: true, // Re-initializing is idempotent
|
|
27
|
+
openWorldHint: false,
|
|
28
|
+
},
|
|
29
|
+
}, async (params, callContext) => {
|
|
30
|
+
const handlerContext = requestContextService.createRequestContext({
|
|
31
|
+
toolName: TOOL_NAME,
|
|
32
|
+
parentContext: callContext,
|
|
109
33
|
});
|
|
110
|
-
|
|
111
|
-
|
|
34
|
+
try {
|
|
35
|
+
// The logic function now handles path resolution.
|
|
36
|
+
const result = await gitInitLogic(params, handlerContext);
|
|
37
|
+
return {
|
|
38
|
+
structuredContent: result,
|
|
39
|
+
content: [{ type: "text", text: `Success: ${JSON.stringify(result, null, 2)}` }],
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
logger.error(`Error in ${TOOL_NAME} handler`, { error, ...handlerContext });
|
|
44
|
+
const handledError = ErrorHandler.handleError(error, {
|
|
45
|
+
operation: `tool:${TOOL_NAME}`,
|
|
46
|
+
context: handlerContext,
|
|
47
|
+
input: params,
|
|
48
|
+
});
|
|
49
|
+
const mcpError = handledError instanceof McpError
|
|
50
|
+
? handledError
|
|
51
|
+
: new McpError(BaseErrorCode.INTERNAL_ERROR, "An unexpected error occurred.", { originalError: handledError });
|
|
52
|
+
return {
|
|
53
|
+
isError: true,
|
|
54
|
+
content: [{ type: "text", text: mcpError.message }],
|
|
55
|
+
structuredContent: mcpError.details,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
logger.info(`Tool '${TOOL_NAME}' registered successfully.`, context);
|
|
112
60
|
};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileoverview Barrel file for the gitLog tool.
|
|
3
|
+
* @module src/mcp-server/tools/gitLog/index
|
|
3
4
|
*/
|
|
4
|
-
export { registerGitLogTool
|
|
5
|
-
// Export types if needed elsewhere, e.g.:
|
|
6
|
-
// export type { GitLogInput, GitLogResult } from './logic.js';
|
|
5
|
+
export { registerGitLogTool } from "./registration.js";
|