@cyanheads/git-mcp-server 2.1.4 → 2.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.
@@ -1,9 +1,9 @@
1
- import { exec } from "child_process";
1
+ import { execFile } from "child_process";
2
2
  import { promisify } from "util";
3
3
  import { z } from "zod";
4
4
  import { BaseErrorCode, McpError } from "../../../types-global/errors.js"; // Direct import for types-global
5
5
  import { logger, sanitization } from "../../../utils/index.js"; // logger (./utils/internal/logger.js), RequestContext (./utils/internal/requestContext.js), sanitization (./utils/security/sanitization.js)
6
- const execAsync = promisify(exec);
6
+ const execFileAsync = promisify(execFile);
7
7
  // Define the reset modes
8
8
  const ResetModeEnum = z.enum(["soft", "mixed", "hard", "merge", "keep"]);
9
9
  // Define the input schema for the git_reset tool using Zod
@@ -73,24 +73,25 @@ export async function resetGitState(input, context) {
73
73
  throw error;
74
74
  throw new McpError(BaseErrorCode.VALIDATION_ERROR, `Invalid path: ${error instanceof Error ? error.message : String(error)}`, { context, operation, originalError: error });
75
75
  }
76
- // Basic sanitization for commit ref
77
- const safeCommit = input.commit?.replace(/[`$&;*()|<>]/g, "");
78
76
  try {
79
77
  // Construct the git reset command
80
- let command = `git -C "${targetPath}" reset`;
78
+ const args = ["-C", targetPath, "reset"];
81
79
  if (input.mode) {
82
- command += ` --${input.mode}`;
80
+ args.push(`--${input.mode}`);
83
81
  }
84
- if (safeCommit) {
85
- command += ` ${safeCommit}`;
82
+ if (input.commit) {
83
+ args.push(input.commit);
86
84
  }
87
85
  // Handling file paths requires careful command construction, often without a commit ref.
88
86
  // Example: `git reset HEAD -- path/to/file` or `git reset -- path/to/file` (unstages)
89
87
  // For simplicity, this initial version focuses on resetting the whole HEAD/index/tree.
90
88
  // Add file path logic here if needed, adjusting command structure.
91
- logger.debug(`Executing command: ${command}`, { ...context, operation });
89
+ logger.debug(`Executing command: git ${args.join(" ")}`, {
90
+ ...context,
91
+ operation,
92
+ });
92
93
  // Execute command. Reset output is often minimal on success, but stderr might indicate issues.
93
- const { stdout, stderr } = await execAsync(command);
94
+ const { stdout, stderr } = await execFileAsync("git", args);
94
95
  logger.debug(`Git reset stdout: ${stdout}`, { ...context, operation });
95
96
  if (stderr) {
96
97
  // Log stderr as info, as it often contains the primary status message
@@ -1,10 +1,10 @@
1
- import { exec } from "child_process";
1
+ import { execFile } from "child_process";
2
2
  import fs from "fs/promises";
3
3
  import { promisify } from "util";
4
4
  import { z } from "zod";
5
5
  import { BaseErrorCode, McpError } from "../../../types-global/errors.js"; // Direct import for types-global
6
6
  import { logger, sanitization } from "../../../utils/index.js"; // RequestContext (./utils/internal/requestContext.js), logger (./utils/internal/logger.js), sanitization (./utils/security/sanitization.js)
7
- const execAsync = promisify(exec);
7
+ const execFileAsync = promisify(execFile);
8
8
  // Define the Zod schema for input validation
9
9
  export const GitSetWorkingDirInputSchema = z.object({
10
10
  path: z
@@ -70,7 +70,7 @@ export async function gitSetWorkingDirLogic(input, context) {
70
70
  let isGitRepo = false;
71
71
  let initializedRepo = false;
72
72
  try {
73
- const { stdout } = await execAsync("git rev-parse --is-inside-work-tree", {
73
+ const { stdout } = await execFileAsync("git", ["rev-parse", "--is-inside-work-tree"], {
74
74
  cwd: sanitizedPath,
75
75
  });
76
76
  if (stdout.trim() === "true") {
@@ -94,7 +94,9 @@ export async function gitSetWorkingDirLogic(input, context) {
94
94
  if (!isGitRepo && input.initializeIfNotPresent) {
95
95
  logger.info(`Path is not a Git repository. Attempting to initialize (initializeIfNotPresent=true) with initial branch 'main'.`, { ...context, operation, path: sanitizedPath });
96
96
  try {
97
- await execAsync("git init --initial-branch=main", { cwd: sanitizedPath });
97
+ await execFileAsync("git", ["init", "--initial-branch=main"], {
98
+ cwd: sanitizedPath,
99
+ });
98
100
  initializedRepo = true;
99
101
  isGitRepo = true; // Now it is a git repo
100
102
  logger.info('Successfully initialized Git repository with initial branch "main".', { ...context, operation, path: sanitizedPath });
@@ -1,9 +1,9 @@
1
- import { exec } from "child_process";
1
+ import { execFile } from "child_process";
2
2
  import { promisify } from "util";
3
3
  import { z } from "zod";
4
4
  import { BaseErrorCode, McpError } from "../../../types-global/errors.js"; // Direct import for types-global
5
5
  import { logger, sanitization } from "../../../utils/index.js"; // logger (./utils/internal/logger.js), RequestContext (./utils/internal/requestContext.js), sanitization (./utils/security/sanitization.js)
6
- const execAsync = promisify(exec);
6
+ const execFileAsync = promisify(execFile);
7
7
  // Define the input schema for the git_show tool using Zod
8
8
  // No refinements needed here, so we don't need a separate BaseSchema
9
9
  export const GitShowInputSchema = z.object({
@@ -89,14 +89,17 @@ export async function gitShowLogic(input, context) {
89
89
  try {
90
90
  // Construct the refspec, combining ref and filePath if needed
91
91
  const refSpec = input.filePath
92
- ? `${input.ref}:"${input.filePath}"`
93
- : `"${input.ref}"`;
92
+ ? `${input.ref}:${input.filePath}`
93
+ : input.ref;
94
94
  // Construct the command
95
- const command = `git -C "${targetPath}" show ${refSpec}`;
96
- logger.debug(`Executing command: ${command}`, { ...context, operation });
95
+ const args = ["-C", targetPath, "show", refSpec];
96
+ logger.debug(`Executing command: git ${args.join(" ")}`, {
97
+ ...context,
98
+ operation,
99
+ });
97
100
  // Execute command. Note: git show might write to stderr for non-error info (like commit details before diff)
98
101
  // We primarily care about stdout for the content. Errors usually have non-zero exit code.
99
- const { stdout, stderr } = await execAsync(command);
102
+ const { stdout, stderr } = await execFileAsync("git", args);
100
103
  if (stderr) {
101
104
  // Log stderr as debug info, as it might contain commit details etc.
102
105
  logger.debug(`Git show command produced stderr (may be informational)`, {
@@ -1,9 +1,9 @@
1
- import { exec } from "child_process";
1
+ import { execFile } from "child_process";
2
2
  import { promisify } from "util";
3
3
  import { z } from "zod";
4
4
  import { BaseErrorCode, McpError } from "../../../types-global/errors.js"; // Direct import for types-global
5
5
  import { logger, sanitization } from "../../../utils/index.js"; // logger (./utils/internal/logger.js), RequestContext (./utils/internal/requestContext.js), sanitization (./utils/security/sanitization.js)
6
- const execAsync = promisify(exec);
6
+ const execFileAsync = promisify(execFile);
7
7
  // Define the BASE input schema for the git_stash tool using Zod
8
8
  export const GitStashBaseSchema = z.object({
9
9
  path: z
@@ -90,16 +90,16 @@ export async function gitStashLogic(input, context) {
90
90
  throw new McpError(BaseErrorCode.VALIDATION_ERROR, `Invalid stash reference format: ${input.stashRef}. Expected format: stash@{n}`, { context, operation });
91
91
  }
92
92
  try {
93
- let command;
93
+ let args;
94
94
  let result;
95
95
  switch (input.mode) {
96
96
  case "list":
97
- command = `git -C "${targetPath}" stash list`;
98
- logger.debug(`Executing command: ${command}`, {
97
+ args = ["-C", targetPath, "stash", "list"];
98
+ logger.debug(`Executing command: git ${args.join(" ")}`, {
99
99
  ...context,
100
100
  operation,
101
101
  });
102
- const { stdout: listStdout } = await execAsync(command);
102
+ const { stdout: listStdout } = await execFileAsync("git", args);
103
103
  const stashes = listStdout
104
104
  .trim()
105
105
  .split("\n")
@@ -121,13 +121,13 @@ export async function gitStashLogic(input, context) {
121
121
  case "pop":
122
122
  // stashRef is validated by Zod refine
123
123
  const stashRefApplyPop = input.stashRef;
124
- command = `git -C "${targetPath}" stash ${input.mode} ${stashRefApplyPop}`;
125
- logger.debug(`Executing command: ${command}`, {
124
+ args = ["-C", targetPath, "stash", input.mode, stashRefApplyPop];
125
+ logger.debug(`Executing command: git ${args.join(" ")}`, {
126
126
  ...context,
127
127
  operation,
128
128
  });
129
129
  try {
130
- const { stdout, stderr } = await execAsync(command);
130
+ const { stdout, stderr } = await execFileAsync("git", args);
131
131
  // Check stdout/stderr for conflict messages, although exit code 0 usually means success
132
132
  const conflicts = /conflict/i.test(stdout) || /conflict/i.test(stderr);
133
133
  const message = conflicts
@@ -166,12 +166,12 @@ export async function gitStashLogic(input, context) {
166
166
  case "drop":
167
167
  // stashRef is validated by Zod refine
168
168
  const stashRefDrop = input.stashRef;
169
- command = `git -C "${targetPath}" stash drop ${stashRefDrop}`;
170
- logger.debug(`Executing command: ${command}`, {
169
+ args = ["-C", targetPath, "stash", "drop", stashRefDrop];
170
+ logger.debug(`Executing command: git ${args.join(" ")}`, {
171
171
  ...context,
172
172
  operation,
173
173
  });
174
- await execAsync(command);
174
+ await execFileAsync("git", args);
175
175
  result = {
176
176
  success: true,
177
177
  mode: "drop",
@@ -180,16 +180,15 @@ export async function gitStashLogic(input, context) {
180
180
  };
181
181
  break;
182
182
  case "save":
183
- command = `git -C "${targetPath}" stash save`;
183
+ args = ["-C", targetPath, "stash", "save"];
184
184
  if (input.message) {
185
- // Ensure message is properly quoted for the shell
186
- command += ` "${input.message.replace(/"/g, '\\"')}"`;
185
+ args.push(input.message);
187
186
  }
