@cyanheads/git-mcp-server 2.6.1 → 2.6.3

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.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/dist/index.js +468 -6
  3. package/package.json +3 -1
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  <div align="center">
9
9
 
10
- [![Version](https://img.shields.io/badge/Version-2.6.1-blue.svg?style=flat-square)](./CHANGELOG.md) [![MCP Spec](https://img.shields.io/badge/MCP%20Spec-2025--11--25-8A2BE2.svg?style=flat-square)](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2025-11-25/changelog.mdx) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^1.24.3-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![Status](https://img.shields.io/badge/Status-Stable-brightgreen.svg?style=flat-square)](https://github.com/cyanheads/git-mcp-server/issues) [![TypeScript](https://img.shields.io/badge/TypeScript-^5.9.3-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-v1.2.21-blueviolet.svg?style=flat-square)](https://bun.sh/)
10
+ [![Version](https://img.shields.io/badge/Version-2.6.2-blue.svg?style=flat-square)](./CHANGELOG.md) [![MCP Spec](https://img.shields.io/badge/MCP%20Spec-2025--11--25-8A2BE2.svg?style=flat-square)](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/docs/specification/2025-11-25/changelog.mdx) [![MCP SDK](https://img.shields.io/badge/MCP%20SDK-^1.24.3-green.svg?style=flat-square)](https://modelcontextprotocol.io/) [![License](https://img.shields.io/badge/License-Apache%202.0-orange.svg?style=flat-square)](./LICENSE) [![Status](https://img.shields.io/badge/Status-Stable-brightgreen.svg?style=flat-square)](https://github.com/cyanheads/git-mcp-server/issues) [![TypeScript](https://img.shields.io/badge/TypeScript-^5.9.3-3178C6.svg?style=flat-square)](https://www.typescriptlang.org/) [![Bun](https://img.shields.io/badge/Bun-v1.2.21-blueviolet.svg?style=flat-square)](https://bun.sh/)
11
11
 
12
12
  </div>
13
13
 
package/dist/index.js CHANGED
@@ -14356,7 +14356,7 @@ var package_default;
14356
14356
  var init_package = __esm(() => {
14357
14357
  package_default = {
14358
14358
  name: "@cyanheads/git-mcp-server",
14359
- version: "2.6.0",
14359
+ version: "2.6.2",
14360
14360
  mcpName: "io.github.cyanheads/git-mcp-server",
14361
14361
  description: "A secure and scalable Git MCP server enabling AI agents to perform comprehensive Git version control operations via STDIO and Streamable HTTP.",
14362
14362
  main: "dist/index.js",
@@ -14440,6 +14440,7 @@ var init_package = __esm(() => {
14440
14440
  "@opentelemetry/semantic-conventions": "^1.38.0",
14441
14441
  "@supabase/supabase-js": "^2.87.1",
14442
14442
  "@types/bun": "^1.3.4",
14443
+ "@types/cross-spawn": "^6.0.6",
14443
14444
  "@types/js-yaml": "^4.0.9",
14444
14445
  "@types/node": "^25.0.1",
14445
14446
  "@types/node-cron": "^3.0.11",
@@ -14530,6 +14531,7 @@ var init_package = __esm(() => {
14530
14531
  }
14531
14532
  ],
14532
14533
  dependencies: {
14534
+ "cross-spawn": "^7.0.6",
14533
14535
  pino: "^10.1.0",
14534
14536
  "pino-pretty": "^13.1.3"
14535
14537
  },
@@ -161116,6 +161118,462 @@ var require_main6 = __commonJS((exports) => {
161116
161118
  }
161117
161119
  });
161118
161120
 
161121
+ // node_modules/isexe/windows.js
161122
+ var require_windows = __commonJS((exports, module) => {
161123
+ module.exports = isexe;
161124
+ isexe.sync = sync;
161125
+ var fs = __require("fs");
161126
+ function checkPathExt(path2, options) {
161127
+ var pathext = options.pathExt !== undefined ? options.pathExt : process.env.PATHEXT;
161128
+ if (!pathext) {
161129
+ return true;
161130
+ }
161131
+ pathext = pathext.split(";");
161132
+ if (pathext.indexOf("") !== -1) {
161133
+ return true;
161134
+ }
161135
+ for (var i2 = 0;i2 < pathext.length; i2++) {
161136
+ var p = pathext[i2].toLowerCase();
161137
+ if (p && path2.substr(-p.length).toLowerCase() === p) {
161138
+ return true;
161139
+ }
161140
+ }
161141
+ return false;
161142
+ }
161143
+ function checkStat(stat, path2, options) {
161144
+ if (!stat.isSymbolicLink() && !stat.isFile()) {
161145
+ return false;
161146
+ }
161147
+ return checkPathExt(path2, options);
161148
+ }
161149
+ function isexe(path2, options, cb) {
161150
+ fs.stat(path2, function(er, stat) {
161151
+ cb(er, er ? false : checkStat(stat, path2, options));
161152
+ });
161153
+ }
161154
+ function sync(path2, options) {
161155
+ return checkStat(fs.statSync(path2), path2, options);
161156
+ }
161157
+ });
161158
+
161159
+ // node_modules/isexe/mode.js
161160
+ var require_mode = __commonJS((exports, module) => {
161161
+ module.exports = isexe;
161162
+ isexe.sync = sync;
161163
+ var fs = __require("fs");
161164
+ function isexe(path2, options, cb) {
161165
+ fs.stat(path2, function(er, stat) {
161166
+ cb(er, er ? false : checkStat(stat, options));
161167
+ });
161168
+ }
161169
+ function sync(path2, options) {
161170
+ return checkStat(fs.statSync(path2), options);
161171
+ }
161172
+ function checkStat(stat, options) {
161173
+ return stat.isFile() && checkMode(stat, options);
161174
+ }
161175
+ function checkMode(stat, options) {
161176
+ var mod2 = stat.mode;
161177
+ var uid = stat.uid;
161178
+ var gid = stat.gid;
161179
+ var myUid = options.uid !== undefined ? options.uid : process.getuid && process.getuid();
161180
+ var myGid = options.gid !== undefined ? options.gid : process.getgid && process.getgid();
161181
+ var u = parseInt("100", 8);
161182
+ var g = parseInt("010", 8);
161183
+ var o = parseInt("001", 8);
161184
+ var ug = u | g;
161185
+ var ret = mod2 & o || mod2 & g && gid === myGid || mod2 & u && uid === myUid || mod2 & ug && myUid === 0;
161186
+ return ret;
161187
+ }
161188
+ });
161189
+
161190
+ // node_modules/isexe/index.js
161191
+ var require_isexe = __commonJS((exports, module) => {
161192
+ var fs = __require("fs");
161193
+ var core3;
161194
+ if (process.platform === "win32" || global.TESTING_WINDOWS) {
161195
+ core3 = require_windows();
161196
+ } else {
161197
+ core3 = require_mode();
161198
+ }
161199
+ module.exports = isexe;
161200
+ isexe.sync = sync;
161201
+ function isexe(path2, options, cb) {
161202
+ if (typeof options === "function") {
161203
+ cb = options;
161204
+ options = {};
161205
+ }
161206
+ if (!cb) {
161207
+ if (typeof Promise !== "function") {
161208
+ throw new TypeError("callback not provided");
161209
+ }
161210
+ return new Promise(function(resolve, reject) {
161211
+ isexe(path2, options || {}, function(er, is) {
161212
+ if (er) {
161213
+ reject(er);
161214
+ } else {
161215
+ resolve(is);
161216
+ }
161217
+ });
161218
+ });
161219
+ }
161220
+ core3(path2, options || {}, function(er, is) {
161221
+ if (er) {
161222
+ if (er.code === "EACCES" || options && options.ignoreErrors) {
161223
+ er = null;
161224
+ is = false;
161225
+ }
161226
+ }
161227
+ cb(er, is);
161228
+ });
161229
+ }
161230
+ function sync(path2, options) {
161231
+ try {
161232
+ return core3.sync(path2, options || {});
161233
+ } catch (er) {
161234
+ if (options && options.ignoreErrors || er.code === "EACCES") {
161235
+ return false;
161236
+ } else {
161237
+ throw er;
161238
+ }
161239
+ }
161240
+ }
161241
+ });
161242
+
161243
+ // node_modules/which/which.js
161244
+ var require_which = __commonJS((exports, module) => {
161245
+ var isWindows = process.platform === "win32" || process.env.OSTYPE === "cygwin" || process.env.OSTYPE === "msys";
161246
+ var path2 = __require("path");
161247
+ var COLON = isWindows ? ";" : ":";
161248
+ var isexe = require_isexe();
161249
+ var getNotFoundError = (cmd) => Object.assign(new Error(`not found: ${cmd}`), { code: "ENOENT" });
161250
+ var getPathInfo = (cmd, opt) => {
161251
+ const colon = opt.colon || COLON;
161252
+ const pathEnv = cmd.match(/\//) || isWindows && cmd.match(/\\/) ? [""] : [
161253
+ ...isWindows ? [process.cwd()] : [],
161254
+ ...(opt.path || process.env.PATH || "").split(colon)
161255
+ ];
161256
+ const pathExtExe = isWindows ? opt.pathExt || process.env.PATHEXT || ".EXE;.CMD;.BAT;.COM" : "";
161257
+ const pathExt = isWindows ? pathExtExe.split(colon) : [""];
161258
+ if (isWindows) {
161259
+ if (cmd.indexOf(".") !== -1 && pathExt[0] !== "")
161260
+ pathExt.unshift("");
161261
+ }
161262
+ return {
161263
+ pathEnv,
161264
+ pathExt,
161265
+ pathExtExe
161266
+ };
161267
+ };
161268
+ var which = (cmd, opt, cb) => {
161269
+ if (typeof opt === "function") {
161270
+ cb = opt;
161271
+ opt = {};
161272
+ }
161273
+ if (!opt)
161274
+ opt = {};
161275
+ const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
161276
+ const found = [];
161277
+ const step = (i2) => new Promise((resolve, reject) => {
161278
+ if (i2 === pathEnv.length)
161279
+ return opt.all && found.length ? resolve(found) : reject(getNotFoundError(cmd));
161280
+ const ppRaw = pathEnv[i2];
161281
+ const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
161282
+ const pCmd = path2.join(pathPart, cmd);
161283
+ const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
161284
+ resolve(subStep(p, i2, 0));
161285
+ });
161286
+ const subStep = (p, i2, ii) => new Promise((resolve, reject) => {
161287
+ if (ii === pathExt.length)
161288
+ return resolve(step(i2 + 1));
161289
+ const ext = pathExt[ii];
161290
+ isexe(p + ext, { pathExt: pathExtExe }, (er, is) => {
161291
+ if (!er && is) {
161292
+ if (opt.all)
161293
+ found.push(p + ext);
161294
+ else
161295
+ return resolve(p + ext);
161296
+ }
161297
+ return resolve(subStep(p, i2, ii + 1));
161298
+ });
161299
+ });
161300
+ return cb ? step(0).then((res) => cb(null, res), cb) : step(0);
161301
+ };
161302
+ var whichSync = (cmd, opt) => {
161303
+ opt = opt || {};
161304
+ const { pathEnv, pathExt, pathExtExe } = getPathInfo(cmd, opt);
161305
+ const found = [];
161306
+ for (let i2 = 0;i2 < pathEnv.length; i2++) {
161307
+ const ppRaw = pathEnv[i2];
161308
+ const pathPart = /^".*"$/.test(ppRaw) ? ppRaw.slice(1, -1) : ppRaw;
161309
+ const pCmd = path2.join(pathPart, cmd);
161310
+ const p = !pathPart && /^\.[\\\/]/.test(cmd) ? cmd.slice(0, 2) + pCmd : pCmd;
161311
+ for (let j = 0;j < pathExt.length; j++) {
161312
+ const cur = p + pathExt[j];
161313
+ try {
161314
+ const is = isexe.sync(cur, { pathExt: pathExtExe });
161315
+ if (is) {
161316
+ if (opt.all)
161317
+ found.push(cur);
161318
+ else
161319
+ return cur;
161320
+ }
161321
+ } catch (ex) {}
161322
+ }
161323
+ }
161324
+ if (opt.all && found.length)
161325
+ return found;
161326
+ if (opt.nothrow)
161327
+ return null;
161328
+ throw getNotFoundError(cmd);
161329
+ };
161330
+ module.exports = which;
161331
+ which.sync = whichSync;
161332
+ });
161333
+
161334
+ // node_modules/path-key/index.js
161335
+ var require_path_key = __commonJS((exports, module) => {
161336
+ var pathKey = (options = {}) => {
161337
+ const environment = options.env || process.env;
161338
+ const platform = options.platform || process.platform;
161339
+ if (platform !== "win32") {
161340
+ return "PATH";
161341
+ }
161342
+ return Object.keys(environment).reverse().find((key) => key.toUpperCase() === "PATH") || "Path";
161343
+ };
161344
+ module.exports = pathKey;
161345
+ module.exports.default = pathKey;
161346
+ });
161347
+
161348
+ // node_modules/cross-spawn/lib/util/resolveCommand.js
161349
+ var require_resolveCommand = __commonJS((exports, module) => {
161350
+ var path2 = __require("path");
161351
+ var which = require_which();
161352
+ var getPathKey = require_path_key();
161353
+ function resolveCommandAttempt(parsed, withoutPathExt) {
161354
+ const env = parsed.options.env || process.env;
161355
+ const cwd = process.cwd();
161356
+ const hasCustomCwd = parsed.options.cwd != null;
161357
+ const shouldSwitchCwd = hasCustomCwd && process.chdir !== undefined && !process.chdir.disabled;
161358
+ if (shouldSwitchCwd) {
161359
+ try {
161360
+ process.chdir(parsed.options.cwd);
161361
+ } catch (err) {}
161362
+ }
161363
+ let resolved;
161364
+ try {
161365
+ resolved = which.sync(parsed.command, {
161366
+ path: env[getPathKey({ env })],
161367
+ pathExt: withoutPathExt ? path2.delimiter : undefined
161368
+ });
161369
+ } catch (e) {} finally {
161370
+ if (shouldSwitchCwd) {
161371
+ process.chdir(cwd);
161372
+ }
161373
+ }
161374
+ if (resolved) {
161375
+ resolved = path2.resolve(hasCustomCwd ? parsed.options.cwd : "", resolved);
161376
+ }
161377
+ return resolved;
161378
+ }
161379
+ function resolveCommand(parsed) {
161380
+ return resolveCommandAttempt(parsed) || resolveCommandAttempt(parsed, true);
161381
+ }
161382
+ module.exports = resolveCommand;
161383
+ });
161384
+
161385
+ // node_modules/cross-spawn/lib/util/escape.js
161386
+ var require_escape3 = __commonJS((exports, module) => {
161387
+ var metaCharsRegExp = /([()\][%!^"`<>&|;, *?])/g;
161388
+ function escapeCommand(arg) {
161389
+ arg = arg.replace(metaCharsRegExp, "^$1");
161390
+ return arg;
161391
+ }
161392
+ function escapeArgument(arg, doubleEscapeMetaChars) {
161393
+ arg = `${arg}`;
161394
+ arg = arg.replace(/(?=(\\+?)?)\1"/g, "$1$1\\\"");
161395
+ arg = arg.replace(/(?=(\\+?)?)\1$/, "$1$1");
161396
+ arg = `"${arg}"`;
161397
+ arg = arg.replace(metaCharsRegExp, "^$1");
161398
+ if (doubleEscapeMetaChars) {
161399
+ arg = arg.replace(metaCharsRegExp, "^$1");
161400
+ }
161401
+ return arg;
161402
+ }
161403
+ exports.command = escapeCommand;
161404
+ exports.argument = escapeArgument;
161405
+ });
161406
+
161407
+ // node_modules/shebang-regex/index.js
161408
+ var require_shebang_regex = __commonJS((exports, module) => {
161409
+ module.exports = /^#!(.*)/;
161410
+ });
161411
+
161412
+ // node_modules/shebang-command/index.js
161413
+ var require_shebang_command = __commonJS((exports, module) => {
161414
+ var shebangRegex = require_shebang_regex();
161415
+ module.exports = (string4 = "") => {
161416
+ const match = string4.match(shebangRegex);
161417
+ if (!match) {
161418
+ return null;
161419
+ }
161420
+ const [path2, argument] = match[0].replace(/#! ?/, "").split(" ");
161421
+ const binary2 = path2.split("/").pop();
161422
+ if (binary2 === "env") {
161423
+ return argument;
161424
+ }
161425
+ return argument ? `${binary2} ${argument}` : binary2;
161426
+ };
161427
+ });
161428
+
161429
+ // node_modules/cross-spawn/lib/util/readShebang.js
161430
+ var require_readShebang = __commonJS((exports, module) => {
161431
+ var fs = __require("fs");
161432
+ var shebangCommand = require_shebang_command();
161433
+ function readShebang(command) {
161434
+ const size = 150;
161435
+ const buffer = Buffer.alloc(size);
161436
+ let fd;
161437
+ try {
161438
+ fd = fs.openSync(command, "r");
161439
+ fs.readSync(fd, buffer, 0, size, 0);
161440
+ fs.closeSync(fd);
161441
+ } catch (e) {}
161442
+ return shebangCommand(buffer.toString());
161443
+ }
161444
+ module.exports = readShebang;
161445
+ });
161446
+
161447
+ // node_modules/cross-spawn/lib/parse.js
161448
+ var require_parse5 = __commonJS((exports, module) => {
161449
+ var path2 = __require("path");
161450
+ var resolveCommand = require_resolveCommand();
161451
+ var escape2 = require_escape3();
161452
+ var readShebang = require_readShebang();
161453
+ var isWin = process.platform === "win32";
161454
+ var isExecutableRegExp = /\.(?:com|exe)$/i;
161455
+ var isCmdShimRegExp = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;
161456
+ function detectShebang(parsed) {
161457
+ parsed.file = resolveCommand(parsed);
161458
+ const shebang = parsed.file && readShebang(parsed.file);
161459
+ if (shebang) {
161460
+ parsed.args.unshift(parsed.file);
161461
+ parsed.command = shebang;
161462
+ return resolveCommand(parsed);
161463
+ }
161464
+ return parsed.file;
161465
+ }
161466
+ function parseNonShell(parsed) {
161467
+ if (!isWin) {
161468
+ return parsed;
161469
+ }
161470
+ const commandFile = detectShebang(parsed);
161471
+ const needsShell = !isExecutableRegExp.test(commandFile);
161472
+ if (parsed.options.forceShell || needsShell) {
161473
+ const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile);
161474
+ parsed.command = path2.normalize(parsed.command);
161475
+ parsed.command = escape2.command(parsed.command);
161476
+ parsed.args = parsed.args.map((arg) => escape2.argument(arg, needsDoubleEscapeMetaChars));
161477
+ const shellCommand = [parsed.command].concat(parsed.args).join(" ");
161478
+ parsed.args = ["/d", "/s", "/c", `"${shellCommand}"`];
161479
+ parsed.command = process.env.comspec || "cmd.exe";
161480
+ parsed.options.windowsVerbatimArguments = true;
161481
+ }
161482
+ return parsed;
161483
+ }
161484
+ function parse6(command, args, options) {
161485
+ if (args && !Array.isArray(args)) {
161486
+ options = args;
161487
+ args = null;
161488
+ }
161489
+ args = args ? args.slice(0) : [];
161490
+ options = Object.assign({}, options);
161491
+ const parsed = {
161492
+ command,
161493
+ args,
161494
+ options,
161495
+ file: undefined,
161496
+ original: {
161497
+ command,
161498
+ args
161499
+ }
161500
+ };
161501
+ return options.shell ? parsed : parseNonShell(parsed);
161502
+ }
161503
+ module.exports = parse6;
161504
+ });
161505
+
161506
+ // node_modules/cross-spawn/lib/enoent.js
161507
+ var require_enoent = __commonJS((exports, module) => {
161508
+ var isWin = process.platform === "win32";
161509
+ function notFoundError(original, syscall) {
161510
+ return Object.assign(new Error(`${syscall} ${original.command} ENOENT`), {
161511
+ code: "ENOENT",
161512
+ errno: "ENOENT",
161513
+ syscall: `${syscall} ${original.command}`,
161514
+ path: original.command,
161515
+ spawnargs: original.args
161516
+ });
161517
+ }
161518
+ function hookChildProcess(cp, parsed) {
161519
+ if (!isWin) {
161520
+ return;
161521
+ }
161522
+ const originalEmit = cp.emit;
161523
+ cp.emit = function(name, arg1) {
161524
+ if (name === "exit") {
161525
+ const err = verifyENOENT(arg1, parsed);
161526
+ if (err) {
161527
+ return originalEmit.call(cp, "error", err);
161528
+ }
161529
+ }
161530
+ return originalEmit.apply(cp, arguments);
161531
+ };
161532
+ }
161533
+ function verifyENOENT(status, parsed) {
161534
+ if (isWin && status === 1 && !parsed.file) {
161535
+ return notFoundError(parsed.original, "spawn");
161536
+ }
161537
+ return null;
161538
+ }
161539
+ function verifyENOENTSync(status, parsed) {
161540
+ if (isWin && status === 1 && !parsed.file) {
161541
+ return notFoundError(parsed.original, "spawnSync");
161542
+ }
161543
+ return null;
161544
+ }
161545
+ module.exports = {
161546
+ hookChildProcess,
161547
+ verifyENOENT,
161548
+ verifyENOENTSync,
161549
+ notFoundError
161550
+ };
161551
+ });
161552
+
161553
+ // node_modules/cross-spawn/index.js
161554
+ var require_cross_spawn = __commonJS((exports, module) => {
161555
+ var cp = __require("child_process");
161556
+ var parse6 = require_parse5();
161557
+ var enoent = require_enoent();
161558
+ function spawn(command, args, options) {
161559
+ const parsed = parse6(command, args, options);
161560
+ const spawned = cp.spawn(parsed.command, parsed.args, parsed.options);
161561
+ enoent.hookChildProcess(spawned, parsed);
161562
+ return spawned;
161563
+ }
161564
+ function spawnSync(command, args, options) {
161565
+ const parsed = parse6(command, args, options);
161566
+ const result = cp.spawnSync(parsed.command, parsed.args, parsed.options);
161567
+ result.error = result.error || enoent.verifyENOENTSync(result.status, parsed);
161568
+ return result;
161569
+ }
161570
+ module.exports = spawn;
161571
+ module.exports.spawn = spawn;
161572
+ module.exports.sync = spawnSync;
161573
+ module.exports._parse = parse6;
161574
+ module.exports._enoent = enoent;
161575
+ });
161576
+
161119
161577
  // node_modules/ajv/dist/compile/codegen/code.js
161120
161578
  var require_code = __commonJS((exports) => {
161121
161579
  Object.defineProperty(exports, "__esModule", { value: true });
@@ -168033,7 +168491,7 @@ function isGitNotFoundError(error46) {
168033
168491
  }
168034
168492
 
168035
168493
  // src/services/git/providers/cli/utils/runtime-adapter.ts
168036
- import { spawn } from "node:child_process";
168494
+ var import_cross_spawn = __toESM(require_cross_spawn(), 1);
168037
168495
  function detectRuntime2() {
168038
168496
  if (typeof globalThis.Bun !== "undefined") {
168039
168497
  return "bun";
@@ -168091,11 +168549,15 @@ async function spawnWithNode(args, cwd, env, timeout, signal) {
168091
168549
  reject(new Error(`Git command cancelled before execution: ${args.join(" ")}`));
168092
168550
  return;
168093
168551
  }
168094
- const proc = spawn("git", args, {
168552
+ const proc = import_cross_spawn.default("git", args, {
168095
168553
  cwd,
168096
168554
  env,
168097
168555
  stdio: ["ignore", "pipe", "pipe"]
168098
168556
  });
168557
+ if (!proc.stdout || !proc.stderr) {
168558
+ reject(new Error("Failed to capture process streams"));
168559
+ return;
168560
+ }
168099
168561
  const stdoutChunks = [];
168100
168562
  const stderrChunks = [];
168101
168563
  proc.stdout.on("data", (chunk) => {
@@ -186014,7 +186476,7 @@ var SuccessResponseSchema = exports_external.object({
186014
186476
  var FilePathSchema = exports_external.string().min(1).regex(/^[^/].*$/, "File path must be relative to repository root").regex(/^(?!.*\.\.).*$/, "File path cannot contain directory traversal").describe("File path relative to repository root.");
186015
186477
  var TagNameSchema = exports_external.string().min(1).max(255).regex(/^[^~^:?*\[\\]+$/, "Invalid tag name format").describe("Tag name (must follow git naming conventions).");
186016
186478
  var CommitMessageSchema = exports_external.string().min(1, "Commit message cannot be empty").max(1e4, "Commit message too long").describe("Commit message.");
186017
- var LimitSchema = exports_external.number().int().positive().max(1000).optional().describe("Maximum number of items to return (1-1000).");
186479
+ var LimitSchema = exports_external.number().int().min(1).max(1000).optional().describe("Maximum number of items to return (1-1000).");
186018
186480
  var SkipSchema = exports_external.number().int().nonnegative().optional().describe("Number of items to skip for pagination.");
186019
186481
  var VerboseSchema = exports_external.boolean().default(false).describe("Include verbose/detailed information in output.");
186020
186482
  var QuietSchema = exports_external.boolean().default(false).describe("Suppress informational output (errors only).");
@@ -186022,7 +186484,7 @@ var RecursiveSchema = exports_external.boolean().default(false).describe("Operat
186022
186484
  var AllSchema = exports_external.boolean().default(false).describe("Include all items (varies by operation).");
186023
186485
  var MergeStrategySchema = exports_external.enum(["ort", "recursive", "octopus", "ours", "subtree"]).optional().describe("Merge strategy to use (ort, recursive, octopus, ours, subtree).");
186024
186486
  var PruneSchema = exports_external.boolean().default(false).describe("Prune remote-tracking references that no longer exist on remote.");
186025
- var DepthSchema = exports_external.number().int().positive().optional().describe("Create a shallow clone with history truncated to N commits.");
186487
+ var DepthSchema = exports_external.number().int().min(1).optional().describe("Create a shallow clone with history truncated to N commits.");
186026
186488
  var SignSchema = exports_external.boolean().optional().describe("Sign the commit/tag with GPG.");
186027
186489
  var NoVerifySchema = exports_external.boolean().default(false).describe("Bypass pre-commit and commit-msg hooks.");
186028
186490
 
@@ -187867,7 +188329,7 @@ var InputSchema17 = exports_external.object({
187867
188329
  noCommit: exports_external.boolean().default(false).describe("Don't create commit (stage changes only)."),
187868
188330
  continueOperation: exports_external.boolean().default(false).describe("Continue cherry-pick after resolving conflicts."),
187869
188331
  abort: exports_external.boolean().default(false).describe("Abort cherry-pick operation."),
187870
- mainline: exports_external.number().int().positive().optional().describe("For merge commits, specify which parent to follow (1 for first parent, 2 for second, etc.)."),
188332
+ mainline: exports_external.number().int().min(1).optional().describe("For merge commits, specify which parent to follow (1 for first parent, 2 for second, etc.)."),
187871
188333
  strategy: MergeStrategySchema.describe("Merge strategy to use for cherry-pick."),
187872
188334
  signoff: exports_external.boolean().default(false).describe("Add Signed-off-by line to the commit message.")
187873
188335
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyanheads/git-mcp-server",
3
- "version": "2.6.1",
3
+ "version": "2.6.3",
4
4
  "mcpName": "io.github.cyanheads/git-mcp-server",
5
5
  "description": "A secure and scalable Git MCP server enabling AI agents to perform comprehensive Git version control operations via STDIO and Streamable HTTP.",
6
6
  "main": "dist/index.js",
@@ -84,6 +84,7 @@
84
84
  "@opentelemetry/semantic-conventions": "^1.38.0",
85
85
  "@supabase/supabase-js": "^2.87.1",
86
86
  "@types/bun": "^1.3.4",
87
+ "@types/cross-spawn": "^6.0.6",
87
88
  "@types/js-yaml": "^4.0.9",
88
89
  "@types/node": "^25.0.1",
89
90
  "@types/node-cron": "^3.0.11",
@@ -174,6 +175,7 @@
174
175
  }
175
176
  ],
176
177
  "dependencies": {
178
+ "cross-spawn": "^7.0.6",
177
179
  "pino": "^10.1.0",
178
180
  "pino-pretty": "^13.1.3"
179
181
  },