@cyanheads/git-mcp-server 2.4.9 → 2.5.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.
Files changed (2) hide show
  1. package/dist/index.js +305 -42
  2. package/package.json +29 -31
package/dist/index.js CHANGED
@@ -4261,7 +4261,7 @@ var package_default;
4261
4261
  var init_package = __esm(() => {
4262
4262
  package_default = {
4263
4263
  name: "@cyanheads/git-mcp-server",
4264
- version: "2.4.9",
4264
+ version: "2.5.1",
4265
4265
  mcpName: "io.github.cyanheads/git-mcp-server",
4266
4266
  description: "A secure and scalable Git MCP server enabling AI agents to perform comprehensive Git version control operations via STDIO and Streamable HTTP.",
4267
4267
  main: "dist/index.js",
@@ -4327,33 +4327,12 @@ var init_package = __esm(() => {
4327
4327
  zod: "3.23.8",
4328
4328
  typescript: "5.9.3"
4329
4329
  },
4330
- dependencies: {
4330
+ devDependencies: {
4331
+ "@cloudflare/workers-types": "^4.20251011.0",
4332
+ "@eslint/js": "^9.37.0",
4331
4333
  "@hono/mcp": "^0.1.4",
4332
4334
  "@hono/node-server": "^1.19.5",
4333
4335
  "@modelcontextprotocol/sdk": "^1.20.0",
4334
- "@supabase/supabase-js": "^2.75.0",
4335
- axios: "^1.12.2",
4336
- "chrono-node": "^2.9.0",
4337
- dotenv: "^17.2.3",
4338
- "fast-xml-parser": "^5.3.0",
4339
- hono: "^4.9.12",
4340
- ignore: "^7.0.5",
4341
- jose: "^6.1.0",
4342
- "js-yaml": "^4.1.0",
4343
- "node-cron": "^4.2.1",
4344
- openai: "^6.3.0",
4345
- papaparse: "^5.5.3",
4346
- "partial-json": "^0.1.7",
4347
- "pdf-lib": "^1.17.1",
4348
- pino: "^10.0.0",
4349
- "pino-pretty": "^13.1.2",
4350
- "reflect-metadata": "^0.2.2",
4351
- repomix: "^1.7.0",
4352
- "sanitize-html": "^2.17.0",
4353
- tslib: "^2.8.1",
4354
- tsyringe: "^4.10.0",
4355
- validator: "13.15.15",
4356
- zod: "^3.23.8",
4357
4336
  "@opentelemetry/api": "^1.9.0",
4358
4337
  "@opentelemetry/auto-instrumentations-node": "^0.65.0",
4359
4338
  "@opentelemetry/exporter-metrics-otlp-http": "^0.206.0",
@@ -4363,11 +4342,8 @@ var init_package = __esm(() => {
4363
4342
  "@opentelemetry/sdk-metrics": "^2.1.0",
4364
4343
  "@opentelemetry/sdk-node": "^0.206.0",
4365
4344
  "@opentelemetry/sdk-trace-node": "^2.1.0",
4366
- "@opentelemetry/semantic-conventions": "^1.37.0"
4367
- },
4368
- devDependencies: {
4369
- "@cloudflare/workers-types": "^4.20251011.0",
4370
- "@eslint/js": "^9.37.0",
4345
+ "@opentelemetry/semantic-conventions": "^1.37.0",
4346
+ "@supabase/supabase-js": "^2.75.0",
4371
4347
  "@types/bun": "^1.3.0",
4372
4348
  "@types/js-yaml": "^4.0.9",
4373
4349
  "@types/node": "^24.7.2",
@@ -4378,21 +4354,43 @@ var init_package = __esm(() => {
4378
4354
  "@vitest/coverage-v8": "3.2.4",
4379
4355
  ajv: "^8.17.1",
4380
4356
  "ajv-formats": "^3.0.1",
4357
+ axios: "^1.12.2",
4381
4358
  "bun-types": "^1.3.0",
4359
+ "chrono-node": "^2.9.0",
4382
4360
  clipboardy: "^5.0.0",
4383
4361
  depcheck: "^1.4.7",
4362
+ dotenv: "^17.2.3",
4384
4363
  eslint: "^9.37.0",
4385
4364
  execa: "^9.6.0",
4365
+ "fast-xml-parser": "^5.3.0",
4386
4366
  globals: "^16.4.0",
4367
+ hono: "^4.9.12",
4387
4368
  husky: "^9.1.7",
4369
+ ignore: "^7.0.5",
4370
+ jose: "^6.1.0",
4371
+ "js-yaml": "^4.1.0",
4388
4372
  msw: "^2.11.5",
4373
+ "node-cron": "^4.2.1",
4374
+ openai: "^6.3.0",
4375
+ papaparse: "^5.5.3",
4376
+ "partial-json": "^0.1.7",
4377
+ "pdf-lib": "^1.17.1",
4378
+ pino: "^10.0.0",
4379
+ "pino-pretty": "^13.1.2",
4389
4380
  prettier: "^3.6.2",
4381
+ "reflect-metadata": "^0.2.2",
4382
+ repomix: "^1.7.0",
4383
+ "sanitize-html": "^2.17.0",
4384
+ tslib: "^2.8.1",
4385
+ tsyringe: "^4.10.0",
4390
4386
  typedoc: "^0.28.14",
4391
4387
  typescript: "^5.9.3",
4392
4388
  "typescript-eslint": "8.46.0",
4389
+ validator: "13.15.15",
4393
4390
  vite: "7.1.9",
4394
4391
  "vite-tsconfig-paths": "^5.1.4",
4395
- vitest: "^3.2.4"
4392
+ vitest: "^3.2.4",
4393
+ zod: "^3.23.8"
4396
4394
  },
4397
4395
  keywords: [
4398
4396
  "ai-agent",
@@ -101104,7 +101102,7 @@ var init_logger = __esm(() => {
101104
101102
  static getInstance() {
101105
101103
  return Logger.instance;
101106
101104
  }
101107
- async createPinoLogger(level) {
101105
+ async createPinoLogger(level, transportType) {
101108
101106
  const pinoLevel = mcpToPinoLevel[level] || "info";
101109
101107
  const pinoOptions = {
101110
101108
  level: pinoLevel,
@@ -101126,7 +101124,8 @@ var init_logger = __esm(() => {
101126
101124
  const transports = [];
101127
101125
  const isDevelopment = config.environment === "development";
101128
101126
  const isTest = config.environment === "testing";
101129
- if (isDevelopment && !isServerless2) {
101127
+ const useColoredOutput = isDevelopment && transportType !== "stdio";
101128
+ if (useColoredOutput && !isServerless2) {
101130
101129
  try {
101131
101130
  const { createRequire: createRequire2 } = await import("node:module");
101132
101131
  const require2 = createRequire2(import.meta.url);
@@ -101183,7 +101182,7 @@ var init_logger = __esm(() => {
101183
101182
  }
101184
101183
  });
101185
101184
  }
101186
- async initialize(level = "info") {
101185
+ async initialize(level = "info", transportType) {
101187
101186
  if (this.initialized) {
101188
101187
  this.warning("Logger already initialized.", requestContextService.createRequestContext({
101189
101188
  operation: "loggerReinit"
@@ -101191,7 +101190,7 @@ var init_logger = __esm(() => {
101191
101190
  return;
101192
101191
  }
101193
101192
  this.currentMcpLevel = level;
101194
- this.pinoLogger = await this.createPinoLogger(level);
101193
+ this.pinoLogger = await this.createPinoLogger(level, transportType);
101195
101194
  this.interactionLogger = await this.createInteractionLogger();
101196
101195
  if (!isServerless2 && !this.cleanupTimer) {
101197
101196
  this.cleanupTimer = setInterval(() => this.flushSuppressedMessages(), this.rateLimitWindow);
@@ -151931,13 +151930,24 @@ function detectRuntime2() {
151931
151930
  }
151932
151931
  return "node";
151933
151932
  }
151934
- async function spawnWithBun(args, cwd, env, timeout) {
151933
+ async function spawnWithBun(args, cwd, env, timeout, signal) {
151935
151934
  const bunApi = globalThis.Bun;
151935
+ if (signal?.aborted) {
151936
+ throw new Error(`Git command cancelled before execution: git ${args.join(" ")}`);
151937
+ }
151936
151938
  const proc = bunApi.spawn(["git", ...args], {
151937
151939
  cwd,
151938
151940
  env,
151939
151941
  stdio: ["ignore", "pipe", "pipe"]
151940
151942
  });
151943
+ const abortPromise = new Promise((_, reject) => {
151944
+ if (signal) {
151945
+ signal.addEventListener("abort", () => {
151946
+ proc.kill();
151947
+ reject(new Error(`Git command cancelled: git ${args.join(" ")}`));
151948
+ }, { once: true });
151949
+ }
151950
+ });
151941
151951
  const timeoutPromise = new Promise((_, reject) => {
151942
151952
  const timeoutId = setTimeout(() => {
151943
151953
  proc.kill();
@@ -151945,7 +151955,11 @@ async function spawnWithBun(args, cwd, env, timeout) {
151945
151955
  }, timeout);
151946
151956
  proc.exited.finally(() => clearTimeout(timeoutId));
151947
151957
  });
151948
- const exitCode = await Promise.race([proc.exited, timeoutPromise]);
151958
+ const exitCode = await Promise.race([
151959
+ proc.exited,
151960
+ timeoutPromise,
151961
+ ...signal ? [abortPromise] : []
151962
+ ]);
151949
151963
  const [stdout, stderr] = await Promise.all([
151950
151964
  proc.stdout.text(),
151951
151965
  proc.stderr.text()
@@ -151958,8 +151972,12 @@ Stdout: ${stdout}`;
151958
151972
  }
151959
151973
  return { stdout, stderr };
151960
151974
  }
151961
- async function spawnWithNode(args, cwd, env, timeout) {
151975
+ async function spawnWithNode(args, cwd, env, timeout, signal) {
151962
151976
  return new Promise((resolve, reject) => {
151977
+ if (signal?.aborted) {
151978
+ reject(new Error(`Git command cancelled before execution: ${args.join(" ")}`));
151979
+ return;
151980
+ }
151963
151981
  const proc = spawn("git", args, {
151964
151982
  cwd,
151965
151983
  env,
@@ -151973,16 +151991,29 @@ async function spawnWithNode(args, cwd, env, timeout) {
151973
151991
  proc.stderr.on("data", (chunk) => {
151974
151992
  stderrChunks.push(chunk);
151975
151993
  });
151994
+ const abortHandler = () => {
151995
+ proc.kill("SIGTERM");
151996
+ reject(new Error(`Git command cancelled: ${args.join(" ")}`));
151997
+ };
151998
+ if (signal) {
151999
+ signal.addEventListener("abort", abortHandler, { once: true });
152000
+ }
151976
152001
  const timeoutHandle = setTimeout(() => {
151977
152002
  proc.kill("SIGTERM");
151978
152003
  reject(new Error(`Git command timed out after ${timeout / 1000}s: ${args.join(" ")}`));
151979
152004
  }, timeout);
151980
152005
  proc.on("error", (error) => {
151981
152006
  clearTimeout(timeoutHandle);
152007
+ if (signal) {
152008
+ signal.removeEventListener("abort", abortHandler);
152009
+ }
151982
152010
  reject(error);
151983
152011
  });
151984
152012
  proc.on("close", (exitCode) => {
151985
152013
  clearTimeout(timeoutHandle);
152014
+ if (signal) {
152015
+ signal.removeEventListener("abort", abortHandler);
152016
+ }
151986
152017
  const stdout = Buffer.concat(stdoutChunks).toString("utf-8");
151987
152018
  const stderr = Buffer.concat(stderrChunks).toString("utf-8");
151988
152019
  if (exitCode !== 0) {
@@ -151996,12 +152027,12 @@ Stdout: ${stdout}`;
151996
152027
  });
151997
152028
  });
151998
152029
  }
151999
- async function spawnGitCommand(args, cwd, env, timeout = 60000) {
152030
+ async function spawnGitCommand(args, cwd, env, timeout = 60000, signal) {
152000
152031
  const runtime2 = detectRuntime2();
152001
152032
  if (runtime2 === "bun") {
152002
- return spawnWithBun(args, cwd, env, timeout);
152033
+ return spawnWithBun(args, cwd, env, timeout, signal);
152003
152034
  } else {
152004
- return spawnWithNode(args, cwd, env, timeout);
152035
+ return spawnWithNode(args, cwd, env, timeout, signal);
152005
152036
  }
152006
152037
  }
152007
152038
 
@@ -172126,6 +172157,163 @@ var httpErrorHandler = async (err, c) => {
172126
172157
  return c.json(errorResponse);
172127
172158
  };
172128
172159
 
172160
+ // src/mcp-server/transports/http/sessionManager.ts
172161
+ init_utils();
172162
+
172163
+ class SessionManager {
172164
+ static instance = null;
172165
+ sessions = new Map;
172166
+ cleanupIntervalId = null;
172167
+ staleTimeoutMs;
172168
+ cleanupIntervalMs;
172169
+ constructor(staleTimeoutMs = 30 * 60 * 1000, cleanupIntervalMs = 5 * 60 * 1000) {
172170
+ this.staleTimeoutMs = staleTimeoutMs;
172171
+ this.cleanupIntervalMs = cleanupIntervalMs;
172172
+ this.startCleanupInterval();
172173
+ }
172174
+ static getInstance(staleTimeoutMs, cleanupIntervalMs) {
172175
+ if (!SessionManager.instance) {
172176
+ SessionManager.instance = new SessionManager(staleTimeoutMs, cleanupIntervalMs);
172177
+ }
172178
+ return SessionManager.instance;
172179
+ }
172180
+ static resetInstance() {
172181
+ if (SessionManager.instance) {
172182
+ SessionManager.instance.stopCleanupInterval();
172183
+ SessionManager.instance = null;
172184
+ }
172185
+ }
172186
+ createSession(sessionId, clientId, tenantId) {
172187
+ const now2 = Date.now();
172188
+ const metadata = {
172189
+ sessionId,
172190
+ createdAt: now2,
172191
+ lastActivityAt: now2,
172192
+ ...clientId !== undefined && { clientId },
172193
+ ...tenantId !== undefined && { tenantId }
172194
+ };
172195
+ this.sessions.set(sessionId, metadata);
172196
+ logger.debug("Created new MCP session", {
172197
+ ...requestContextService.createRequestContext({
172198
+ operation: "SessionManager.createSession"
172199
+ }),
172200
+ sessionId,
172201
+ ...clientId !== undefined && { clientId },
172202
+ ...tenantId !== undefined && { tenantId },
172203
+ totalSessions: this.sessions.size
172204
+ });
172205
+ return sessionId;
172206
+ }
172207
+ isSessionValid(sessionId) {
172208
+ const session = this.sessions.get(sessionId);
172209
+ if (!session) {
172210
+ return false;
172211
+ }
172212
+ const now2 = Date.now();
172213
+ const age = now2 - session.lastActivityAt;
172214
+ if (age > this.staleTimeoutMs) {
172215
+ logger.info("Session expired due to inactivity", {
172216
+ ...requestContextService.createRequestContext({
172217
+ operation: "SessionManager.isSessionValid"
172218
+ }),
172219
+ sessionId,
172220
+ ageMs: age,
172221
+ staleTimeoutMs: this.staleTimeoutMs
172222
+ });
172223
+ this.sessions.delete(sessionId);
172224
+ return false;
172225
+ }
172226
+ return true;
172227
+ }
172228
+ touchSession(sessionId) {
172229
+ const session = this.sessions.get(sessionId);
172230
+ if (session) {
172231
+ session.lastActivityAt = Date.now();
172232
+ }
172233
+ }
172234
+ terminateSession(sessionId) {
172235
+ const existed = this.sessions.has(sessionId);
172236
+ this.sessions.delete(sessionId);
172237
+ if (existed) {
172238
+ logger.info("Session explicitly terminated", {
172239
+ ...requestContextService.createRequestContext({
172240
+ operation: "SessionManager.terminateSession"
172241
+ }),
172242
+ sessionId,
172243
+ remainingSessions: this.sessions.size
172244
+ });
172245
+ }
172246
+ return existed;
172247
+ }
172248
+ getSessionMetadata(sessionId) {
172249
+ if (!this.isSessionValid(sessionId)) {
172250
+ return null;
172251
+ }
172252
+ return this.sessions.get(sessionId) ?? null;
172253
+ }
172254
+ getActiveSessionCount() {
172255
+ return this.sessions.size;
172256
+ }
172257
+ startCleanupInterval() {
172258
+ if (this.cleanupIntervalId) {
172259
+ return;
172260
+ }
172261
+ this.cleanupIntervalId = setInterval(() => {
172262
+ this.cleanupStaleSessions();
172263
+ }, this.cleanupIntervalMs);
172264
+ logger.info("Session cleanup interval started", {
172265
+ ...requestContextService.createRequestContext({
172266
+ operation: "SessionManager.startCleanupInterval"
172267
+ }),
172268
+ cleanupIntervalMs: this.cleanupIntervalMs,
172269
+ staleTimeoutMs: this.staleTimeoutMs
172270
+ });
172271
+ }
172272
+ stopCleanupInterval() {
172273
+ if (this.cleanupIntervalId) {
172274
+ clearInterval(this.cleanupIntervalId);
172275
+ this.cleanupIntervalId = null;
172276
+ logger.info("Session cleanup interval stopped", {
172277
+ ...requestContextService.createRequestContext({
172278
+ operation: "SessionManager.stopCleanupInterval"
172279
+ })
172280
+ });
172281
+ }
172282
+ }
172283
+ cleanupStaleSessions() {
172284
+ const now2 = Date.now();
172285
+ const sessionsBefore = this.sessions.size;
172286
+ let removedCount = 0;
172287
+ for (const [sessionId, metadata] of this.sessions.entries()) {
172288
+ const age = now2 - metadata.lastActivityAt;
172289
+ if (age > this.staleTimeoutMs) {
172290
+ this.sessions.delete(sessionId);
172291
+ removedCount++;
172292
+ }
172293
+ }
172294
+ if (removedCount > 0) {
172295
+ logger.notice("Cleaned up stale sessions", {
172296
+ ...requestContextService.createRequestContext({
172297
+ operation: "SessionManager.cleanupStaleSessions"
172298
+ }),
172299
+ removedCount,
172300
+ sessionsBefore,
172301
+ sessionsAfter: this.sessions.size
172302
+ });
172303
+ }
172304
+ }
172305
+ clearAllSessions() {
172306
+ const count = this.sessions.size;
172307
+ this.sessions.clear();
172308
+ logger.warning("All sessions cleared", {
172309
+ ...requestContextService.createRequestContext({
172310
+ operation: "SessionManager.clearAllSessions"
172311
+ }),
172312
+ clearedCount: count
172313
+ });
172314
+ }
172315
+ }
172316
+
172129
172317
  // src/mcp-server/transports/http/httpTransport.ts
172130
172318
  init_utils();
172131
172319
 
@@ -172142,6 +172330,11 @@ function createHttpApp(mcpServer, parentContext) {
172142
172330
  ...parentContext,
172143
172331
  component: "HttpTransportSetup"
172144
172332
  };
172333
+ const sessionManager = SessionManager.getInstance(config.mcpStatefulSessionStaleTimeoutMs);
172334
+ logger.info("Session manager initialized", {
172335
+ ...transportContext,
172336
+ staleTimeoutMs: config.mcpStatefulSessionStaleTimeoutMs
172337
+ });
172145
172338
  const allowedOrigin = Array.isArray(config.mcpAllowedOrigins) && config.mcpAllowedOrigins.length > 0 ? config.mcpAllowedOrigins : "*";
172146
172339
  app.use("*", cors({
172147
172340
  origin: allowedOrigin,
@@ -172190,6 +172383,35 @@ function createHttpApp(mcpServer, parentContext) {
172190
172383
  } else {
172191
172384
  logger.info("Authentication is disabled; MCP endpoint is unprotected.", transportContext);
172192
172385
  }
172386
+ app.delete(config.mcpHttpEndpointPath, (c) => {
172387
+ const sessionId = c.req.header("mcp-session-id");
172388
+ if (!sessionId) {
172389
+ return c.json({
172390
+ jsonrpc: "2.0",
172391
+ error: {
172392
+ code: -32600,
172393
+ message: "Mcp-Session-Id header required for DELETE"
172394
+ },
172395
+ id: null
172396
+ }, 400);
172397
+ }
172398
+ const terminated = sessionManager.terminateSession(sessionId);
172399
+ if (!terminated) {
172400
+ return c.json({
172401
+ jsonrpc: "2.0",
172402
+ error: {
172403
+ code: -32001,
172404
+ message: "Session not found or already expired"
172405
+ },
172406
+ id: null
172407
+ }, 404);
172408
+ }
172409
+ logger.info("Session terminated via DELETE", {
172410
+ ...transportContext,
172411
+ sessionId
172412
+ });
172413
+ return c.body(null, 204);
172414
+ });
172193
172415
  app.all(config.mcpHttpEndpointPath, async (c) => {
172194
172416
  const protocolVersion = c.req.header("mcp-protocol-version") ?? "2025-03-26";
172195
172417
  logger.debug("Handling MCP request.", {
@@ -172205,12 +172427,50 @@ function createHttpApp(mcpServer, parentContext) {
172205
172427
  protocolVersion,
172206
172428
  supportedVersions
172207
172429
  });
172430
+ return c.json({
172431
+ jsonrpc: "2.0",
172432
+ error: {
172433
+ code: -32600,
172434
+ message: `Unsupported MCP protocol version: ${protocolVersion}`,
172435
+ data: {
172436
+ requested: protocolVersion,
172437
+ supported: supportedVersions
172438
+ }
172439
+ },
172440
+ id: null
172441
+ }, 400);
172208
172442
  }
172209
172443
  const sessionId = c.req.header("mcp-session-id") ?? randomUUID();
172444
+ if (c.req.header("mcp-session-id") && !sessionManager.isSessionValid(sessionId)) {
172445
+ logger.warning("Invalid or expired session ID", {
172446
+ ...transportContext,
172447
+ sessionId
172448
+ });
172449
+ return c.json({
172450
+ jsonrpc: "2.0",
172451
+ error: {
172452
+ code: -32001,
172453
+ message: "Session expired or invalid. Please reinitialize."
172454
+ },
172455
+ id: null
172456
+ }, 404);
172457
+ }
172458
+ if (!c.req.header("mcp-session-id")) {
172459
+ logger.debug("New session will be created", {
172460
+ ...transportContext,
172461
+ sessionId
172462
+ });
172463
+ } else {
172464
+ sessionManager.touchSession(sessionId);
172465
+ }
172210
172466
  const transport = new McpSessionTransport(sessionId);
172211
172467
  const handleRpc = async () => {
172212
172468
  await mcpServer.connect(transport);
172213
172469
  const response = await transport.handleRequest(c);
172470
+ if (response && !c.req.header("mcp-session-id")) {
172471
+ const store = authContext.getStore();
172472
+ sessionManager.createSession(sessionId, store?.authInfo.clientId, store?.authInfo.tenantId);
172473
+ }
172214
172474
  if (response) {
172215
172475
  return response;
172216
172476
  }
@@ -172306,6 +172566,9 @@ async function stopHttpTransport(server, parentContext) {
172306
172566
  transportType: "Http"
172307
172567
  };
172308
172568
  logger.info("Attempting to stop http transport...", operationContext);
172569
+ const sessionManager = SessionManager.getInstance();
172570
+ sessionManager.stopCleanupInterval();
172571
+ logger.info("Session cleanup interval stopped", operationContext);
172309
172572
  return new Promise((resolve, reject) => {
172310
172573
  server.close((err) => {
172311
172574
  if (err) {
@@ -172602,7 +172865,7 @@ var start = async () => {
172602
172865
  console.warn(`[Startup Warning] Invalid MCP_LOG_LEVEL "${initialLogLevelConfig}". Defaulting to "info".`);
172603
172866
  }
172604
172867
  }
172605
- await logger.initialize(validatedMcpLogLevel);
172868
+ await logger.initialize(validatedMcpLogLevel, config2.mcpTransportType);
172606
172869
  logger.info(`Logger initialized. Effective MCP logging level: ${validatedMcpLogLevel}.`, requestContextService.createRequestContext({ operation: "LoggerInit" }));
172607
172870
  const runtime2 = detectRuntime();
172608
172871
  const runtimeDesc = getRuntimeDescription();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyanheads/git-mcp-server",
3
- "version": "2.4.9",
3
+ "version": "2.5.2",
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",
@@ -66,33 +66,12 @@
66
66
  "zod": "3.23.8",
67
67
  "typescript": "5.9.3"
68
68
  },
69
- "dependencies": {
69
+ "devDependencies": {
70
+ "@cloudflare/workers-types": "^4.20251011.0",
71
+ "@eslint/js": "^9.37.0",
70
72
  "@hono/mcp": "^0.1.4",
71
73
  "@hono/node-server": "^1.19.5",
72
74
  "@modelcontextprotocol/sdk": "^1.20.0",
73
- "@supabase/supabase-js": "^2.75.0",
74
- "axios": "^1.12.2",
75
- "chrono-node": "^2.9.0",
76
- "dotenv": "^17.2.3",
77
- "fast-xml-parser": "^5.3.0",
78
- "hono": "^4.9.12",
79
- "ignore": "^7.0.5",
80
- "jose": "^6.1.0",
81
- "js-yaml": "^4.1.0",
82
- "node-cron": "^4.2.1",
83
- "openai": "^6.3.0",
84
- "papaparse": "^5.5.3",
85
- "partial-json": "^0.1.7",
86
- "pdf-lib": "^1.17.1",
87
- "pino": "^10.0.0",
88
- "pino-pretty": "^13.1.2",
89
- "reflect-metadata": "^0.2.2",
90
- "repomix": "^1.7.0",
91
- "sanitize-html": "^2.17.0",
92
- "tslib": "^2.8.1",
93
- "tsyringe": "^4.10.0",
94
- "validator": "13.15.15",
95
- "zod": "^3.23.8",
96
75
  "@opentelemetry/api": "^1.9.0",
97
76
  "@opentelemetry/auto-instrumentations-node": "^0.65.0",
98
77
  "@opentelemetry/exporter-metrics-otlp-http": "^0.206.0",
@@ -102,11 +81,8 @@
102
81
  "@opentelemetry/sdk-metrics": "^2.1.0",
103
82
  "@opentelemetry/sdk-node": "^0.206.0",
104
83
  "@opentelemetry/sdk-trace-node": "^2.1.0",
105
- "@opentelemetry/semantic-conventions": "^1.37.0"
106
- },
107
- "devDependencies": {
108
- "@cloudflare/workers-types": "^4.20251011.0",
109
- "@eslint/js": "^9.37.0",
84
+ "@opentelemetry/semantic-conventions": "^1.37.0",
85
+ "@supabase/supabase-js": "^2.75.0",
110
86
  "@types/bun": "^1.3.0",
111
87
  "@types/js-yaml": "^4.0.9",
112
88
  "@types/node": "^24.7.2",
@@ -117,21 +93,43 @@
117
93
  "@vitest/coverage-v8": "3.2.4",
118
94
  "ajv": "^8.17.1",
119
95
  "ajv-formats": "^3.0.1",
96
+ "axios": "^1.12.2",
120
97
  "bun-types": "^1.3.0",
98
+ "chrono-node": "^2.9.0",
121
99
  "clipboardy": "^5.0.0",
122
100
  "depcheck": "^1.4.7",
101
+ "dotenv": "^17.2.3",
123
102
  "eslint": "^9.37.0",
124
103
  "execa": "^9.6.0",
104
+ "fast-xml-parser": "^5.3.0",
125
105
  "globals": "^16.4.0",
106
+ "hono": "^4.9.12",
126
107
  "husky": "^9.1.7",
108
+ "ignore": "^7.0.5",
109
+ "jose": "^6.1.0",
110
+ "js-yaml": "^4.1.0",
127
111
  "msw": "^2.11.5",
112
+ "node-cron": "^4.2.1",
113
+ "openai": "^6.3.0",
114
+ "papaparse": "^5.5.3",
115
+ "partial-json": "^0.1.7",
116
+ "pdf-lib": "^1.17.1",
117
+ "pino": "^10.0.0",
118
+ "pino-pretty": "^13.1.2",
128
119
  "prettier": "^3.6.2",
120
+ "reflect-metadata": "^0.2.2",
121
+ "repomix": "^1.7.0",
122
+ "sanitize-html": "^2.17.0",
123
+ "tslib": "^2.8.1",
124
+ "tsyringe": "^4.10.0",
129
125
  "typedoc": "^0.28.14",
130
126
  "typescript": "^5.9.3",
131
127
  "typescript-eslint": "8.46.0",
128
+ "validator": "13.15.15",
132
129
  "vite": "7.1.9",
133
130
  "vite-tsconfig-paths": "^5.1.4",
134
- "vitest": "^3.2.4"
131
+ "vitest": "^3.2.4",
132
+ "zod": "^3.23.8"
135
133
  },
136
134
  "keywords": [
137
135
  "ai-agent",