188
- logger.debug(`Executing command: ${command}`, {
187
+ logger.debug(`Executing command: git ${args.join(" ")}`, {
189
188
  ...context,
190
189
  operation,
191
190
  });
192
- const { stdout: saveStdout } = await execAsync(command);
191
+ const { stdout: saveStdout } = await execFileAsync("git", args);
193
192
  const stashCreated = !/no local changes to save/i.test(saveStdout);
194
193
  const saveMessage = stashCreated
195
194
  ? `Changes stashed successfully.` +
@@ -1,9 +1,9 @@
1
- import { exec } from "child_process";
1
+ import { execFile } from "child_process";
2
2
  import { promisify } from "util";
3
3
  import { z } from "zod";
4
4
  import { BaseErrorCode, McpError } from "../../../types-global/errors.js"; // Direct import for types-global
5
5
  import { logger, sanitization } from "../../../utils/index.js"; // logger (./utils/internal/logger.js), RequestContext (./utils/internal/requestContext.js), sanitization (./utils/security/sanitization.js)
6
- const execAsync = promisify(exec);
6
+ const execFileAsync = promisify(execFile);
7
7
  // Define the input schema for the git_status tool using Zod
8
8
  export const GitStatusInputSchema = z.object({
9
9
  path: z
@@ -197,10 +197,12 @@ export async function getGitStatus(input, context) {
197
197
  }
198
198
  try {
199
199
  // Using --porcelain=v1 for stable, scriptable output and -b for branch info
200
- // Ensure the path passed to -C is correctly quoted for the shell
201
- const command = `git -C "${targetPath}" status --porcelain=v1 -b`;
202
- logger.debug(`Executing command: ${command}`, { ...context, operation });
203
- const { stdout, stderr } = await execAsync(command);
200
+ const args = ["-C", targetPath, "status", "--porcelain=v1", "-b"];
201
+ logger.debug(`Executing command: git ${args.join(" ")}`, {
202
+ ...context,
203
+ operation,
204
+ });
205
+ const { stdout, stderr } = await execFileAsync("git", args);
204
206
  if (stderr) {
205
207
  // Log stderr as warning but proceed to parse stdout
206
208
  logger.warning(`Git status command produced stderr (may be informational)`, { ...context, operation, stderr });
@@ -216,8 +218,14 @@ export async function getGitStatus(input, context) {
216
218
  // This handles the case of an empty repo after init but before first commit
217
219
  if (structuredResult.is_clean && !structuredResult.current_branch) {
218
220
  try {
219
- const branchCommand = `git -C "${targetPath}" rev-parse --abbrev-ref HEAD`;
220
- const { stdout: branchStdout } = await execAsync(branchCommand);
221
+ const branchArgs = [
222
+ "-C",
223
+ targetPath,
224
+ "rev-parse",
225
+ "--abbrev-ref",
226
+ "HEAD",
227
+ ];
228
+ const { stdout: branchStdout } = await execFileAsync("git", branchArgs);
221
229
  const currentBranchName = branchStdout.trim(); // Renamed variable for clarity
222
230
  if (currentBranchName && currentBranchName !== "HEAD") {
223
231
  structuredResult.current_branch = currentBranchName;
@@ -1,9 +1,9 @@
1
- import { exec } from "child_process";
1
+ import { execFile } from "child_process";
2
2
  import { promisify } from "util";
3
3
  import { z } from "zod";
4
4
  import { BaseErrorCode, McpError } from "../../../types-global/errors.js"; // Direct import for types-global
5
5
  import { logger, sanitization } from "../../../utils/index.js"; // logger (./utils/internal/logger.js), RequestContext (./utils/internal/requestContext.js), sanitization (./utils/security/sanitization.js)
6
- const execAsync = promisify(exec);
6
+ const execFileAsync = promisify(execFile);
7
7
  // Define the base input schema for the git_tag tool using Zod
8
8
  // We export this separately to access its .shape for registration
9
9
  export const GitTagBaseSchema = z.object({
@@ -111,16 +111,16 @@ export async function gitTagLogic(input, context) {
111
111
  throw new McpError(BaseErrorCode.VALIDATION_ERROR, `Invalid commit reference format: ${input.commitRef}`, { context, operation });
112
112
  }
113
113
  try {
114
- let command;
114
+ let args;
115
115
  let result;
116
116
  switch (input.mode) {
117
117
  case "list":
118
- command = `git -C "${targetPath}" tag --list`;
119
- logger.debug(`Executing command: ${command}`, {
118
+ args = ["-C", targetPath, "tag", "--list"];
119
+ logger.debug(`Executing command: git ${args.join(" ")}`, {
120
120
  ...context,
121
121
  operation,
122
122
  });
123
- const { stdout: listStdout } = await execAsync(command);
123
+ const { stdout: listStdout } = await execFileAsync("git", args);
124
124
  const tags = listStdout
125
125
  .trim()
126
126
  .split("\n")
@@ -130,20 +130,20 @@ export async function gitTagLogic(input, context) {
130
130
  case "create":
131
131
  // TagName is validated by Zod refine
132
132
  const tagNameCreate = input.tagName;
133
- command = `git -C "${targetPath}" tag`;
133
+ args = ["-C", targetPath, "tag"];
134
134
  if (input.annotate) {
135
135
  // Message is validated by Zod refine
136
- command += ` -a -m "${input.message.replace(/"/g, '\\"')}"`;
136
+ args.push("-a", "-m", input.message);
137
137
  }
138
- command += ` "${tagNameCreate}"`;
138
+ args.push(tagNameCreate);
139
139
  if (input.commitRef) {
140
- command += ` "${input.commitRef}"`;
140
+ args.push(input.commitRef);
141
141
  }
142
- logger.debug(`Executing command: ${command}`, {
142
+ logger.debug(`Executing command: git ${args.join(" ")}`, {
143
143
  ...context,
144
144
  operation,
145
145
  });
146
- await execAsync(command);
146
+ await execFileAsync("git", args);
147
147
  result = {
148
148
  success: true,
149
149
  mode: "create",
@@ -154,12 +154,12 @@ export async function gitTagLogic(input, context) {
154
154
  case "delete":
155
155
  // TagName is validated by Zod refine
156
156
  const tagNameDelete = input.tagName;
157
- command = `git -C "${targetPath}" tag -d "${tagNameDelete}"`;
158
- logger.debug(`Executing command: ${command}`, {
157
+ args = ["-C", targetPath, "tag", "-d", tagNameDelete];
158
+ logger.debug(`Executing command: git ${args.join(" ")}`, {
159
159
  ...context,
160
160
  operation,
161
161
  });
162
- await execAsync(command);
162
+ await execFileAsync("git", args);
163
163
  result = {
164
164
  success: true,
165
165
  mode: "delete",
@@ -1,9 +1,9 @@
1
- import { exec } from "child_process";
1
+ import { execFile } from "child_process";
2
2
  import { promisify } from "util";
3
3
  import { z } from "zod";
4
4
  import { logger, sanitization } from "../../../utils/index.js";
5
5
  import { BaseErrorCode, McpError } from "../../../types-global/errors.js";
6
- const execAsync = promisify(exec);
6
+ const execFileAsync = promisify(execFile);
7
7
  // Define the BASE input schema for the git_worktree tool using Zod
8
8
  export const GitWorktreeBaseSchema = z.object({
9
9
  path: z
@@ -176,18 +176,19 @@ export async function gitWorktreeLogic(input, context) {
176
176
  throw new McpError(BaseErrorCode.VALIDATION_ERROR, `Invalid path: ${error instanceof Error ? error.message : String(error)}`, { context, operation, originalError: error });
177
177
  }
178
178
  try {
179
- let command = `git -C "${targetPath}" worktree `;
179
+ let args;
180
180
  let result;
181
181
  switch (input.mode) {
182
182
  case "list":
183
- command += "list";
184
- if (input.verbose)
185
- command += " --porcelain"; // Use porcelain for structured output
186
- logger.debug(`Executing command: ${command}`, {
183
+ args = ["-C", targetPath, "worktree", "list"];
184
+ if (input.verbose) {
185
+ args.push("--porcelain");
186
+ } // Use porcelain for structured output
187
+ logger.debug(`Executing command: git ${args.join(" ")}`, {
187
188
  ...context,
188
189
  operation,
189
190
  });
190
- const { stdout: listStdout } = await execAsync(command);
191
+ const { stdout: listStdout } = await execFileAsync("git", args);
191
192
  if (input.verbose) {
192
193
  const worktrees = parsePorcelainWorktreeList(listStdout);
193
194
  result = { success: true, mode: "list", worktrees };
@@ -214,21 +215,25 @@ export async function gitWorktreeLogic(input, context) {
214
215
  case "add":
215
216
  // worktreePath is guaranteed by refine
216
217
  const sanitizedWorktreePathAdd = sanitization.sanitizePath(input.worktreePath, { allowAbsolute: true, rootDir: targetPath }).sanitizedPath;
217
- command += `add `;
218
- if (input.force)
219
- command += "--force ";
220
- if (input.detach)
221
- command += "--detach ";
222
- if (input.newBranch)
223
- command += `-b "${input.newBranch}" `;
224
- command += `"${sanitizedWorktreePathAdd}"`;
225
- if (input.commitish)
226
- command += ` "${input.commitish}"`;
227
- logger.debug(`Executing command: ${command}`, {
218
+ args = ["-C", targetPath, "worktree", "add"];
219
+ if (input.force) {
220
+ args.push("--force");
221
+ }
222
+ if (input.detach) {
223
+ args.push("--detach");
224
+ }
225
+ if (input.newBranch) {
226
+ args.push("-b", input.newBranch);
227
+ }
228
+ args.push(sanitizedWorktreePathAdd);
229
+ if (input.commitish) {
230
+ args.push(input.commitish);
231
+ }
232
+ logger.debug(`Executing command: git ${args.join(" ")}`, {
228
233
  ...context,
229
234
  operation,
230
235
  });
231
- await execAsync(command);
236
+ await execFileAsync("git", args);
232
237
  // To get the HEAD of the new worktree, we might need another command or parse output if available
233
238
  // For simplicity, we'll report success. A more robust solution might `git -C new_worktree_path rev-parse HEAD`
234
239
  result = {
@@ -243,15 +248,16 @@ export async function gitWorktreeLogic(input, context) {
243
248
  case "remove":
244
249
  // worktreePath is guaranteed by refine
245
250
  const sanitizedWorktreePathRemove = sanitization.sanitizePath(input.worktreePath, { allowAbsolute: true, rootDir: targetPath }).sanitizedPath;
246
- command += `remove `;
247
- if (input.force)
248
- command += "--force ";
249
- command += `"${sanitizedWorktreePathRemove}"`;
250
- logger.debug(`Executing command: ${command}`, {
251
+ args = ["-C", targetPath, "worktree", "remove"];
252
+ if (input.force) {
253
+ args.push("--force");
254
+ }
255
+ args.push(sanitizedWorktreePathRemove);
256
+ logger.debug(`Executing command: git ${args.join(" ")}`, {
251
257
  ...context,
252
258
  operation,
253
259
  });
254
- const { stdout: removeStdout } = await execAsync(command);
260
+ const { stdout: removeStdout } = await execFileAsync("git", args);
255
261
  result = {
256
262
  success: true,
257
263
  mode: "remove",
@@ -267,12 +273,19 @@ export async function gitWorktreeLogic(input, context) {
267
273
  allowAbsolute: true,
268
274
  rootDir: targetPath,
269
275
  }).sanitizedPath;
270
- command += `move "${sanitizedOldPathMove}" "${sanitizedNewPathMove}"`;
271
- logger.debug(`Executing command: ${command}`, {
276
+ args = [
277
+ "-C",
278
+ targetPath,
279
+ "worktree",
280
+ "move",
281
+ sanitizedOldPathMove,
282
+ sanitizedNewPathMove,
283
+ ];
284
+ logger.debug(`Executing command: git ${args.join(" ")}`, {
272
285
  ...context,
273
286
  operation,
274
287
  });
275
- await execAsync(command);
288
+ await execFileAsync("git", args);
276
289
  result = {
277
290
  success: true,
278
291
  mode: "move",
@@ -282,18 +295,21 @@ export async function gitWorktreeLogic(input, context) {
282
295
  };
283
296
  break;
284
297
  case "prune":
285
- command += "prune ";
286
- if (input.dryRun)
287
- command += "--dry-run ";
288
- if (input.verbose)
289
- command += "--verbose ";
290
- if (input.expire)
291
- command += `--expire "${input.expire}" `;
292
- logger.debug(`Executing command: ${command}`, {
298
+ args = ["-C", targetPath, "worktree", "prune"];
299
+ if (input.dryRun) {
300
+ args.push("--dry-run");
301
+ }
302
+ if (input.verbose) {
303
+ args.push("--verbose");
304
+ }
305
+ if (input.expire) {
306
+ args.push(`--expire=${input.expire}`);
307
+ }
308
+ logger.debug(`Executing command: git ${args.join(" ")}`, {
293
309
  ...context,
294
310
  operation,
295
311
  });
296
- const { stdout: pruneStdout, stderr: pruneStderr } = await execAsync(command);
312
+ const { stdout: pruneStdout, stderr: pruneStderr } = await execFileAsync("git", args);
297
313
  // Prune often outputs to stderr even on success for verbose/dry-run
298
314
  const pruneMessage = pruneStdout.trim() ||
299
315
  pruneStderr.trim() ||
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyanheads/git-mcp-server",
3
- "version": "2.1.4",
3
+ "version": "2.1.6",
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": [
@@ -36,22 +36,15 @@
36
36
  },
37
37
  "dependencies": {
38
38
  "@hono/node-server": "^1.14.4",
39
- "@modelcontextprotocol/inspector": "^0.14.3",
40
- "@modelcontextprotocol/sdk": "^1.13.0",
41
- "@types/jsonwebtoken": "^9.0.10",
42
- "@types/node": "^24.0.3",
39
+ "@modelcontextprotocol/sdk": "^1.13.2",
40
+ "@types/node": "^24.0.7",
43
41
  "@types/sanitize-html": "^2.16.0",
44
42
  "@types/validator": "^13.15.2",
45
- "chalk": "^5.4.1",
46
43
  "chrono-node": "2.8.0",
47
- "cli-table3": "^0.6.5",
48
- "dotenv": "^16.5.0",
49
- "express": "^5.1.0",
50
- "hono": "^4.8.2",
51
- "ignore": "^7.0.5",
44
+ "dotenv": "^17.0.0",
45
+ "hono": "^4.8.3",
52
46
  "jose": "^6.0.11",
53
- "jsonwebtoken": "^9.0.2",
54
- "openai": "^5.6.0",
47
+ "openai": "^5.8.2",
55
48
  "partial-json": "^0.1.7",
56
49
  "sanitize-html": "^2.17.0",
57
50
  "tiktoken": "^1.0.21",
@@ -59,8 +52,7 @@
59
52
  "typescript": "^5.8.3",
60
53
  "validator": "^13.15.15",
61
54
  "winston": "^3.17.0",
62
- "winston-daily-rotate-file": "^5.0.0",
63
- "yargs": "^18.0.0",
55
+ "winston-transport": "^4.9.0",
64
56
  "zod": "^3.25.67"
65
57
  },
66
58
  "keywords": [
@@ -113,11 +105,8 @@
113
105
  "node": ">=20.0.0"
114
106
  },
115
107
  "devDependencies": {
116
- "@types/express": "^5.0.3",
117
- "@types/js-yaml": "^4.0.9",
118
- "js-yaml": "^4.1.0",
119
- "prettier": "^3.5.3",
120
- "typedoc": "^0.28.5"
108
+ "prettier": "^3.6.2",
109
+ "typedoc": "^0.28.6"
121
110
  },
122
111
  "publishConfig": {
123
112
  "access": "public"