@cyanheads/git-mcp-server 2.13.0 → 2.14.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 (3) hide show
  1. package/README.md +13 -13
  2. package/dist/index.js +1891 -1946
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -15284,7 +15284,7 @@ var package_default;
15284
15284
  var init_package = __esm(() => {
15285
15285
  package_default = {
15286
15286
  name: "@cyanheads/git-mcp-server",
15287
- version: "2.13.0",
15287
+ version: "2.14.2",
15288
15288
  mcpName: "io.github.cyanheads/git-mcp-server",
15289
15289
  description: "A secure and scalable Git MCP server enabling AI agents to perform comprehensive Git version control operations via STDIO and Streamable HTTP.",
15290
15290
  main: "dist/index.js",
@@ -105579,75 +105579,6 @@ var require_index_incubating = __commonJS((exports) => {
105579
105579
  __exportStar(require_experimental_events(), exports);
105580
105580
  });
105581
105581
 
105582
- // src/mcp-server/transports/auth/lib/authContext.ts
105583
- import { AsyncLocalStorage } from "async_hooks";
105584
- var authContext;
105585
- var init_authContext = __esm(() => {
105586
- authContext = new AsyncLocalStorage;
105587
- });
105588
-
105589
- // src/utils/internal/requestContext.ts
105590
- var import_api2, requestContextServiceInstance, requestContextService;
105591
- var init_requestContext = __esm(() => {
105592
- init_authContext();
105593
- init_utils();
105594
- init_logger();
105595
- import_api2 = __toESM(require_src(), 1);
105596
- requestContextServiceInstance = {
105597
- config: {},
105598
- configure(config3) {
105599
- this.config = {
105600
- ...this.config,
105601
- ...config3
105602
- };
105603
- const logContext = this.createRequestContext({
105604
- operation: "RequestContextService.configure",
105605
- additionalContext: { newConfigState: { ...this.config } }
105606
- });
105607
- logger.debug("RequestContextService configuration updated", logContext);
105608
- return { ...this.config };
105609
- },
105610
- getConfig() {
105611
- return { ...this.config };
105612
- },
105613
- createRequestContext(params = {}) {
105614
- const { parentContext, additionalContext, operation, ...rest } = params;
105615
- const inheritedContext = parentContext && typeof parentContext === "object" ? { ...parentContext } : {};
105616
- let inheritedTenantId;
105617
- if (inheritedContext && typeof inheritedContext === "object" && "tenantId" in inheritedContext && typeof inheritedContext.tenantId === "string") {
105618
- inheritedTenantId = inheritedContext.tenantId;
105619
- }
105620
- const authStore = authContext.getStore();
105621
- const tenantIdFromAuth = authStore?.authInfo?.tenantId;
105622
- const inheritedRequestId = inheritedContext.requestId;
105623
- const requestId = typeof inheritedRequestId === "string" && inheritedRequestId ? inheritedRequestId : generateRequestContextId();
105624
- const timestamp = new Date().toISOString();
105625
- const restTenantId = typeof rest.tenantId === "string" ? rest.tenantId : undefined;
105626
- const additionalTenantId = additionalContext && typeof additionalContext === "object" && typeof additionalContext.tenantId === "string" ? additionalContext.tenantId : undefined;
105627
- const resolvedTenantId = additionalTenantId ?? restTenantId ?? inheritedTenantId ?? tenantIdFromAuth;
105628
- const context = {
105629
- ...inheritedContext,
105630
- ...rest,
105631
- requestId,
105632
- timestamp,
105633
- ...resolvedTenantId ? { tenantId: resolvedTenantId } : {},
105634
- ...additionalContext && typeof additionalContext === "object" ? additionalContext : {},
105635
- ...operation && typeof operation === "string" ? { operation } : {}
105636
- };
105637
- const activeSpan = import_api2.trace.getActiveSpan();
105638
- if (activeSpan && typeof activeSpan.spanContext === "function") {
105639
- const spanContext = activeSpan.spanContext();
105640
- if (spanContext) {
105641
- context.traceId = spanContext.traceId;
105642
- context.spanId = spanContext.spanId;
105643
- }
105644
- }
105645
- return context;
105646
- }
105647
- };
105648
- requestContextService = requestContextServiceInstance;
105649
- });
105650
-
105651
105582
  // node_modules/validator/lib/util/assertString.js
105652
105583
  var require_assertString = __commonJS((exports, module) => {
105653
105584
  Object.defineProperty(exports, "__esModule", {
@@ -112046,1408 +111977,6 @@ var require_validator = __commonJS((exports, module) => {
112046
111977
  module.exports.default = exports.default;
112047
111978
  });
112048
111979
 
112049
- // src/utils/security/sanitization.ts
112050
- class Sanitization {
112051
- static instance;
112052
- sensitiveFields = [
112053
- "password",
112054
- "token",
112055
- "secret",
112056
- "apiKey",
112057
- "credential",
112058
- "jwt",
112059
- "ssn",
112060
- "cvv",
112061
- "authorization",
112062
- "cookie",
112063
- "clientsecret",
112064
- "client_secret",
112065
- "private_key",
112066
- "privatekey"
112067
- ];
112068
- constructor() {}
112069
- static getInstance() {
112070
- if (!Sanitization.instance) {
112071
- Sanitization.instance = new Sanitization;
112072
- }
112073
- return Sanitization.instance;
112074
- }
112075
- setSensitiveFields(fields) {
112076
- this.sensitiveFields = [
112077
- ...new Set([
112078
- ...this.sensitiveFields,
112079
- ...fields.map((f3) => f3.toLowerCase())
112080
- ])
112081
- ];
112082
- const logContext = requestContextService.createRequestContext({
112083
- operation: "Sanitization.setSensitiveFields",
112084
- additionalContext: {
112085
- newSensitiveFieldCount: this.sensitiveFields.length
112086
- }
112087
- });
112088
- logger.debug("Updated sensitive fields list for log sanitization", logContext);
112089
- }
112090
- getSensitiveFields() {
112091
- return [...this.sensitiveFields];
112092
- }
112093
- getSensitivePinoFields() {
112094
- return this.sensitiveFields.map((field) => field.replace(/[-_]/g, ""));
112095
- }
112096
- sanitizeUrl(input, allowedProtocols = ["http", "https"]) {
112097
- try {
112098
- const trimmedInput = input.trim();
112099
- if (!import_validator.default.isURL(trimmedInput, {
112100
- protocols: allowedProtocols,
112101
- require_protocol: true,
112102
- require_host: true
112103
- })) {
112104
- throw new Error("Invalid URL format or protocol not in allowed list.");
112105
- }
112106
- const lowercasedInput = trimmedInput.toLowerCase();
112107
- if (lowercasedInput.startsWith("javascript:") || lowercasedInput.startsWith("data:") || lowercasedInput.startsWith("vbscript:")) {
112108
- throw new Error("Disallowed pseudo-protocol (javascript:, data:, or vbscript:) in URL.");
112109
- }
112110
- return trimmedInput;
112111
- } catch (error48) {
112112
- throw new McpError(-32007 /* ValidationError */, error48 instanceof Error ? error48.message : "Invalid or unsafe URL provided.", { input });
112113
- }
112114
- }
112115
- sanitizePath(input, options = {}) {
112116
- if (isServerless || !pathModule) {
112117
- throw new McpError(-32603 /* InternalError */, "File-based path sanitization is not supported in this environment.");
112118
- }
112119
- const path2 = pathModule;
112120
- const originalInput = input;
112121
- const resolvedRootDir = options.rootDir ? path2.resolve(options.rootDir) : undefined;
112122
- const effectiveOptions = {
112123
- toPosix: options.toPosix ?? false,
112124
- allowAbsolute: options.allowAbsolute ?? false,
112125
- ...resolvedRootDir && { rootDir: resolvedRootDir }
112126
- };
112127
- let wasAbsoluteInitially = false;
112128
- try {
112129
- if (!input || typeof input !== "string")
112130
- throw new Error("Invalid path input: must be a non-empty string.");
112131
- if (input.includes("\x00"))
112132
- throw new Error("Path contains null byte, which is disallowed.");
112133
- let normalized = path2.normalize(input);
112134
- wasAbsoluteInitially = path2.isAbsolute(normalized);
112135
- if (effectiveOptions.toPosix) {
112136
- normalized = normalized.replace(/\\/g, "/");
112137
- }
112138
- let finalSanitizedPath;
112139
- if (resolvedRootDir) {
112140
- let fullPath;
112141
- if (path2.isAbsolute(normalized)) {
112142
- fullPath = path2.normalize(normalized);
112143
- } else {
112144
- fullPath = path2.resolve(resolvedRootDir, normalized);
112145
- }
112146
- const normalizedRoot = path2.normalize(resolvedRootDir);
112147
- const normalizedFull = path2.normalize(fullPath);
112148
- if (!normalizedFull.startsWith(normalizedRoot + path2.sep) && normalizedFull !== normalizedRoot) {
112149
- throw new Error("Path traversal detected: attempts to escape the defined root directory.");
112150
- }
112151
- finalSanitizedPath = path2.relative(normalizedRoot, normalizedFull);
112152
- finalSanitizedPath = finalSanitizedPath === "" ? "." : finalSanitizedPath;
112153
- if (path2.isAbsolute(finalSanitizedPath) && !effectiveOptions.allowAbsolute) {
112154
- throw new Error("Path resolved to absolute outside root when absolute paths are disallowed.");
112155
- }
112156
- } else {
112157
- if (path2.isAbsolute(normalized)) {
112158
- if (!effectiveOptions.allowAbsolute) {
112159
- throw new Error("Absolute paths are disallowed by current options.");
112160
- } else {
112161
- finalSanitizedPath = normalized;
112162
- }
112163
- } else {
112164
- const resolvedAgainstCwd = path2.resolve(normalized);
112165
- const currentWorkingDir = path2.resolve(".");
112166
- if (!resolvedAgainstCwd.startsWith(currentWorkingDir + path2.sep) && resolvedAgainstCwd !== currentWorkingDir) {
112167
- throw new Error("Relative path traversal detected (escapes current working directory context).");
112168
- }
112169
- finalSanitizedPath = normalized;
112170
- }
112171
- }
112172
- return {
112173
- sanitizedPath: finalSanitizedPath,
112174
- originalInput,
112175
- wasAbsolute: wasAbsoluteInitially,
112176
- convertedToRelative: wasAbsoluteInitially && !path2.isAbsolute(finalSanitizedPath) && !effectiveOptions.allowAbsolute,
112177
- optionsUsed: effectiveOptions
112178
- };
112179
- } catch (error48) {
112180
- logger.warning("Path sanitization error", requestContextService.createRequestContext({
112181
- operation: "Sanitization.sanitizePath.error",
112182
- additionalContext: {
112183
- originalPathInput: originalInput,
112184
- pathOptionsUsed: effectiveOptions,
112185
- errorMessage: error48 instanceof Error ? error48.message : String(error48)
112186
- }
112187
- }));
112188
- throw new McpError(-32007 /* ValidationError */, error48 instanceof Error ? error48.message : "Invalid or unsafe path provided.", { input: originalInput });
112189
- }
112190
- }
112191
- sanitizeJson(input, maxSize) {
112192
- try {
112193
- if (typeof input !== "string")
112194
- throw new Error("Invalid input: expected a JSON string.");
112195
- const computeBytes = (s2) => {
112196
- if (typeof Buffer !== "undefined" && typeof Buffer.byteLength === "function") {
112197
- return Buffer.byteLength(s2, "utf8");
112198
- }
112199
- if (typeof TextEncoder !== "undefined") {
112200
- return new TextEncoder().encode(s2).length;
112201
- }
112202
- return s2.length;
112203
- };
112204
- if (maxSize !== undefined && computeBytes(input) > maxSize) {
112205
- throw new McpError(-32007 /* ValidationError */, `JSON string exceeds maximum allowed size of ${maxSize} bytes.`, { actualSize: computeBytes(input), maxSize });
112206
- }
112207
- return JSON.parse(input);
112208
- } catch (error48) {
112209
- if (error48 instanceof McpError)
112210
- throw error48;
112211
- throw new McpError(-32007 /* ValidationError */, error48 instanceof Error ? error48.message : "Invalid JSON format.", {
112212
- inputPreview: input.length > 100 ? `${input.substring(0, 100)}...` : input
112213
- });
112214
- }
112215
- }
112216
- sanitizeNumber(input, min, max) {
112217
- let value;
112218
- if (typeof input === "string") {
112219
- const trimmedInput = input.trim();
112220
- if (trimmedInput === "" || !import_validator.default.isNumeric(trimmedInput)) {
112221
- throw new McpError(-32007 /* ValidationError */, "Invalid number format: input is empty or not numeric.", { input });
112222
- }
112223
- value = parseFloat(trimmedInput);
112224
- } else if (typeof input === "number") {
112225
- value = input;
112226
- } else {
112227
- throw new McpError(-32007 /* ValidationError */, "Invalid input type: expected number or string.", { input: String(input) });
112228
- }
112229
- if (isNaN(value) || !isFinite(value)) {
112230
- throw new McpError(-32007 /* ValidationError */, "Invalid number value (NaN or Infinity).", { input });
112231
- }
112232
- let clamped = false;
112233
- const originalValueForLog = value;
112234
- if (min !== undefined && value < min) {
112235
- value = min;
112236
- clamped = true;
112237
- }
112238
- if (max !== undefined && value > max) {
112239
- value = max;
112240
- clamped = true;
112241
- }
112242
- if (clamped) {
112243
- logger.debug("Number clamped to range.", requestContextService.createRequestContext({
112244
- operation: "Sanitization.sanitizeNumber.clamped",
112245
- additionalContext: {
112246
- originalInput: String(input),
112247
- parsedValue: originalValueForLog,
112248
- minValue: min,
112249
- maxValue: max,
112250
- clampedValue: value
112251
- }
112252
- }));
112253
- }
112254
- return value;
112255
- }
112256
- sanitizeForLogging(input) {
112257
- try {
112258
- if (!input || typeof input !== "object")
112259
- return input;
112260
- const clonedInput = typeof globalThis.structuredClone === "function" ? globalThis.structuredClone(input) : JSON.parse(JSON.stringify(input));
112261
- this.redactSensitiveFields(clonedInput);
112262
- return clonedInput;
112263
- } catch (error48) {
112264
- logger.error("Error during log sanitization, returning placeholder.", requestContextService.createRequestContext({
112265
- operation: "Sanitization.sanitizeForLogging.error",
112266
- additionalContext: {
112267
- errorMessage: error48 instanceof Error ? error48.message : String(error48)
112268
- }
112269
- }));
112270
- return "[Log Sanitization Failed]";
112271
- }
112272
- }
112273
- redactSensitiveFields(obj) {
112274
- if (!obj || typeof obj !== "object")
112275
- return;
112276
- if (Array.isArray(obj)) {
112277
- obj.forEach((item) => this.redactSensitiveFields(item));
112278
- return;
112279
- }
112280
- const normalize = (str) => str.toLowerCase().replace(/[^a-z0-9]/g, "");
112281
- const normalizedSensitiveSet = new Set(this.sensitiveFields.map((f3) => normalize(f3)).filter(Boolean));
112282
- const wordSensitiveSet = new Set(this.sensitiveFields.map((f3) => f3.toLowerCase()).filter(Boolean));
112283
- for (const key in obj) {
112284
- if (Object.prototype.hasOwnProperty.call(obj, key)) {
112285
- const value = obj[key];
112286
- const normalizedKey = normalize(key);
112287
- const keyWords = key.replace(/([A-Z])/g, " $1").toLowerCase().split(/[\s_-]+/).filter(Boolean);
112288
- const isExactSensitive = normalizedSensitiveSet.has(normalizedKey);
112289
- const isWordSensitive = keyWords.some((w) => wordSensitiveSet.has(w));
112290
- const isSensitive = isExactSensitive || isWordSensitive;
112291
- if (isSensitive) {
112292
- obj[key] = "[REDACTED]";
112293
- } else if (value && typeof value === "object") {
112294
- this.redactSensitiveFields(value);
112295
- }
112296
- }
112297
- }
112298
- }
112299
- }
112300
- var import_validator, isServerless, pathModule, sanitization, sanitizeInputForLogging = (input) => sanitization.sanitizeForLogging(input);
112301
- var init_sanitization = __esm(() => {
112302
- init_errors3();
112303
- init_utils();
112304
- import_validator = __toESM(require_validator(), 1);
112305
- isServerless = typeof process === "undefined" || process.env.IS_SERVERLESS === "true";
112306
- if (!isServerless) {
112307
- import("path").then((mod2) => {
112308
- pathModule = mod2.default;
112309
- }).catch(() => {});
112310
- }
112311
- sanitization = Sanitization.getInstance();
112312
- });
112313
-
112314
- // src/utils/internal/logger.ts
112315
- import pino from "pino";
112316
- var mcpToPinoLevel, pinoToMcpLevelSeverity, isServerless2, Logger, logger;
112317
- var init_logger = __esm(() => {
112318
- init_config();
112319
- init_requestContext();
112320
- init_sanitization();
112321
- mcpToPinoLevel = {
112322
- emerg: "fatal",
112323
- alert: "fatal",
112324
- crit: "error",
112325
- error: "error",
112326
- warning: "warn",
112327
- notice: "info",
112328
- info: "info",
112329
- debug: "debug"
112330
- };
112331
- pinoToMcpLevelSeverity = {
112332
- fatal: 0,
112333
- error: 2,
112334
- warn: 4,
112335
- info: 6,
112336
- debug: 7
112337
- };
112338
- isServerless2 = typeof process === "undefined" || process.env.IS_SERVERLESS === "true";
112339
- Logger = class Logger {
112340
- static instance = new Logger;
112341
- pinoLogger;
112342
- interactionLogger;
112343
- initialized = false;
112344
- currentMcpLevel = "info";
112345
- transportType;
112346
- rateLimitThreshold = 10;
112347
- rateLimitWindow = 60000;
112348
- messageCounts = new Map;
112349
- suppressedMessages = new Map;
112350
- cleanupTimer;
112351
- constructor() {}
112352
- static getInstance() {
112353
- return Logger.instance;
112354
- }
112355
- async createPinoLogger(level, transportType) {
112356
- const pinoLevel = mcpToPinoLevel[level] || "info";
112357
- const pinoOptions = {
112358
- level: pinoLevel,
112359
- base: {
112360
- env: config2.environment,
112361
- version: config2.mcpServerVersion,
112362
- pid: !isServerless2 ? process.pid : undefined
112363
- },
112364
- redact: {
112365
- paths: sanitization.getSensitivePinoFields(),
112366
- censor: "[REDACTED]"
112367
- }
112368
- };
112369
- if (isServerless2) {
112370
- return pino(pinoOptions);
112371
- }
112372
- const { default: fs2 } = await import("fs");
112373
- const { default: path2 } = await import("path");
112374
- const transports = [];
112375
- const isDevelopment = config2.environment === "development";
112376
- const isTest = config2.environment === "testing";
112377
- const noColorEnv = process.env.NO_COLOR === "1" || process.env.FORCE_COLOR === "0";
112378
- const useColoredOutput = isDevelopment && transportType !== "stdio" && !noColorEnv;
112379
- if (useColoredOutput && !isServerless2) {
112380
- try {
112381
- const { createRequire: createRequire2 } = await import("node:module");
112382
- const require2 = createRequire2(import.meta.url);
112383
- const prettyTarget = require2.resolve("pino-pretty");
112384
- transports.push({
112385
- target: prettyTarget,
112386
- options: { colorize: true, translateTime: "yyyy-mm-dd HH:MM:ss" }
112387
- });
112388
- } catch (err) {
112389
- if (process.stderr?.isTTY) {
112390
- console.warn(`[Logger Init] Pretty transport unavailable (${err instanceof Error ? err.message : String(err)}); falling back to stdout JSON.`);
112391
- }
112392
- transports.push({ target: "pino/file", options: { destination: 1 } });
112393
- }
112394
- } else if (!isTest) {
112395
- transports.push({ target: "pino/file", options: { destination: 2 } });
112396
- }
112397
- if (config2.logsPath) {
112398
- try {
112399
- if (!fs2.existsSync(config2.logsPath)) {
112400
- fs2.mkdirSync(config2.logsPath, { recursive: true });
112401
- }
112402
- transports.push({
112403
- level: pinoLevel,
112404
- target: "pino/file",
112405
- options: {
112406
- destination: path2.join(config2.logsPath, "combined.log"),
112407
- mkdir: true
112408
- }
112409
- });
112410
- transports.push({
112411
- level: "error",
112412
- target: "pino/file",
112413
- options: {
112414
- destination: path2.join(config2.logsPath, "error.log"),
112415
- mkdir: true
112416
- }
112417
- });
112418
- } catch (err) {
112419
- if (process.stderr?.isTTY) {
112420
- console.error(`[Logger Init] Failed to configure file logging: ${err instanceof Error ? err.message : String(err)}`);
112421
- }
112422
- }
112423
- }
112424
- return pino({ ...pinoOptions, transport: { targets: transports } });
112425
- }
112426
- async createInteractionLogger() {
112427
- if (isServerless2 || !config2.logsPath)
112428
- return;
112429
- const { default: path2 } = await import("path");
112430
- return pino({
112431
- transport: {
112432
- target: "pino/file",
112433
- options: {
112434
- destination: path2.join(config2.logsPath, "interactions.log"),
112435
- mkdir: true
112436
- }
112437
- }
112438
- });
112439
- }
112440
- async initialize(level = "info", transportType) {
112441
- if (this.initialized) {
112442
- this.warning("Logger already initialized.", requestContextService.createRequestContext({
112443
- operation: "loggerReinit"
112444
- }));
112445
- return;
112446
- }
112447
- this.currentMcpLevel = level;
112448
- this.transportType = transportType;
112449
- this.pinoLogger = await this.createPinoLogger(level, transportType);
112450
- this.interactionLogger = await this.createInteractionLogger();
112451
- if (!isServerless2 && !this.cleanupTimer) {
112452
- this.cleanupTimer = setInterval(() => this.flushSuppressedMessages(), this.rateLimitWindow);
112453
- this.cleanupTimer.unref?.();
112454
- }
112455
- this.initialized = true;
112456
- this.info(`Logger initialized. MCP level: ${level}.`, requestContextService.createRequestContext({ operation: "loggerInit" }));
112457
- }
112458
- setLevel(newLevel) {
112459
- if (!this.pinoLogger || !this.initialized) {
112460
- if (process.stderr?.isTTY) {
112461
- console.error("Cannot set level: Logger not initialized.");
112462
- }
112463
- return;
112464
- }
112465
- this.currentMcpLevel = newLevel;
112466
- this.pinoLogger.level = mcpToPinoLevel[newLevel] || "info";
112467
- this.info(`Log level changed to ${newLevel}.`, requestContextService.createRequestContext({
112468
- operation: "loggerSetLevel"
112469
- }));
112470
- }
112471
- async close() {
112472
- if (!this.initialized)
112473
- return Promise.resolve();
112474
- this.info("Logger shutting down.", requestContextService.createRequestContext({ operation: "loggerClose" }));
112475
- if (this.cleanupTimer)
112476
- clearInterval(this.cleanupTimer);
112477
- this.flushSuppressedMessages();
112478
- await Promise.all([
112479
- new Promise((resolve) => {
112480
- if (this.pinoLogger) {
112481
- this.pinoLogger.flush((err) => {
112482
- if (err && process.stderr?.isTTY && this.transportType !== "stdio") {
112483
- console.error("Error flushing main logger:", err);
112484
- }
112485
- resolve();
112486
- });
112487
- } else {
112488
- resolve();
112489
- }
112490
- }),
112491
- new Promise((resolve) => {
112492
- if (this.interactionLogger) {
112493
- this.interactionLogger.flush((err) => {
112494
- if (err && process.stderr?.isTTY && this.transportType !== "stdio") {
112495
- console.error("Error flushing interaction logger:", err);
112496
- }
112497
- resolve();
112498
- });
112499
- } else {
112500
- resolve();
112501
- }
112502
- })
112503
- ]);
112504
- this.initialized = false;
112505
- }
112506
- isInitialized() {
112507
- return this.initialized;
112508
- }
112509
- isRateLimited(message) {
112510
- const now = Date.now();
112511
- const entry = this.messageCounts.get(message);
112512
- if (!entry) {
112513
- this.messageCounts.set(message, { count: 1, firstSeen: now });
112514
- return false;
112515
- }
112516
- if (now - entry.firstSeen > this.rateLimitWindow) {
112517
- this.messageCounts.set(message, { count: 1, firstSeen: now });
112518
- return false;
112519
- }
112520
- entry.count++;
112521
- if (entry.count > this.rateLimitThreshold) {
112522
- this.suppressedMessages.set(message, (this.suppressedMessages.get(message) || 0) + 1);
112523
- return true;
112524
- }
112525
- return false;
112526
- }
112527
- flushSuppressedMessages() {
112528
- if (this.suppressedMessages.size === 0)
112529
- return;
112530
- for (const [message, count] of this.suppressedMessages.entries()) {
112531
- this.warning(`Log message suppressed ${count} times due to rate limiting.`, requestContextService.createRequestContext({
112532
- operation: "loggerRateLimitFlush",
112533
- additionalContext: { originalMessage: message }
112534
- }));
112535
- }
112536
- this.suppressedMessages.clear();
112537
- this.messageCounts.clear();
112538
- }
112539
- log(level, msg, context, error48) {
112540
- if (!this.pinoLogger || !this.initialized)
112541
- return;
112542
- const pinoLevel = mcpToPinoLevel[level] || "info";
112543
- const currentPinoLevel = mcpToPinoLevel[this.currentMcpLevel] || "info";
112544
- const levelSeverity = pinoToMcpLevelSeverity[pinoLevel];
112545
- const currentLevelSeverity = pinoToMcpLevelSeverity[currentPinoLevel];
112546
- if (typeof levelSeverity === "number" && typeof currentLevelSeverity === "number" && levelSeverity > currentLevelSeverity) {
112547
- return;
112548
- }
112549
- if (this.isRateLimited(msg))
112550
- return;
112551
- const logObject = { ...context };
112552
- if (error48)
112553
- logObject.err = pino.stdSerializers.err(error48);
112554
- this.pinoLogger[pinoLevel](logObject, msg);
112555
- }
112556
- debug(msg, context) {
112557
- this.log("debug", msg, context);
112558
- }
112559
- info(msg, context) {
112560
- this.log("info", msg, context);
112561
- }
112562
- notice(msg, context) {
112563
- this.log("notice", msg, context);
112564
- }
112565
- warning(msg, context) {
112566
- this.log("warning", msg, context);
112567
- }
112568
- error(msg, errorOrContext, context) {
112569
- const errorObj = errorOrContext instanceof Error ? errorOrContext : undefined;
112570
- const actualContext = errorOrContext instanceof Error ? context : errorOrContext;
112571
- this.log("error", msg, actualContext, errorObj);
112572
- }
112573
- crit(msg, errorOrContext, context) {
112574
- const errorObj = errorOrContext instanceof Error ? errorOrContext : undefined;
112575
- const actualContext = errorOrContext instanceof Error ? context : errorOrContext;
112576
- this.log("crit", msg, actualContext, errorObj);
112577
- }
112578
- alert(msg, errorOrContext, context) {
112579
- const errorObj = errorOrContext instanceof Error ? errorOrContext : undefined;
112580
- const actualContext = errorOrContext instanceof Error ? context : errorOrContext;
112581
- this.log("alert", msg, actualContext, errorObj);
112582
- }
112583
- emerg(msg, errorOrContext, context) {
112584
- const errorObj = errorOrContext instanceof Error ? errorOrContext : undefined;
112585
- const actualContext = errorOrContext instanceof Error ? context : errorOrContext;
112586
- this.log("emerg", msg, actualContext, errorObj);
112587
- }
112588
- fatal(msg, errorOrContext, context) {
112589
- this.emerg(msg, errorOrContext, context);
112590
- }
112591
- logInteraction(interactionName, data) {
112592
- if (!this.interactionLogger) {
112593
- if (!isServerless2)
112594
- this.warning("Interaction logger not available.", data.context || {});
112595
- return;
112596
- }
112597
- this.interactionLogger.info({ interactionName, ...data });
112598
- }
112599
- };
112600
- logger = Logger.getInstance();
112601
- });
112602
-
112603
- // src/utils/internal/error-handler/mappings.ts
112604
- var ERROR_TYPE_MAPPINGS, COMMON_ERROR_PATTERNS;
112605
- var init_mappings = __esm(() => {
112606
- ERROR_TYPE_MAPPINGS = {
112607
- SyntaxError: -32007 /* ValidationError */,
112608
- TypeError: -32007 /* ValidationError */,
112609
- ReferenceError: -32603 /* InternalError */,
112610
- RangeError: -32007 /* ValidationError */,
112611
- URIError: -32007 /* ValidationError */,
112612
- EvalError: -32603 /* InternalError */,
112613
- AggregateError: -32603 /* InternalError */
112614
- };
112615
- COMMON_ERROR_PATTERNS = [
112616
- {
112617
- pattern: /auth|unauthorized|unauthenticated|not.*logged.*in|invalid.*token|expired.*token/i,
112618
- errorCode: -32006 /* Unauthorized */
112619
- },
112620
- {
112621
- pattern: /permission|forbidden|access.*denied|not.*allowed/i,
112622
- errorCode: -32005 /* Forbidden */
112623
- },
112624
- {
112625
- pattern: /not found|missing|no such|doesn't exist|couldn't find/i,
112626
- errorCode: -32001 /* NotFound */
112627
- },
112628
- {
112629
- pattern: /invalid|validation|malformed|bad request|wrong format|missing required/i,
112630
- errorCode: -32007 /* ValidationError */
112631
- },
112632
- {
112633
- pattern: /conflict|already exists|duplicate|unique constraint/i,
112634
- errorCode: -32002 /* Conflict */
112635
- },
112636
- {
112637
- pattern: /rate limit|too many requests|throttled/i,
112638
- errorCode: -32003 /* RateLimited */
112639
- },
112640
- {
112641
- pattern: /timeout|timed out|deadline exceeded/i,
112642
- errorCode: -32004 /* Timeout */
112643
- },
112644
- {
112645
- pattern: /abort(ed)?|cancell?ed/i,
112646
- errorCode: -32004 /* Timeout */
112647
- },
112648
- {
112649
- pattern: /service unavailable|bad gateway|gateway timeout|upstream error/i,
112650
- errorCode: -32000 /* ServiceUnavailable */
112651
- },
112652
- {
112653
- pattern: /zod|zoderror|schema validation/i,
112654
- errorCode: -32007 /* ValidationError */
112655
- }
112656
- ];
112657
- });
112658
-
112659
- // src/utils/internal/error-handler/helpers.ts
112660
- function createSafeRegex(pattern) {
112661
- if (pattern instanceof RegExp) {
112662
- let flags = pattern.flags.replace("g", "");
112663
- if (!flags.includes("i")) {
112664
- flags += "i";
112665
- }
112666
- return new RegExp(pattern.source, flags);
112667
- }
112668
- return new RegExp(pattern, "i");
112669
- }
112670
- function getErrorName(error48) {
112671
- if (error48 instanceof Error) {
112672
- return error48.name || "Error";
112673
- }
112674
- if (error48 === null) {
112675
- return "NullValueEncountered";
112676
- }
112677
- if (error48 === undefined) {
112678
- return "UndefinedValueEncountered";
112679
- }
112680
- if (typeof error48 === "object" && error48 !== null && error48.constructor && typeof error48.constructor.name === "string" && error48.constructor.name !== "Object") {
112681
- return `${error48.constructor.name}Encountered`;
112682
- }
112683
- return `${typeof error48}Encountered`;
112684
- }
112685
- function getErrorMessage(error48) {
112686
- try {
112687
- if (error48 instanceof Error) {
112688
- if ("errors" in error48 && Array.isArray(error48.errors)) {
112689
- const inner = error48.errors.map((e2) => e2 instanceof Error ? e2.message : String(e2)).filter(Boolean).slice(0, 3).join("; ");
112690
- return inner ? `${error48.message}: ${inner}` : error48.message;
112691
- }
112692
- return error48.message;
112693
- }
112694
- if (error48 === null) {
112695
- return "Null value encountered as error";
112696
- }
112697
- if (error48 === undefined) {
112698
- return "Undefined value encountered as error";
112699
- }
112700
- if (typeof error48 === "string") {
112701
- return error48;
112702
- }
112703
- if (typeof error48 === "number" || typeof error48 === "boolean") {
112704
- return String(error48);
112705
- }
112706
- if (typeof error48 === "bigint") {
112707
- return error48.toString();
112708
- }
112709
- if (typeof error48 === "function") {
112710
- return `[function ${error48.name || "anonymous"}]`;
112711
- }
112712
- if (typeof error48 === "object") {
112713
- try {
112714
- const json2 = JSON.stringify(error48);
112715
- if (json2 && json2 !== "{}")
112716
- return json2;
112717
- } catch {}
112718
- const ctor = error48.constructor?.name;
112719
- return `Non-Error object encountered (constructor: ${ctor || "Object"})`;
112720
- }
112721
- if (typeof error48 === "symbol") {
112722
- return error48.toString();
112723
- }
112724
- return "[unrepresentable error]";
112725
- } catch (conversionError) {
112726
- return `Error converting error to string: ${conversionError instanceof Error ? conversionError.message : "Unknown conversion error"}`;
112727
- }
112728
- }
112729
-
112730
- // src/utils/internal/error-handler/errorHandler.ts
112731
- class ErrorHandler {
112732
- static determineErrorCode(error48) {
112733
- if (error48 instanceof McpError) {
112734
- return error48.code;
112735
- }
112736
- const errorName = getErrorName(error48);
112737
- const errorMessage = getErrorMessage(error48);
112738
- const mappedFromType = ERROR_TYPE_MAPPINGS[errorName];
112739
- if (mappedFromType) {
112740
- return mappedFromType;
112741
- }
112742
- for (const mapping of COMMON_ERROR_PATTERNS) {
112743
- const regex = createSafeRegex(mapping.pattern);
112744
- if (regex.test(errorMessage) || regex.test(errorName)) {
112745
- return mapping.errorCode;
112746
- }
112747
- }
112748
- if (typeof error48 === "object" && error48 !== null && "name" in error48 && error48.name === "AbortError") {
112749
- return -32004 /* Timeout */;
112750
- }
112751
- return -32603 /* InternalError */;
112752
- }
112753
- static handleError(error48, options) {
112754
- const activeSpan = import_api3.trace.getActiveSpan();
112755
- if (activeSpan) {
112756
- if (error48 instanceof Error) {
112757
- activeSpan.recordException(error48);
112758
- }
112759
- activeSpan.setStatus({
112760
- code: import_api3.SpanStatusCode.ERROR,
112761
- message: error48 instanceof Error ? error48.message : String(error48)
112762
- });
112763
- }
112764
- const {
112765
- context = {},
112766
- operation,
112767
- input,
112768
- rethrow = false,
112769
- errorCode: explicitErrorCode,
112770
- includeStack = true,
112771
- critical = false,
112772
- errorMapper
112773
- } = options;
112774
- const sanitizedInput = input !== undefined ? sanitizeInputForLogging(input) : undefined;
112775
- const originalErrorName = getErrorName(error48);
112776
- const originalErrorMessage = getErrorMessage(error48);
112777
- const originalStack = error48 instanceof Error ? error48.stack : undefined;
112778
- let finalError;
112779
- let loggedErrorCode;
112780
- const errorDataSeed = error48 instanceof McpError && typeof error48.data === "object" && error48.data !== null ? { ...error48.data } : {};
112781
- const consolidatedData = {
112782
- ...errorDataSeed,
112783
- ...context,
112784
- originalErrorName,
112785
- originalMessage: originalErrorMessage
112786
- };
112787
- if (originalStack && !(error48 instanceof McpError && error48.data?.originalStack)) {
112788
- consolidatedData.originalStack = originalStack;
112789
- }
112790
- const cause = error48 instanceof Error ? error48 : undefined;
112791
- const rootCause = (() => {
112792
- let current = cause;
112793
- let depth = 0;
112794
- while (current && current instanceof Error && current.cause && depth < 5) {
112795
- current = current.cause;
112796
- depth += 1;
112797
- }
112798
- return current instanceof Error ? { name: current.name, message: current.message } : undefined;
112799
- })();
112800
- if (rootCause) {
112801
- consolidatedData["rootCause"] = rootCause;
112802
- }
112803
- if (error48 instanceof McpError) {
112804
- loggedErrorCode = error48.code;
112805
- finalError = errorMapper ? errorMapper(error48) : new McpError(error48.code, error48.message, consolidatedData, {
112806
- cause
112807
- });
112808
- } else {
112809
- loggedErrorCode = explicitErrorCode || ErrorHandler.determineErrorCode(error48);
112810
- const message = `Error in ${operation}: ${originalErrorMessage}`;
112811
- finalError = errorMapper ? errorMapper(error48) : new McpError(loggedErrorCode, message, consolidatedData, {
112812
- cause
112813
- });
112814
- }
112815
- if (finalError !== error48 && error48 instanceof Error && finalError instanceof Error && !finalError.stack && error48.stack) {
112816
- finalError.stack = error48.stack;
112817
- }
112818
- const logRequestId = typeof context.requestId === "string" && context.requestId ? context.requestId : generateUUID();
112819
- const logTimestamp = typeof context.timestamp === "string" && context.timestamp ? context.timestamp : new Date().toISOString();
112820
- const stack = finalError instanceof Error ? finalError.stack : originalStack;
112821
- const logContext = {
112822
- requestId: logRequestId,
112823
- timestamp: logTimestamp,
112824
- operation,
112825
- input: sanitizedInput,
112826
- critical,
112827
- errorCode: loggedErrorCode,
112828
- originalErrorType: originalErrorName,
112829
- finalErrorType: getErrorName(finalError),
112830
- ...Object.fromEntries(Object.entries(context).filter(([key]) => key !== "requestId" && key !== "timestamp")),
112831
- errorData: finalError instanceof McpError && finalError.data ? finalError.data : consolidatedData,
112832
- ...includeStack && stack ? { stack } : {}
112833
- };
112834
- logger.error(`Error in ${operation}: ${finalError.message || originalErrorMessage}`, logContext);
112835
- if (rethrow) {
112836
- throw finalError;
112837
- }
112838
- return finalError;
112839
- }
112840
- static mapError(error48, mappings, defaultFactory) {
112841
- const errorMessage = getErrorMessage(error48);
112842
- const errorName = getErrorName(error48);
112843
- for (const mapping of mappings) {
112844
- const regex = createSafeRegex(mapping.pattern);
112845
- if (regex.test(errorMessage) || regex.test(errorName)) {
112846
- return mapping.factory(error48, mapping.additionalContext);
112847
- }
112848
- }
112849
- if (defaultFactory) {
112850
- return defaultFactory(error48);
112851
- }
112852
- return error48 instanceof Error ? error48 : new Error(String(error48));
112853
- }
112854
- static formatError(error48) {
112855
- if (error48 instanceof McpError) {
112856
- return {
112857
- code: error48.code,
112858
- message: error48.message,
112859
- data: typeof error48.data === "object" && error48.data !== null ? error48.data : {}
112860
- };
112861
- }
112862
- if (error48 instanceof Error) {
112863
- return {
112864
- code: ErrorHandler.determineErrorCode(error48),
112865
- message: error48.message,
112866
- data: { errorType: error48.name || "Error" }
112867
- };
112868
- }
112869
- return {
112870
- code: -32099 /* UnknownError */,
112871
- message: getErrorMessage(error48),
112872
- data: { errorType: getErrorName(error48) }
112873
- };
112874
- }
112875
- static async tryCatch(fn, options) {
112876
- try {
112877
- return await Promise.resolve(fn());
112878
- } catch (caughtError) {
112879
- throw ErrorHandler.handleError(caughtError, {
112880
- ...options,
112881
- rethrow: true
112882
- });
112883
- }
112884
- }
112885
- }
112886
- var import_api3;
112887
- var init_errorHandler = __esm(() => {
112888
- init_errors3();
112889
- init_utils();
112890
- init_logger();
112891
- init_mappings();
112892
- import_api3 = __toESM(require_src(), 1);
112893
- });
112894
-
112895
- // src/utils/internal/error-handler/index.ts
112896
- var init_error_handler = __esm(() => {
112897
- init_errorHandler();
112898
- });
112899
-
112900
- // src/utils/internal/runtime.ts
112901
- function detectRuntime() {
112902
- if (runtimeCaps.isBun) {
112903
- return "bun";
112904
- }
112905
- if (runtimeCaps.isNode) {
112906
- return "node";
112907
- }
112908
- if (runtimeCaps.isWorkerLike) {
112909
- return "worker";
112910
- }
112911
- if (runtimeCaps.isBrowserLike) {
112912
- return "browser";
112913
- }
112914
- return "unknown";
112915
- }
112916
- function getRuntimeDescription() {
112917
- const runtime = detectRuntime();
112918
- switch (runtime) {
112919
- case "bun":
112920
- return `Bun ${process.versions?.bun || "unknown"}`;
112921
- case "node":
112922
- return `Node.js ${process.versions?.node || "unknown"}`;
112923
- case "worker":
112924
- return "Cloudflare Workers / Web Worker";
112925
- case "browser":
112926
- return "Browser";
112927
- default:
112928
- return "Unknown runtime";
112929
- }
112930
- }
112931
- var safeHas = (key) => {
112932
- try {
112933
- return typeof globalThis[key] !== "undefined";
112934
- } catch {
112935
- return false;
112936
- }
112937
- }, isBun, isNode, hasProcess, hasBuffer, hasTextEncoder, hasPerformanceNow, isWorkerLike, isBrowserLike, runtimeCaps;
112938
- var init_runtime = __esm(() => {
112939
- isBun = typeof globalThis.Bun !== "undefined" || typeof process.versions?.bun === "string";
112940
- isNode = !isBun && typeof process !== "undefined" && typeof process.versions?.node === "string";
112941
- hasProcess = typeof process !== "undefined";
112942
- hasBuffer = typeof Buffer !== "undefined";
112943
- hasTextEncoder = safeHas("TextEncoder");
112944
- hasPerformanceNow = typeof globalThis.performance?.now === "function";
112945
- isWorkerLike = !isNode && !isBun && typeof globalThis.WorkerGlobalScope !== "undefined";
112946
- isBrowserLike = !isNode && !isBun && !isWorkerLike && safeHas("window");
112947
- runtimeCaps = {
112948
- isNode,
112949
- isBun,
112950
- isWorkerLike,
112951
- isBrowserLike,
112952
- hasProcess,
112953
- hasBuffer,
112954
- hasTextEncoder,
112955
- hasPerformanceNow
112956
- };
112957
- });
112958
-
112959
- // src/utils/internal/health.ts
112960
- function getHealthSnapshot() {
112961
- return {
112962
- app: {
112963
- name: config2.mcpServerName,
112964
- version: config2.mcpServerVersion,
112965
- environment: config2.environment
112966
- },
112967
- runtime: {
112968
- isNode: runtimeCaps.isNode,
112969
- isWorkerLike: runtimeCaps.isWorkerLike,
112970
- isBrowserLike: runtimeCaps.isBrowserLike
112971
- },
112972
- telemetry: {
112973
- enabled: Boolean(config2.openTelemetry.enabled),
112974
- diagLevel: config2.openTelemetry.logLevel
112975
- },
112976
- logging: {
112977
- initialized: logger.isInitialized()
112978
- }
112979
- };
112980
- }
112981
- var init_health = __esm(() => {
112982
- init_config();
112983
- init_logger();
112984
- init_runtime();
112985
- });
112986
-
112987
- // src/utils/telemetry/semconv.ts
112988
- var ATTR_CODE_FUNCTION = "code.function", ATTR_CODE_NAMESPACE = "code.namespace", ATTR_MCP_TOOL_INPUT_BYTES = "mcp.tool.input_bytes", ATTR_MCP_TOOL_OUTPUT_BYTES = "mcp.tool.output_bytes", ATTR_MCP_TOOL_DURATION_MS = "mcp.tool.duration_ms", ATTR_MCP_TOOL_SUCCESS = "mcp.tool.success", ATTR_MCP_TOOL_ERROR_CODE = "mcp.tool.error_code", ATTR_MCP_TOOL_MEMORY_RSS_BEFORE = "mcp.tool.memory_rss_bytes.before", ATTR_MCP_TOOL_MEMORY_RSS_AFTER = "mcp.tool.memory_rss_bytes.after", ATTR_MCP_TOOL_MEMORY_RSS_DELTA = "mcp.tool.memory_rss_bytes.delta", ATTR_MCP_TOOL_MEMORY_HEAP_USED_BEFORE = "mcp.tool.memory_heap_used_bytes.before", ATTR_MCP_TOOL_MEMORY_HEAP_USED_AFTER = "mcp.tool.memory_heap_used_bytes.after", ATTR_MCP_TOOL_MEMORY_HEAP_USED_DELTA = "mcp.tool.memory_heap_used_bytes.delta";
112989
-
112990
- // src/utils/internal/performance.ts
112991
- async function loadPerfHooks() {
112992
- return import("perf_hooks");
112993
- }
112994
- async function initializePerformance_Hrt() {
112995
- const globalWithPerf = globalThis;
112996
- if (typeof globalWithPerf.performance?.now === "function") {
112997
- const perf = globalWithPerf.performance;
112998
- performanceNow = () => perf?.now() ?? Date.now();
112999
- } else {
113000
- try {
113001
- const { performance: nodePerformance } = await loadPerfHooks();
113002
- performanceNow = () => nodePerformance.now();
113003
- } catch (_e) {
113004
- performanceNow = () => Date.now();
113005
- logger.warning("Could not import perf_hooks, falling back to Date.now() for performance timing.");
113006
- }
113007
- }
113008
- }
113009
- async function measureToolExecution(toolLogicFn, context, inputPayload) {
113010
- const tracer = import_api4.trace.getTracer(config2.openTelemetry.serviceName, config2.openTelemetry.serviceVersion);
113011
- const { toolName } = context;
113012
- return tracer.startActiveSpan(`tool_execution:${toolName}`, async (span) => {
113013
- const memBefore = typeof process !== "undefined" && typeof process.memoryUsage === "function" ? process.memoryUsage() : { rss: 0, heapUsed: 0 };
113014
- const t0 = nowMs();
113015
- span.setAttributes({
113016
- [ATTR_CODE_FUNCTION]: toolName,
113017
- [ATTR_CODE_NAMESPACE]: "mcp-tools",
113018
- [ATTR_MCP_TOOL_INPUT_BYTES]: toBytes(inputPayload),
113019
- [ATTR_MCP_TOOL_MEMORY_RSS_BEFORE]: memBefore.rss,
113020
- [ATTR_MCP_TOOL_MEMORY_HEAP_USED_BEFORE]: memBefore.heapUsed
113021
- });
113022
- let ok = false;
113023
- let errorCode;
113024
- let output;
113025
- try {
113026
- const result = await toolLogicFn();
113027
- ok = true;
113028
- output = result;
113029
- span.setStatus({ code: import_api4.SpanStatusCode.OK });
113030
- span.setAttribute(ATTR_MCP_TOOL_OUTPUT_BYTES, toBytes(output));
113031
- return result;
113032
- } catch (err) {
113033
- if (err instanceof McpError)
113034
- errorCode = String(err.code);
113035
- else if (err instanceof Error)
113036
- errorCode = "UNHANDLED_ERROR";
113037
- else
113038
- errorCode = "UNKNOWN_ERROR";
113039
- if (err instanceof Error)
113040
- span.recordException(err);
113041
- span.setStatus({
113042
- code: import_api4.SpanStatusCode.ERROR,
113043
- message: err instanceof Error ? err.message : String(err)
113044
- });
113045
- throw err;
113046
- } finally {
113047
- const t1 = nowMs();
113048
- const durationMs = Number((t1 - t0).toFixed(2));
113049
- const memAfter = typeof process !== "undefined" && typeof process.memoryUsage === "function" ? process.memoryUsage() : { rss: 0, heapUsed: 0 };
113050
- const rssDelta = memAfter.rss - memBefore.rss;
113051
- const heapUsedDelta = memAfter.heapUsed - memBefore.heapUsed;
113052
- span.setAttributes({
113053
- [ATTR_MCP_TOOL_DURATION_MS]: durationMs,
113054
- [ATTR_MCP_TOOL_SUCCESS]: ok,
113055
- [ATTR_MCP_TOOL_MEMORY_RSS_AFTER]: memAfter.rss,
113056
- [ATTR_MCP_TOOL_MEMORY_HEAP_USED_AFTER]: memAfter.heapUsed,
113057
- [ATTR_MCP_TOOL_MEMORY_RSS_DELTA]: rssDelta,
113058
- [ATTR_MCP_TOOL_MEMORY_HEAP_USED_DELTA]: heapUsedDelta
113059
- });
113060
- if (errorCode)
113061
- span.setAttribute(ATTR_MCP_TOOL_ERROR_CODE, errorCode);
113062
- span.end();
113063
- logger.info("Tool execution finished.", {
113064
- ...context,
113065
- metrics: {
113066
- durationMs,
113067
- isSuccess: ok,
113068
- errorCode,
113069
- inputBytes: toBytes(inputPayload),
113070
- outputBytes: toBytes(output),
113071
- memory: {
113072
- rss: {
113073
- before: memBefore.rss,
113074
- after: memAfter.rss,
113075
- delta: rssDelta
113076
- },
113077
- heapUsed: {
113078
- before: memBefore.heapUsed,
113079
- after: memAfter.heapUsed,
113080
- delta: heapUsedDelta
113081
- }
113082
- }
113083
- }
113084
- });
113085
- }
113086
- });
113087
- }
113088
- var import_api4, performanceNow = () => Date.now(), nowMs = () => performanceNow(), toBytes = (payload) => {
113089
- if (payload == null)
113090
- return 0;
113091
- try {
113092
- const json2 = JSON.stringify(payload);
113093
- if (typeof Buffer !== "undefined" && typeof Buffer.byteLength === "function") {
113094
- const bytes = Buffer.byteLength(json2, "utf8");
113095
- return bytes;
113096
- }
113097
- if (typeof TextEncoder !== "undefined") {
113098
- return new TextEncoder().encode(json2).length;
113099
- }
113100
- return json2.length;
113101
- } catch {
113102
- return 0;
113103
- }
113104
- };
113105
- var init_performance = __esm(() => {
113106
- init_config();
113107
- init_errors3();
113108
- init_logger();
113109
- import_api4 = __toESM(require_src(), 1);
113110
- });
113111
-
113112
- // src/utils/internal/startupBanner.ts
113113
- function logStartupBanner(message, transportType) {
113114
- if (process.stdout.isTTY) {
113115
- if (transportType === "stdio") {
113116
- console.error(message);
113117
- } else {
113118
- console.log(message);
113119
- }
113120
- }
113121
- }
113122
-
113123
- // src/utils/internal/index.ts
113124
- var init_internal = __esm(() => {
113125
- init_error_handler();
113126
- init_health();
113127
- init_logger();
113128
- init_performance();
113129
- init_requestContext();
113130
- init_runtime();
113131
- });
113132
-
113133
- // src/utils/metrics/tokenCounter.ts
113134
- function getModelHeuristics(model) {
113135
- const key = (model ?? DEFAULT_MODEL).toLowerCase();
113136
- const found = HEURISTICS[key];
113137
- return found ?? HEURISTICS.default;
113138
- }
113139
- function nonEmptyString(s2) {
113140
- return typeof s2 === "string" && s2.length > 0;
113141
- }
113142
- function approxTokenCount(text, charsPerToken) {
113143
- if (!text)
113144
- return 0;
113145
- const normalized = text.replace(/\s+/g, " ").trim();
113146
- if (!normalized)
113147
- return 0;
113148
- return Math.ceil(normalized.length / Math.max(1, charsPerToken));
113149
- }
113150
- async function countTokens(text, context, model) {
113151
- return ErrorHandler.tryCatch(() => {
113152
- const h2 = getModelHeuristics(model);
113153
- return approxTokenCount(text ?? "", h2.charsPerToken);
113154
- }, {
113155
- operation: "countTokens",
113156
- ...context && { context },
113157
- input: {
113158
- textSample: nonEmptyString(text) ? text.length > 53 ? `${text.slice(0, 50)}...` : text : ""
113159
- },
113160
- errorCode: -32603 /* InternalError */
113161
- });
113162
- }
113163
- async function countChatTokens(messages, context, model) {
113164
- return ErrorHandler.tryCatch(() => {
113165
- const h2 = getModelHeuristics(model);
113166
- let tokens = 0;
113167
- for (const message of messages) {
113168
- tokens += h2.tokensPerMessage;
113169
- tokens += 1;
113170
- if (typeof message.content === "string") {
113171
- tokens += approxTokenCount(message.content, h2.charsPerToken);
113172
- } else if (Array.isArray(message.content)) {
113173
- for (const part of message.content) {
113174
- if (part && part.type === "text" && nonEmptyString(part.text)) {
113175
- tokens += approxTokenCount(part.text, h2.charsPerToken);
113176
- } else if (part) {
113177
- logger.warning(`Non-text content part found (type: ${String(part.type)}), token count contribution ignored.`, context);
113178
- }
113179
- }
113180
- }
113181
- if (message.name) {
113182
- tokens += h2.tokensPerName;
113183
- tokens += approxTokenCount(message.name, h2.charsPerToken);
113184
- }
113185
- if (message.role === "assistant" && Array.isArray(message.tool_calls)) {
113186
- for (const toolCall of message.tool_calls) {
113187
- if (toolCall?.type === "function") {
113188
- if (toolCall.function?.name) {
113189
- tokens += approxTokenCount(toolCall.function.name, h2.charsPerToken);
113190
- }
113191
- if (toolCall.function?.arguments) {
113192
- tokens += approxTokenCount(toolCall.function.arguments, h2.charsPerToken);
113193
- }
113194
- }
113195
- }
113196
- }
113197
- if (message.role === "tool" && message.tool_call_id) {
113198
- tokens += approxTokenCount(message.tool_call_id, h2.charsPerToken);
113199
- }
113200
- }
113201
- tokens += h2.replyPrimer;
113202
- return tokens;
113203
- }, {
113204
- operation: "countChatTokens",
113205
- ...context && { context },
113206
- input: { messageCount: messages.length },
113207
- errorCode: -32603 /* InternalError */
113208
- });
113209
- }
113210
- var DEFAULT_MODEL = "gpt-4o", HEURISTICS;
113211
- var init_tokenCounter = __esm(() => {
113212
- init_utils();
113213
- HEURISTICS = {
113214
- "gpt-4o": {
113215
- charsPerToken: 4,
113216
- tokensPerMessage: 3,
113217
- tokensPerName: 1,
113218
- replyPrimer: 3
113219
- },
113220
- "gpt-4o-mini": {
113221
- charsPerToken: 4,
113222
- tokensPerMessage: 3,
113223
- tokensPerName: 1,
113224
- replyPrimer: 3
113225
- },
113226
- default: {
113227
- charsPerToken: 4,
113228
- tokensPerMessage: 3,
113229
- tokensPerName: 1,
113230
- replyPrimer: 3
113231
- }
113232
- };
113233
- });
113234
-
113235
- // src/utils/metrics/registry.ts
113236
- function getMeter() {
113237
- return import_api5.metrics.getMeter(config2.openTelemetry.serviceName, config2.openTelemetry.serviceVersion);
113238
- }
113239
- function isEnabled() {
113240
- return Boolean(config2.openTelemetry.enabled);
113241
- }
113242
- function getCounter(name, description, unit) {
113243
- if (!isEnabled()) {
113244
- return {
113245
- add: () => {
113246
- return;
113247
- },
113248
- bind: () => ({ add: () => {
113249
- return;
113250
- } }),
113251
- unbind: () => {
113252
- return;
113253
- }
113254
- };
113255
- }
113256
- const key = `${name}|${description ?? ""}|${unit ?? ""}`;
113257
- const existing = counters.get(key);
113258
- if (existing)
113259
- return existing;
113260
- const opts = {};
113261
- if (description !== undefined)
113262
- opts.description = description;
113263
- if (unit !== undefined)
113264
- opts.unit = unit;
113265
- const counter = Object.keys(opts).length ? getMeter().createCounter(name, opts) : getMeter().createCounter(name);
113266
- counters.set(key, counter);
113267
- return counter;
113268
- }
113269
- function getHistogram(name, description, unit) {
113270
- if (!isEnabled()) {
113271
- return {
113272
- record: () => {
113273
- return;
113274
- },
113275
- bind: () => ({ record: () => {
113276
- return;
113277
- } }),
113278
- unbind: () => {
113279
- return;
113280
- }
113281
- };
113282
- }
113283
- const key = `${name}|${description ?? ""}|${unit ?? ""}`;
113284
- const existing = histograms.get(key);
113285
- if (existing)
113286
- return existing;
113287
- const opts = {};
113288
- if (description !== undefined)
113289
- opts.description = description;
113290
- if (unit !== undefined)
113291
- opts.unit = unit;
113292
- const histogram = Object.keys(opts).length ? getMeter().createHistogram(name, opts) : getMeter().createHistogram(name);
113293
- histograms.set(key, histogram);
113294
- return histogram;
113295
- }
113296
- function add(name, value, attributes, description, unit) {
113297
- const c = getCounter(name, description, unit);
113298
- c.add(value, attributes);
113299
- }
113300
- function record2(name, value, attributes, description, unit) {
113301
- const h2 = getHistogram(name, description, unit);
113302
- h2.record(value, attributes);
113303
- }
113304
- var import_api5, counters, histograms, metricsRegistry;
113305
- var init_registry = __esm(() => {
113306
- init_config();
113307
- import_api5 = __toESM(require_src(), 1);
113308
- counters = new Map;
113309
- histograms = new Map;
113310
- metricsRegistry = {
113311
- getCounter,
113312
- getHistogram,
113313
- add,
113314
- record: record2,
113315
- enabled: isEnabled
113316
- };
113317
- });
113318
-
113319
- // src/utils/metrics/index.ts
113320
- var init_metrics = __esm(() => {
113321
- init_tokenCounter();
113322
- init_registry();
113323
- });
113324
-
113325
- // src/utils/security/idGenerator.ts
113326
- import { randomUUID as cryptoRandomUUID, randomBytes } from "crypto";
113327
-
113328
- class IdGenerator {
113329
- static DEFAULT_CHARSET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
113330
- static DEFAULT_SEPARATOR = "_";
113331
- static DEFAULT_LENGTH = 6;
113332
- entityPrefixes = {};
113333
- prefixToEntityType = {};
113334
- constructor(entityPrefixes = {}) {
113335
- this.setEntityPrefixes(entityPrefixes);
113336
- }
113337
- setEntityPrefixes(entityPrefixes) {
113338
- this.entityPrefixes = { ...entityPrefixes };
113339
- this.prefixToEntityType = Object.entries(this.entityPrefixes).reduce((acc, [type, prefix]) => {
113340
- acc[prefix.toLowerCase()] = type;
113341
- return acc;
113342
- }, {});
113343
- }
113344
- getEntityPrefixes() {
113345
- return { ...this.entityPrefixes };
113346
- }
113347
- generateRandomString(length = IdGenerator.DEFAULT_LENGTH, charset = IdGenerator.DEFAULT_CHARSET) {
113348
- let result = "";
113349
- const maxValidByteValue = Math.floor(256 / charset.length) * charset.length;
113350
- while (result.length < length) {
113351
- const byteBuffer = randomBytes(1);
113352
- const byte = byteBuffer[0];
113353
- if (byte !== undefined && byte < maxValidByteValue) {
113354
- const charIndex = byte % charset.length;
113355
- const char = charset[charIndex];
113356
- if (char) {
113357
- result += char;
113358
- }
113359
- }
113360
- }
113361
- return result;
113362
- }
113363
- generate(prefix, options = {}) {
113364
- const {
113365
- length = IdGenerator.DEFAULT_LENGTH,
113366
- separator = IdGenerator.DEFAULT_SEPARATOR,
113367
- charset = IdGenerator.DEFAULT_CHARSET
113368
- } = options;
113369
- const randomPart = this.generateRandomString(length, charset);
113370
- const generatedId = prefix ? `${prefix}${separator}${randomPart}` : randomPart;
113371
- return generatedId;
113372
- }
113373
- generateForEntity(entityType, options = {}) {
113374
- const prefix = this.entityPrefixes[entityType];
113375
- if (!prefix) {
113376
- throw new McpError(-32007 /* ValidationError */, `Unknown entity type: ${entityType}. No prefix registered.`);
113377
- }
113378
- return this.generate(prefix, options);
113379
- }
113380
- isValid(id, entityType, options = {}) {
113381
- const prefix = this.entityPrefixes[entityType];
113382
- const {
113383
- length = IdGenerator.DEFAULT_LENGTH,
113384
- separator = IdGenerator.DEFAULT_SEPARATOR,
113385
- charset = IdGenerator.DEFAULT_CHARSET
113386
- } = options;
113387
- if (!prefix) {
113388
- return false;
113389
- }
113390
- const escapedCharsetForClass = charset.replace(/[[\]\\^-]/g, "\\$&");
113391
- const charsetRegexPart = `[${escapedCharsetForClass}]`;
113392
- const pattern = new RegExp(`^${this.escapeRegex(prefix)}${this.escapeRegex(separator)}${charsetRegexPart}{${length}}$`);
113393
- return pattern.test(id);
113394
- }
113395
- escapeRegex(str) {
113396
- return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
113397
- }
113398
- stripPrefix(id, separator = IdGenerator.DEFAULT_SEPARATOR) {
113399
- const parts = id.split(separator);
113400
- return parts.length > 1 ? parts.slice(1).join(separator) : id;
113401
- }
113402
- getEntityType(id, separator = IdGenerator.DEFAULT_SEPARATOR) {
113403
- const parts = id.split(separator);
113404
- if (parts.length < 2 || !parts[0]) {
113405
- throw new McpError(-32007 /* ValidationError */, `Invalid ID format: ${id}. Expected format like: PREFIX${separator}RANDOMLPART`);
113406
- }
113407
- const prefix = parts[0];
113408
- const entityType = this.prefixToEntityType[prefix.toLowerCase()];
113409
- if (!entityType) {
113410
- throw new McpError(-32007 /* ValidationError */, `Unknown entity type for prefix: ${prefix}`);
113411
- }
113412
- return entityType;
113413
- }
113414
- normalize(id, separator = IdGenerator.DEFAULT_SEPARATOR) {
113415
- const entityType = this.getEntityType(id, separator);
113416
- const registeredPrefix = this.entityPrefixes[entityType];
113417
- const idParts = id.split(separator);
113418
- const randomPart = idParts.slice(1).join(separator);
113419
- return `${registeredPrefix}${separator}${randomPart.toUpperCase()}`;
113420
- }
113421
- }
113422
- var idGenerator, generateUUID = () => {
113423
- return cryptoRandomUUID();
113424
- }, generateRequestContextId = () => {
113425
- const generateSecureRandomString = (length, charset2) => {
113426
- let result = "";
113427
- const maxValidByteValue = Math.floor(256 / charset2.length) * charset2.length;
113428
- while (result.length < length) {
113429
- const byteBuffer = randomBytes(1);
113430
- const byte = byteBuffer[0];
113431
- if (byte !== undefined && byte < maxValidByteValue) {
113432
- const charIndex = byte % charset2.length;
113433
- const char = charset2[charIndex];
113434
- if (char) {
113435
- result += char;
113436
- }
113437
- }
113438
- }
113439
- return result;
113440
- };
113441
- const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
113442
- const part1 = generateSecureRandomString(5, charset);
113443
- const part2 = generateSecureRandomString(5, charset);
113444
- return `${part1}-${part2}`;
113445
- };
113446
- var init_idGenerator = __esm(() => {
113447
- init_errors3();
113448
- idGenerator = new IdGenerator;
113449
- });
113450
-
113451
111980
  // node_modules/tsyringe/node_modules/tslib/tslib.js
113452
111981
  var require_tslib = __commonJS((exports, module) => {
113453
111982
  /*! *****************************************************************************
@@ -114593,7 +113122,7 @@ var require_registry2 = __commonJS((exports) => {
114593
113122
  Object.defineProperty(exports, "__esModule", { value: true });
114594
113123
  var tslib_1 = require_tslib();
114595
113124
  var dependency_container_1 = require_dependency_container();
114596
- function registry3(registrations = []) {
113125
+ function registry2(registrations = []) {
114597
113126
  return function(target) {
114598
113127
  registrations.forEach((_a2) => {
114599
113128
  var { token, options } = _a2, provider = tslib_1.__rest(_a2, ["token", "options"]);
@@ -114602,7 +113131,7 @@ var require_registry2 = __commonJS((exports) => {
114602
113131
  return target;
114603
113132
  };
114604
113133
  }
114605
- exports.default = registry3;
113134
+ exports.default = registry2;
114606
113135
  });
114607
113136
 
114608
113137
  // node_modules/tsyringe/dist/cjs/decorators/singleton.js
@@ -114846,195 +113375,6 @@ var init_tokens = __esm(() => {
114846
113375
  GitProviderFactory = Symbol("GitProviderFactory");
114847
113376
  });
114848
113377
 
114849
- // src/utils/security/rateLimiter.ts
114850
- var import_api6, import_tsyringe, RateLimiter;
114851
- var init_rateLimiter = __esm(() => {
114852
- init_tokens();
114853
- init_errors3();
114854
- init_utils();
114855
- import_api6 = __toESM(require_src(), 1);
114856
- import_tsyringe = __toESM(require_cjs2(), 1);
114857
- RateLimiter = class RateLimiter {
114858
- config;
114859
- logger;
114860
- limits;
114861
- cleanupTimer = null;
114862
- effectiveConfig;
114863
- constructor(config3, logger3) {
114864
- this.config = config3;
114865
- this.logger = logger3;
114866
- const defaultConfig = {
114867
- windowMs: 15 * 60 * 1000,
114868
- maxRequests: 100,
114869
- errorMessage: "Rate limit exceeded. Please try again in {waitTime} seconds.",
114870
- skipInDevelopment: false,
114871
- cleanupInterval: 5 * 60 * 1000
114872
- };
114873
- this.effectiveConfig = { ...defaultConfig };
114874
- this.limits = new Map;
114875
- this.startCleanupTimer();
114876
- }
114877
- startCleanupTimer() {
114878
- if (this.cleanupTimer) {
114879
- clearInterval(this.cleanupTimer);
114880
- }
114881
- const interval = this.effectiveConfig.cleanupInterval;
114882
- if (interval && interval > 0) {
114883
- this.cleanupTimer = setInterval(() => {
114884
- this.cleanupExpiredEntries();
114885
- }, interval);
114886
- if (this.cleanupTimer.unref) {
114887
- this.cleanupTimer.unref();
114888
- }
114889
- }
114890
- }
114891
- cleanupExpiredEntries() {
114892
- const now = Date.now();
114893
- let expiredCount = 0;
114894
- for (const [key, entry] of this.limits.entries()) {
114895
- if (now >= entry.resetTime) {
114896
- this.limits.delete(key);
114897
- expiredCount++;
114898
- }
114899
- }
114900
- if (expiredCount > 0) {
114901
- const logContext = requestContextService.createRequestContext({
114902
- operation: "RateLimiter.cleanupExpiredEntries",
114903
- additionalContext: {
114904
- cleanedCount: expiredCount,
114905
- totalRemainingAfterClean: this.limits.size
114906
- }
114907
- });
114908
- this.logger.debug(`Cleaned up ${expiredCount} expired rate limit entries`, logContext);
114909
- }
114910
- }
114911
- configure(config3) {
114912
- Object.assign(this.effectiveConfig, config3);
114913
- if (config3.cleanupInterval !== undefined) {
114914
- this.startCleanupTimer();
114915
- }
114916
- }
114917
- getConfig() {
114918
- return { ...this.effectiveConfig };
114919
- }
114920
- reset() {
114921
- this.limits.clear();
114922
- const logContext = requestContextService.createRequestContext({
114923
- operation: "RateLimiter.reset"
114924
- });
114925
- this.logger.debug("Rate limiter reset, all limits cleared", logContext);
114926
- }
114927
- check(key, context) {
114928
- const activeSpan = import_api6.trace.getActiveSpan();
114929
- activeSpan?.setAttribute("mcp.rate_limit.checked", true);
114930
- if (this.effectiveConfig.skipInDevelopment && this.config.environment === "development") {
114931
- activeSpan?.setAttribute("mcp.rate_limit.skipped", "development");
114932
- return;
114933
- }
114934
- const limitKey = this.effectiveConfig.keyGenerator ? this.effectiveConfig.keyGenerator(key, context) : key;
114935
- activeSpan?.setAttribute("mcp.rate_limit.key", limitKey);
114936
- const now = Date.now();
114937
- let entry = this.limits.get(limitKey);
114938
- if (!entry || now >= entry.resetTime) {
114939
- entry = {
114940
- count: 1,
114941
- resetTime: now + this.effectiveConfig.windowMs
114942
- };
114943
- this.limits.set(limitKey, entry);
114944
- } else {
114945
- entry.count++;
114946
- }
114947
- const remaining = Math.max(0, this.effectiveConfig.maxRequests - entry.count);
114948
- activeSpan?.setAttributes({
114949
- "mcp.rate_limit.limit": this.effectiveConfig.maxRequests,
114950
- "mcp.rate_limit.count": entry.count,
114951
- "mcp.rate_limit.remaining": remaining
114952
- });
114953
- if (entry.count > this.effectiveConfig.maxRequests) {
114954
- const waitTime = Math.ceil((entry.resetTime - now) / 1000);
114955
- const errorMessage = (this.effectiveConfig.errorMessage || "Rate limit exceeded. Please try again in {waitTime} seconds.").replace("{waitTime}", waitTime.toString());
114956
- activeSpan?.addEvent("rate_limit_exceeded", {
114957
- "mcp.rate_limit.wait_time_seconds": waitTime
114958
- });
114959
- throw new McpError(-32003 /* RateLimited */, errorMessage, {
114960
- waitTimeSeconds: waitTime,
114961
- key: limitKey,
114962
- limit: this.effectiveConfig.maxRequests,
114963
- windowMs: this.effectiveConfig.windowMs
114964
- });
114965
- }
114966
- }
114967
- getStatus(key) {
114968
- const entry = this.limits.get(key);
114969
- if (!entry)
114970
- return null;
114971
- return {
114972
- current: entry.count,
114973
- limit: this.effectiveConfig.maxRequests,
114974
- remaining: Math.max(0, this.effectiveConfig.maxRequests - entry.count),
114975
- resetTime: entry.resetTime
114976
- };
114977
- }
114978
- dispose() {
114979
- if (this.cleanupTimer) {
114980
- clearInterval(this.cleanupTimer);
114981
- this.cleanupTimer = null;
114982
- }
114983
- this.limits.clear();
114984
- }
114985
- };
114986
- RateLimiter = __legacyDecorateClassTS([
114987
- import_tsyringe.injectable(),
114988
- __legacyDecorateParamTS(0, import_tsyringe.inject(AppConfig)),
114989
- __legacyDecorateParamTS(1, import_tsyringe.inject(Logger2)),
114990
- __legacyMetadataTS("design:paramtypes", [
114991
- Object,
114992
- Object
114993
- ])
114994
- ], RateLimiter);
114995
- });
114996
-
114997
- // src/utils/security/index.ts
114998
- var init_security = __esm(() => {
114999
- init_idGenerator();
115000
- init_rateLimiter();
115001
- init_sanitization();
115002
- });
115003
-
115004
- // src/utils/index.ts
115005
- var exports_utils = {};
115006
- __export(exports_utils, {
115007
- sanitizeInputForLogging: () => sanitizeInputForLogging,
115008
- sanitization: () => sanitization,
115009
- runtimeCaps: () => runtimeCaps,
115010
- requestContextService: () => requestContextService,
115011
- nowMs: () => nowMs,
115012
- metricsRegistry: () => metricsRegistry,
115013
- measureToolExecution: () => measureToolExecution,
115014
- logger: () => logger,
115015
- logStartupBanner: () => logStartupBanner,
115016
- loadPerfHooks: () => loadPerfHooks,
115017
- initializePerformance_Hrt: () => initializePerformance_Hrt,
115018
- idGenerator: () => idGenerator,
115019
- getRuntimeDescription: () => getRuntimeDescription,
115020
- getHealthSnapshot: () => getHealthSnapshot,
115021
- generateUUID: () => generateUUID,
115022
- generateRequestContextId: () => generateRequestContextId,
115023
- detectRuntime: () => detectRuntime,
115024
- countTokens: () => countTokens,
115025
- countChatTokens: () => countChatTokens,
115026
- Sanitization: () => Sanitization,
115027
- RateLimiter: () => RateLimiter,
115028
- Logger: () => Logger,
115029
- IdGenerator: () => IdGenerator,
115030
- ErrorHandler: () => ErrorHandler
115031
- });
115032
- var init_utils = __esm(() => {
115033
- init_internal();
115034
- init_metrics();
115035
- init_security();
115036
- });
115037
-
115038
113378
  // node_modules/tslib/tslib.js
115039
113379
  var require_tslib2 = __commonJS((exports, module) => {
115040
113380
  var __extends;
@@ -116170,22 +114510,22 @@ var require_transformers = __commonJS((exports) => {
116170
114510
  PostgresTypes2["tsrange"] = "tsrange";
116171
114511
  PostgresTypes2["tstzrange"] = "tstzrange";
116172
114512
  })(PostgresTypes || (exports.PostgresTypes = PostgresTypes = {}));
116173
- var convertChangeData = (columns, record3, options = {}) => {
114513
+ var convertChangeData = (columns, record2, options = {}) => {
116174
114514
  var _a2;
116175
114515
  const skipTypes = (_a2 = options.skipTypes) !== null && _a2 !== undefined ? _a2 : [];
116176
- if (!record3) {
114516
+ if (!record2) {
116177
114517
  return {};
116178
114518
  }
116179
- return Object.keys(record3).reduce((acc, rec_key) => {
116180
- acc[rec_key] = (0, exports.convertColumn)(rec_key, columns, record3, skipTypes);
114519
+ return Object.keys(record2).reduce((acc, rec_key) => {
114520
+ acc[rec_key] = (0, exports.convertColumn)(rec_key, columns, record2, skipTypes);
116181
114521
  return acc;
116182
114522
  }, {});
116183
114523
  };
116184
114524
  exports.convertChangeData = convertChangeData;
116185
- var convertColumn = (columnName, columns, record3, skipTypes) => {
114525
+ var convertColumn = (columnName, columns, record2, skipTypes) => {
116186
114526
  const column = columns.find((x2) => x2.name === columnName);
116187
114527
  const colType = column === null || column === undefined ? undefined : column.type;
116188
- const value = record3[columnName];
114528
+ const value = record2[columnName];
116189
114529
  if (colType && !skipTypes.includes(colType)) {
116190
114530
  return (0, exports.convertCell)(colType, value);
116191
114531
  }
@@ -127950,13 +126290,13 @@ var require_core = __commonJS((exports) => {
127950
126290
  return metaOpts;
127951
126291
  }
127952
126292
  var noLogs = { log() {}, warn() {}, error() {} };
127953
- function getLogger(logger3) {
127954
- if (logger3 === false)
126293
+ function getLogger(logger2) {
126294
+ if (logger2 === false)
127955
126295
  return noLogs;
127956
- if (logger3 === undefined)
126296
+ if (logger2 === undefined)
127957
126297
  return console;
127958
- if (logger3.log && logger3.warn && logger3.error)
127959
- return logger3;
126298
+ if (logger2.log && logger2.warn && logger2.error)
126299
+ return logger2;
127960
126300
  throw new Error("logger must implement log, warn and error methods");
127961
126301
  }
127962
126302
  var KEYWORD_NAME = /^[a-z_$][a-z0-9_$:-]*$/i;
@@ -130301,10 +128641,1377 @@ async function shutdownOpenTelemetry() {
130301
128641
  }
130302
128642
  }
130303
128643
 
130304
- // src/index.ts
130305
- init_utils();
130306
- init_logger();
130307
- init_runtime();
128644
+ // src/utils/internal/error-handler/errorHandler.ts
128645
+ init_errors3();
128646
+ var import_api3 = __toESM(require_src(), 1);
128647
+
128648
+ // src/utils/internal/logger.ts
128649
+ init_config();
128650
+ import pino from "pino";
128651
+
128652
+ // src/utils/internal/requestContext.ts
128653
+ var import_api2 = __toESM(require_src(), 1);
128654
+
128655
+ // src/mcp-server/transports/auth/lib/authContext.ts
128656
+ import { AsyncLocalStorage } from "async_hooks";
128657
+ var authContext = new AsyncLocalStorage;
128658
+
128659
+ // src/utils/internal/requestContext.ts
128660
+ var requestContextServiceInstance = {
128661
+ config: {},
128662
+ configure(config3) {
128663
+ this.config = {
128664
+ ...this.config,
128665
+ ...config3
128666
+ };
128667
+ const logContext = this.createRequestContext({
128668
+ operation: "RequestContextService.configure",
128669
+ additionalContext: { newConfigState: { ...this.config } }
128670
+ });
128671
+ logger.debug("RequestContextService configuration updated", logContext);
128672
+ return { ...this.config };
128673
+ },
128674
+ getConfig() {
128675
+ return { ...this.config };
128676
+ },
128677
+ createRequestContext(params = {}) {
128678
+ const { parentContext, additionalContext, operation, ...rest } = params;
128679
+ const inheritedContext = parentContext && typeof parentContext === "object" ? { ...parentContext } : {};
128680
+ let inheritedTenantId;
128681
+ if (inheritedContext && typeof inheritedContext === "object" && "tenantId" in inheritedContext && typeof inheritedContext.tenantId === "string") {
128682
+ inheritedTenantId = inheritedContext.tenantId;
128683
+ }
128684
+ const authStore = authContext.getStore();
128685
+ const tenantIdFromAuth = authStore?.authInfo?.tenantId;
128686
+ const inheritedRequestId = inheritedContext.requestId;
128687
+ const requestId = typeof inheritedRequestId === "string" && inheritedRequestId ? inheritedRequestId : generateRequestContextId();
128688
+ const timestamp = new Date().toISOString();
128689
+ const restTenantId = typeof rest.tenantId === "string" ? rest.tenantId : undefined;
128690
+ const additionalTenantId = additionalContext && typeof additionalContext === "object" && typeof additionalContext.tenantId === "string" ? additionalContext.tenantId : undefined;
128691
+ const resolvedTenantId = additionalTenantId ?? restTenantId ?? inheritedTenantId ?? tenantIdFromAuth;
128692
+ const context = {
128693
+ ...inheritedContext,
128694
+ ...rest,
128695
+ requestId,
128696
+ timestamp,
128697
+ ...resolvedTenantId ? { tenantId: resolvedTenantId } : {},
128698
+ ...additionalContext && typeof additionalContext === "object" ? additionalContext : {},
128699
+ ...operation && typeof operation === "string" ? { operation } : {}
128700
+ };
128701
+ const activeSpan = import_api2.trace.getActiveSpan();
128702
+ if (activeSpan && typeof activeSpan.spanContext === "function") {
128703
+ const spanContext = activeSpan.spanContext();
128704
+ if (spanContext) {
128705
+ context.traceId = spanContext.traceId;
128706
+ context.spanId = spanContext.spanId;
128707
+ }
128708
+ }
128709
+ return context;
128710
+ }
128711
+ };
128712
+ var requestContextService = requestContextServiceInstance;
128713
+
128714
+ // src/utils/security/sanitization.ts
128715
+ init_errors3();
128716
+ var import_validator = __toESM(require_validator(), 1);
128717
+ var isServerless = typeof process === "undefined" || process.env.IS_SERVERLESS === "true";
128718
+ var pathModule;
128719
+ if (!isServerless) {
128720
+ import("path").then((mod2) => {
128721
+ pathModule = mod2.default;
128722
+ }).catch(() => {});
128723
+ }
128724
+
128725
+ class Sanitization {
128726
+ static instance;
128727
+ sensitiveFields = [
128728
+ "password",
128729
+ "token",
128730
+ "secret",
128731
+ "apiKey",
128732
+ "credential",
128733
+ "jwt",
128734
+ "ssn",
128735
+ "cvv",
128736
+ "authorization",
128737
+ "cookie",
128738
+ "clientsecret",
128739
+ "client_secret",
128740
+ "private_key",
128741
+ "privatekey"
128742
+ ];
128743
+ constructor() {}
128744
+ static getInstance() {
128745
+ if (!Sanitization.instance) {
128746
+ Sanitization.instance = new Sanitization;
128747
+ }
128748
+ return Sanitization.instance;
128749
+ }
128750
+ setSensitiveFields(fields) {
128751
+ this.sensitiveFields = [
128752
+ ...new Set([
128753
+ ...this.sensitiveFields,
128754
+ ...fields.map((f3) => f3.toLowerCase())
128755
+ ])
128756
+ ];
128757
+ const logContext = requestContextService.createRequestContext({
128758
+ operation: "Sanitization.setSensitiveFields",
128759
+ additionalContext: {
128760
+ newSensitiveFieldCount: this.sensitiveFields.length
128761
+ }
128762
+ });
128763
+ logger.debug("Updated sensitive fields list for log sanitization", logContext);
128764
+ }
128765
+ getSensitiveFields() {
128766
+ return [...this.sensitiveFields];
128767
+ }
128768
+ getSensitivePinoFields() {
128769
+ return this.sensitiveFields.map((field) => field.replace(/[-_]/g, ""));
128770
+ }
128771
+ sanitizeUrl(input, allowedProtocols = ["http", "https"]) {
128772
+ try {
128773
+ const trimmedInput = input.trim();
128774
+ if (!import_validator.default.isURL(trimmedInput, {
128775
+ protocols: allowedProtocols,
128776
+ require_protocol: true,
128777
+ require_host: true
128778
+ })) {
128779
+ throw new Error("Invalid URL format or protocol not in allowed list.");
128780
+ }
128781
+ const lowercasedInput = trimmedInput.toLowerCase();
128782
+ if (lowercasedInput.startsWith("javascript:") || lowercasedInput.startsWith("data:") || lowercasedInput.startsWith("vbscript:")) {
128783
+ throw new Error("Disallowed pseudo-protocol (javascript:, data:, or vbscript:) in URL.");
128784
+ }
128785
+ return trimmedInput;
128786
+ } catch (error48) {
128787
+ throw new McpError(-32007 /* ValidationError */, error48 instanceof Error ? error48.message : "Invalid or unsafe URL provided.", { input });
128788
+ }
128789
+ }
128790
+ sanitizePath(input, options = {}) {
128791
+ if (isServerless || !pathModule) {
128792
+ throw new McpError(-32603 /* InternalError */, "File-based path sanitization is not supported in this environment.");
128793
+ }
128794
+ const path2 = pathModule;
128795
+ const originalInput = input;
128796
+ const resolvedRootDir = options.rootDir ? path2.resolve(options.rootDir) : undefined;
128797
+ const effectiveOptions = {
128798
+ toPosix: options.toPosix ?? false,
128799
+ allowAbsolute: options.allowAbsolute ?? false,
128800
+ ...resolvedRootDir && { rootDir: resolvedRootDir }
128801
+ };
128802
+ let wasAbsoluteInitially = false;
128803
+ try {
128804
+ if (!input || typeof input !== "string")
128805
+ throw new Error("Invalid path input: must be a non-empty string.");
128806
+ if (input.includes("\x00"))
128807
+ throw new Error("Path contains null byte, which is disallowed.");
128808
+ let normalized = path2.normalize(input);
128809
+ wasAbsoluteInitially = path2.isAbsolute(normalized);
128810
+ if (effectiveOptions.toPosix) {
128811
+ normalized = normalized.replace(/\\/g, "/");
128812
+ }
128813
+ let finalSanitizedPath;
128814
+ if (resolvedRootDir) {
128815
+ let fullPath;
128816
+ if (path2.isAbsolute(normalized)) {
128817
+ fullPath = path2.normalize(normalized);
128818
+ } else {
128819
+ fullPath = path2.resolve(resolvedRootDir, normalized);
128820
+ }
128821
+ const normalizedRoot = path2.normalize(resolvedRootDir);
128822
+ const normalizedFull = path2.normalize(fullPath);
128823
+ if (!normalizedFull.startsWith(normalizedRoot + path2.sep) && normalizedFull !== normalizedRoot) {
128824
+ throw new Error("Path traversal detected: attempts to escape the defined root directory.");
128825
+ }
128826
+ finalSanitizedPath = path2.relative(normalizedRoot, normalizedFull);
128827
+ finalSanitizedPath = finalSanitizedPath === "" ? "." : finalSanitizedPath;
128828
+ if (path2.isAbsolute(finalSanitizedPath) && !effectiveOptions.allowAbsolute) {
128829
+ throw new Error("Path resolved to absolute outside root when absolute paths are disallowed.");
128830
+ }
128831
+ } else {
128832
+ if (path2.isAbsolute(normalized)) {
128833
+ if (!effectiveOptions.allowAbsolute) {
128834
+ throw new Error("Absolute paths are disallowed by current options.");
128835
+ } else {
128836
+ finalSanitizedPath = normalized;
128837
+ }
128838
+ } else {
128839
+ const resolvedAgainstCwd = path2.resolve(normalized);
128840
+ const currentWorkingDir = path2.resolve(".");
128841
+ if (!resolvedAgainstCwd.startsWith(currentWorkingDir + path2.sep) && resolvedAgainstCwd !== currentWorkingDir) {
128842
+ throw new Error("Relative path traversal detected (escapes current working directory context).");
128843
+ }
128844
+ finalSanitizedPath = normalized;
128845
+ }
128846
+ }
128847
+ return {
128848
+ sanitizedPath: finalSanitizedPath,
128849
+ originalInput,
128850
+ wasAbsolute: wasAbsoluteInitially,
128851
+ convertedToRelative: wasAbsoluteInitially && !path2.isAbsolute(finalSanitizedPath) && !effectiveOptions.allowAbsolute,
128852
+ optionsUsed: effectiveOptions
128853
+ };
128854
+ } catch (error48) {
128855
+ logger.warning("Path sanitization error", requestContextService.createRequestContext({
128856
+ operation: "Sanitization.sanitizePath.error",
128857
+ additionalContext: {
128858
+ originalPathInput: originalInput,
128859
+ pathOptionsUsed: effectiveOptions,
128860
+ errorMessage: error48 instanceof Error ? error48.message : String(error48)
128861
+ }
128862
+ }));
128863
+ throw new McpError(-32007 /* ValidationError */, error48 instanceof Error ? error48.message : "Invalid or unsafe path provided.", { input: originalInput });
128864
+ }
128865
+ }
128866
+ sanitizeJson(input, maxSize) {
128867
+ try {
128868
+ if (typeof input !== "string")
128869
+ throw new Error("Invalid input: expected a JSON string.");
128870
+ const computeBytes = (s2) => {
128871
+ if (typeof Buffer !== "undefined" && typeof Buffer.byteLength === "function") {
128872
+ return Buffer.byteLength(s2, "utf8");
128873
+ }
128874
+ if (typeof TextEncoder !== "undefined") {
128875
+ return new TextEncoder().encode(s2).length;
128876
+ }
128877
+ return s2.length;
128878
+ };
128879
+ if (maxSize !== undefined && computeBytes(input) > maxSize) {
128880
+ throw new McpError(-32007 /* ValidationError */, `JSON string exceeds maximum allowed size of ${maxSize} bytes.`, { actualSize: computeBytes(input), maxSize });
128881
+ }
128882
+ return JSON.parse(input);
128883
+ } catch (error48) {
128884
+ if (error48 instanceof McpError)
128885
+ throw error48;
128886
+ throw new McpError(-32007 /* ValidationError */, error48 instanceof Error ? error48.message : "Invalid JSON format.", {
128887
+ inputPreview: input.length > 100 ? `${input.substring(0, 100)}...` : input
128888
+ });
128889
+ }
128890
+ }
128891
+ sanitizeNumber(input, min, max) {
128892
+ let value;
128893
+ if (typeof input === "string") {
128894
+ const trimmedInput = input.trim();
128895
+ if (trimmedInput === "" || !import_validator.default.isNumeric(trimmedInput)) {
128896
+ throw new McpError(-32007 /* ValidationError */, "Invalid number format: input is empty or not numeric.", { input });
128897
+ }
128898
+ value = parseFloat(trimmedInput);
128899
+ } else if (typeof input === "number") {
128900
+ value = input;
128901
+ } else {
128902
+ throw new McpError(-32007 /* ValidationError */, "Invalid input type: expected number or string.", { input: String(input) });
128903
+ }
128904
+ if (isNaN(value) || !isFinite(value)) {
128905
+ throw new McpError(-32007 /* ValidationError */, "Invalid number value (NaN or Infinity).", { input });
128906
+ }
128907
+ let clamped = false;
128908
+ const originalValueForLog = value;
128909
+ if (min !== undefined && value < min) {
128910
+ value = min;
128911
+ clamped = true;
128912
+ }
128913
+ if (max !== undefined && value > max) {
128914
+ value = max;
128915
+ clamped = true;
128916
+ }
128917
+ if (clamped) {
128918
+ logger.debug("Number clamped to range.", requestContextService.createRequestContext({
128919
+ operation: "Sanitization.sanitizeNumber.clamped",
128920
+ additionalContext: {
128921
+ originalInput: String(input),
128922
+ parsedValue: originalValueForLog,
128923
+ minValue: min,
128924
+ maxValue: max,
128925
+ clampedValue: value
128926
+ }
128927
+ }));
128928
+ }
128929
+ return value;
128930
+ }
128931
+ sanitizeForLogging(input) {
128932
+ try {
128933
+ if (!input || typeof input !== "object")
128934
+ return input;
128935
+ const clonedInput = typeof globalThis.structuredClone === "function" ? globalThis.structuredClone(input) : JSON.parse(JSON.stringify(input));
128936
+ this.redactSensitiveFields(clonedInput);
128937
+ return clonedInput;
128938
+ } catch (error48) {
128939
+ logger.error("Error during log sanitization, returning placeholder.", requestContextService.createRequestContext({
128940
+ operation: "Sanitization.sanitizeForLogging.error",
128941
+ additionalContext: {
128942
+ errorMessage: error48 instanceof Error ? error48.message : String(error48)
128943
+ }
128944
+ }));
128945
+ return "[Log Sanitization Failed]";
128946
+ }
128947
+ }
128948
+ redactSensitiveFields(obj) {
128949
+ if (!obj || typeof obj !== "object")
128950
+ return;
128951
+ if (Array.isArray(obj)) {
128952
+ obj.forEach((item) => this.redactSensitiveFields(item));
128953
+ return;
128954
+ }
128955
+ const normalize = (str) => str.toLowerCase().replace(/[^a-z0-9]/g, "");
128956
+ const normalizedSensitiveSet = new Set(this.sensitiveFields.map((f3) => normalize(f3)).filter(Boolean));
128957
+ const wordSensitiveSet = new Set(this.sensitiveFields.map((f3) => f3.toLowerCase()).filter(Boolean));
128958
+ for (const key in obj) {
128959
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
128960
+ const value = obj[key];
128961
+ const normalizedKey = normalize(key);
128962
+ const keyWords = key.replace(/([A-Z])/g, " $1").toLowerCase().split(/[\s_-]+/).filter(Boolean);
128963
+ const isExactSensitive = normalizedSensitiveSet.has(normalizedKey);
128964
+ const isWordSensitive = keyWords.some((w) => wordSensitiveSet.has(w));
128965
+ const isSensitive = isExactSensitive || isWordSensitive;
128966
+ if (isSensitive) {
128967
+ obj[key] = "[REDACTED]";
128968
+ } else if (value && typeof value === "object") {
128969
+ this.redactSensitiveFields(value);
128970
+ }
128971
+ }
128972
+ }
128973
+ }
128974
+ }
128975
+ var sanitization = Sanitization.getInstance();
128976
+ var sanitizeInputForLogging = (input) => sanitization.sanitizeForLogging(input);
128977
+
128978
+ // src/utils/internal/logger.ts
128979
+ var mcpToPinoLevel = {
128980
+ emerg: "fatal",
128981
+ alert: "fatal",
128982
+ crit: "error",
128983
+ error: "error",
128984
+ warning: "warn",
128985
+ notice: "info",
128986
+ info: "info",
128987
+ debug: "debug"
128988
+ };
128989
+ var pinoToMcpLevelSeverity = {
128990
+ fatal: 0,
128991
+ error: 2,
128992
+ warn: 4,
128993
+ info: 6,
128994
+ debug: 7
128995
+ };
128996
+ var isServerless2 = typeof process === "undefined" || process.env.IS_SERVERLESS === "true";
128997
+
128998
+ class Logger {
128999
+ static instance = new Logger;
129000
+ pinoLogger;
129001
+ interactionLogger;
129002
+ initialized = false;
129003
+ currentMcpLevel = "info";
129004
+ transportType;
129005
+ rateLimitThreshold = 10;
129006
+ rateLimitWindow = 60000;
129007
+ messageCounts = new Map;
129008
+ suppressedMessages = new Map;
129009
+ cleanupTimer;
129010
+ constructor() {}
129011
+ static getInstance() {
129012
+ return Logger.instance;
129013
+ }
129014
+ async createPinoLogger(level, transportType) {
129015
+ const pinoLevel = mcpToPinoLevel[level] || "info";
129016
+ const pinoOptions = {
129017
+ level: pinoLevel,
129018
+ base: {
129019
+ env: config2.environment,
129020
+ version: config2.mcpServerVersion,
129021
+ pid: !isServerless2 ? process.pid : undefined
129022
+ },
129023
+ redact: {
129024
+ paths: sanitization.getSensitivePinoFields(),
129025
+ censor: "[REDACTED]"
129026
+ }
129027
+ };
129028
+ if (isServerless2) {
129029
+ return pino(pinoOptions);
129030
+ }
129031
+ const { default: fs2 } = await import("fs");
129032
+ const { default: path2 } = await import("path");
129033
+ const transports = [];
129034
+ const isDevelopment = config2.environment === "development";
129035
+ const isTest = config2.environment === "testing";
129036
+ const noColorEnv = process.env.NO_COLOR === "1" || process.env.FORCE_COLOR === "0";
129037
+ const useColoredOutput = isDevelopment && transportType !== "stdio" && !noColorEnv;
129038
+ if (useColoredOutput && !isServerless2) {
129039
+ try {
129040
+ const { createRequire: createRequire2 } = await import("node:module");
129041
+ const require2 = createRequire2(import.meta.url);
129042
+ const prettyTarget = require2.resolve("pino-pretty");
129043
+ transports.push({
129044
+ target: prettyTarget,
129045
+ options: { colorize: true, translateTime: "yyyy-mm-dd HH:MM:ss" }
129046
+ });
129047
+ } catch (err) {
129048
+ if (process.stderr?.isTTY) {
129049
+ console.warn(`[Logger Init] Pretty transport unavailable (${err instanceof Error ? err.message : String(err)}); falling back to stdout JSON.`);
129050
+ }
129051
+ transports.push({ target: "pino/file", options: { destination: 1 } });
129052
+ }
129053
+ } else if (!isTest) {
129054
+ transports.push({ target: "pino/file", options: { destination: 2 } });
129055
+ }
129056
+ if (config2.logsPath) {
129057
+ try {
129058
+ if (!fs2.existsSync(config2.logsPath)) {
129059
+ fs2.mkdirSync(config2.logsPath, { recursive: true });
129060
+ }
129061
+ transports.push({
129062
+ level: pinoLevel,
129063
+ target: "pino/file",
129064
+ options: {
129065
+ destination: path2.join(config2.logsPath, "combined.log"),
129066
+ mkdir: true
129067
+ }
129068
+ });
129069
+ transports.push({
129070
+ level: "error",
129071
+ target: "pino/file",
129072
+ options: {
129073
+ destination: path2.join(config2.logsPath, "error.log"),
129074
+ mkdir: true
129075
+ }
129076
+ });
129077
+ } catch (err) {
129078
+ if (process.stderr?.isTTY) {
129079
+ console.error(`[Logger Init] Failed to configure file logging: ${err instanceof Error ? err.message : String(err)}`);
129080
+ }
129081
+ }
129082
+ }
129083
+ return pino({ ...pinoOptions, transport: { targets: transports } });
129084
+ }
129085
+ async createInteractionLogger() {
129086
+ if (isServerless2 || !config2.logsPath)
129087
+ return;
129088
+ const { default: path2 } = await import("path");
129089
+ return pino({
129090
+ transport: {
129091
+ target: "pino/file",
129092
+ options: {
129093
+ destination: path2.join(config2.logsPath, "interactions.log"),
129094
+ mkdir: true
129095
+ }
129096
+ }
129097
+ });
129098
+ }
129099
+ async initialize(level = "info", transportType) {
129100
+ if (this.initialized) {
129101
+ this.warning("Logger already initialized.", requestContextService.createRequestContext({
129102
+ operation: "loggerReinit"
129103
+ }));
129104
+ return;
129105
+ }
129106
+ this.currentMcpLevel = level;
129107
+ this.transportType = transportType;
129108
+ this.pinoLogger = await this.createPinoLogger(level, transportType);
129109
+ this.interactionLogger = await this.createInteractionLogger();
129110
+ if (!isServerless2 && !this.cleanupTimer) {
129111
+ this.cleanupTimer = setInterval(() => this.flushSuppressedMessages(), this.rateLimitWindow);
129112
+ this.cleanupTimer.unref?.();
129113
+ }
129114
+ this.initialized = true;
129115
+ this.info(`Logger initialized. MCP level: ${level}.`, requestContextService.createRequestContext({ operation: "loggerInit" }));
129116
+ }
129117
+ setLevel(newLevel) {
129118
+ if (!this.pinoLogger || !this.initialized) {
129119
+ if (process.stderr?.isTTY) {
129120
+ console.error("Cannot set level: Logger not initialized.");
129121
+ }
129122
+ return;
129123
+ }
129124
+ this.currentMcpLevel = newLevel;
129125
+ this.pinoLogger.level = mcpToPinoLevel[newLevel] || "info";
129126
+ this.info(`Log level changed to ${newLevel}.`, requestContextService.createRequestContext({
129127
+ operation: "loggerSetLevel"
129128
+ }));
129129
+ }
129130
+ async close() {
129131
+ if (!this.initialized)
129132
+ return Promise.resolve();
129133
+ this.info("Logger shutting down.", requestContextService.createRequestContext({ operation: "loggerClose" }));
129134
+ if (this.cleanupTimer)
129135
+ clearInterval(this.cleanupTimer);
129136
+ this.flushSuppressedMessages();
129137
+ await Promise.all([
129138
+ new Promise((resolve) => {
129139
+ if (this.pinoLogger) {
129140
+ this.pinoLogger.flush((err) => {
129141
+ if (err && process.stderr?.isTTY && this.transportType !== "stdio") {
129142
+ console.error("Error flushing main logger:", err);
129143
+ }
129144
+ resolve();
129145
+ });
129146
+ } else {
129147
+ resolve();
129148
+ }
129149
+ }),
129150
+ new Promise((resolve) => {
129151
+ if (this.interactionLogger) {
129152
+ this.interactionLogger.flush((err) => {
129153
+ if (err && process.stderr?.isTTY && this.transportType !== "stdio") {
129154
+ console.error("Error flushing interaction logger:", err);
129155
+ }
129156
+ resolve();
129157
+ });
129158
+ } else {
129159
+ resolve();
129160
+ }
129161
+ })
129162
+ ]);
129163
+ this.initialized = false;
129164
+ }
129165
+ isInitialized() {
129166
+ return this.initialized;
129167
+ }
129168
+ isRateLimited(message) {
129169
+ const now = Date.now();
129170
+ const entry = this.messageCounts.get(message);
129171
+ if (!entry) {
129172
+ this.messageCounts.set(message, { count: 1, firstSeen: now });
129173
+ return false;
129174
+ }
129175
+ if (now - entry.firstSeen > this.rateLimitWindow) {
129176
+ this.messageCounts.set(message, { count: 1, firstSeen: now });
129177
+ return false;
129178
+ }
129179
+ entry.count++;
129180
+ if (entry.count > this.rateLimitThreshold) {
129181
+ this.suppressedMessages.set(message, (this.suppressedMessages.get(message) || 0) + 1);
129182
+ return true;
129183
+ }
129184
+ return false;
129185
+ }
129186
+ flushSuppressedMessages() {
129187
+ if (this.suppressedMessages.size === 0)
129188
+ return;
129189
+ for (const [message, count] of this.suppressedMessages.entries()) {
129190
+ this.warning(`Log message suppressed ${count} times due to rate limiting.`, requestContextService.createRequestContext({
129191
+ operation: "loggerRateLimitFlush",
129192
+ additionalContext: { originalMessage: message }
129193
+ }));
129194
+ }
129195
+ this.suppressedMessages.clear();
129196
+ this.messageCounts.clear();
129197
+ }
129198
+ log(level, msg, context, error48) {
129199
+ if (!this.pinoLogger || !this.initialized)
129200
+ return;
129201
+ const pinoLevel = mcpToPinoLevel[level] || "info";
129202
+ const currentPinoLevel = mcpToPinoLevel[this.currentMcpLevel] || "info";
129203
+ const levelSeverity = pinoToMcpLevelSeverity[pinoLevel];
129204
+ const currentLevelSeverity = pinoToMcpLevelSeverity[currentPinoLevel];
129205
+ if (typeof levelSeverity === "number" && typeof currentLevelSeverity === "number" && levelSeverity > currentLevelSeverity) {
129206
+ return;
129207
+ }
129208
+ if (this.isRateLimited(msg))
129209
+ return;
129210
+ const logObject = { ...context };
129211
+ if (error48)
129212
+ logObject.err = pino.stdSerializers.err(error48);
129213
+ this.pinoLogger[pinoLevel](logObject, msg);
129214
+ }
129215
+ debug(msg, context) {
129216
+ this.log("debug", msg, context);
129217
+ }
129218
+ info(msg, context) {
129219
+ this.log("info", msg, context);
129220
+ }
129221
+ notice(msg, context) {
129222
+ this.log("notice", msg, context);
129223
+ }
129224
+ warning(msg, context) {
129225
+ this.log("warning", msg, context);
129226
+ }
129227
+ error(msg, errorOrContext, context) {
129228
+ const errorObj = errorOrContext instanceof Error ? errorOrContext : undefined;
129229
+ const actualContext = errorOrContext instanceof Error ? context : errorOrContext;
129230
+ this.log("error", msg, actualContext, errorObj);
129231
+ }
129232
+ crit(msg, errorOrContext, context) {
129233
+ const errorObj = errorOrContext instanceof Error ? errorOrContext : undefined;
129234
+ const actualContext = errorOrContext instanceof Error ? context : errorOrContext;
129235
+ this.log("crit", msg, actualContext, errorObj);
129236
+ }
129237
+ alert(msg, errorOrContext, context) {
129238
+ const errorObj = errorOrContext instanceof Error ? errorOrContext : undefined;
129239
+ const actualContext = errorOrContext instanceof Error ? context : errorOrContext;
129240
+ this.log("alert", msg, actualContext, errorObj);
129241
+ }
129242
+ emerg(msg, errorOrContext, context) {
129243
+ const errorObj = errorOrContext instanceof Error ? errorOrContext : undefined;
129244
+ const actualContext = errorOrContext instanceof Error ? context : errorOrContext;
129245
+ this.log("emerg", msg, actualContext, errorObj);
129246
+ }
129247
+ fatal(msg, errorOrContext, context) {
129248
+ this.emerg(msg, errorOrContext, context);
129249
+ }
129250
+ logInteraction(interactionName, data) {
129251
+ if (!this.interactionLogger) {
129252
+ if (!isServerless2)
129253
+ this.warning("Interaction logger not available.", data.context || {});
129254
+ return;
129255
+ }
129256
+ this.interactionLogger.info({ interactionName, ...data });
129257
+ }
129258
+ }
129259
+ var logger = Logger.getInstance();
129260
+
129261
+ // src/utils/internal/error-handler/mappings.ts
129262
+ var ERROR_TYPE_MAPPINGS = {
129263
+ SyntaxError: -32007 /* ValidationError */,
129264
+ TypeError: -32007 /* ValidationError */,
129265
+ ReferenceError: -32603 /* InternalError */,
129266
+ RangeError: -32007 /* ValidationError */,
129267
+ URIError: -32007 /* ValidationError */,
129268
+ EvalError: -32603 /* InternalError */,
129269
+ AggregateError: -32603 /* InternalError */
129270
+ };
129271
+ var COMMON_ERROR_PATTERNS = [
129272
+ {
129273
+ pattern: /auth|unauthorized|unauthenticated|not.*logged.*in|invalid.*token|expired.*token/i,
129274
+ errorCode: -32006 /* Unauthorized */
129275
+ },
129276
+ {
129277
+ pattern: /permission|forbidden|access.*denied|not.*allowed/i,
129278
+ errorCode: -32005 /* Forbidden */
129279
+ },
129280
+ {
129281
+ pattern: /not found|missing|no such|doesn't exist|couldn't find/i,
129282
+ errorCode: -32001 /* NotFound */
129283
+ },
129284
+ {
129285
+ pattern: /invalid|validation|malformed|bad request|wrong format|missing required/i,
129286
+ errorCode: -32007 /* ValidationError */
129287
+ },
129288
+ {
129289
+ pattern: /conflict|already exists|duplicate|unique constraint/i,
129290
+ errorCode: -32002 /* Conflict */
129291
+ },
129292
+ {
129293
+ pattern: /rate limit|too many requests|throttled/i,
129294
+ errorCode: -32003 /* RateLimited */
129295
+ },
129296
+ {
129297
+ pattern: /timeout|timed out|deadline exceeded/i,
129298
+ errorCode: -32004 /* Timeout */
129299
+ },
129300
+ {
129301
+ pattern: /abort(ed)?|cancell?ed/i,
129302
+ errorCode: -32004 /* Timeout */
129303
+ },
129304
+ {
129305
+ pattern: /service unavailable|bad gateway|gateway timeout|upstream error/i,
129306
+ errorCode: -32000 /* ServiceUnavailable */
129307
+ },
129308
+ {
129309
+ pattern: /zod|zoderror|schema validation/i,
129310
+ errorCode: -32007 /* ValidationError */
129311
+ }
129312
+ ];
129313
+
129314
+ // src/utils/internal/error-handler/helpers.ts
129315
+ function createSafeRegex(pattern) {
129316
+ if (pattern instanceof RegExp) {
129317
+ let flags = pattern.flags.replace("g", "");
129318
+ if (!flags.includes("i")) {
129319
+ flags += "i";
129320
+ }
129321
+ return new RegExp(pattern.source, flags);
129322
+ }
129323
+ return new RegExp(pattern, "i");
129324
+ }
129325
+ function getErrorName(error48) {
129326
+ if (error48 instanceof Error) {
129327
+ return error48.name || "Error";
129328
+ }
129329
+ if (error48 === null) {
129330
+ return "NullValueEncountered";
129331
+ }
129332
+ if (error48 === undefined) {
129333
+ return "UndefinedValueEncountered";
129334
+ }
129335
+ if (typeof error48 === "object" && error48 !== null && error48.constructor && typeof error48.constructor.name === "string" && error48.constructor.name !== "Object") {
129336
+ return `${error48.constructor.name}Encountered`;
129337
+ }
129338
+ return `${typeof error48}Encountered`;
129339
+ }
129340
+ function getErrorMessage(error48) {
129341
+ try {
129342
+ if (error48 instanceof Error) {
129343
+ if ("errors" in error48 && Array.isArray(error48.errors)) {
129344
+ const inner = error48.errors.map((e2) => e2 instanceof Error ? e2.message : String(e2)).filter(Boolean).slice(0, 3).join("; ");
129345
+ return inner ? `${error48.message}: ${inner}` : error48.message;
129346
+ }
129347
+ return error48.message;
129348
+ }
129349
+ if (error48 === null) {
129350
+ return "Null value encountered as error";
129351
+ }
129352
+ if (error48 === undefined) {
129353
+ return "Undefined value encountered as error";
129354
+ }
129355
+ if (typeof error48 === "string") {
129356
+ return error48;
129357
+ }
129358
+ if (typeof error48 === "number" || typeof error48 === "boolean") {
129359
+ return String(error48);
129360
+ }
129361
+ if (typeof error48 === "bigint") {
129362
+ return error48.toString();
129363
+ }
129364
+ if (typeof error48 === "function") {
129365
+ return `[function ${error48.name || "anonymous"}]`;
129366
+ }
129367
+ if (typeof error48 === "object") {
129368
+ try {
129369
+ const json2 = JSON.stringify(error48);
129370
+ if (json2 && json2 !== "{}")
129371
+ return json2;
129372
+ } catch {}
129373
+ const ctor = error48.constructor?.name;
129374
+ return `Non-Error object encountered (constructor: ${ctor || "Object"})`;
129375
+ }
129376
+ if (typeof error48 === "symbol") {
129377
+ return error48.toString();
129378
+ }
129379
+ return "[unrepresentable error]";
129380
+ } catch (conversionError) {
129381
+ return `Error converting error to string: ${conversionError instanceof Error ? conversionError.message : "Unknown conversion error"}`;
129382
+ }
129383
+ }
129384
+
129385
+ // src/utils/internal/error-handler/errorHandler.ts
129386
+ class ErrorHandler {
129387
+ static determineErrorCode(error48) {
129388
+ if (error48 instanceof McpError) {
129389
+ return error48.code;
129390
+ }
129391
+ const errorName = getErrorName(error48);
129392
+ const errorMessage = getErrorMessage(error48);
129393
+ const mappedFromType = ERROR_TYPE_MAPPINGS[errorName];
129394
+ if (mappedFromType) {
129395
+ return mappedFromType;
129396
+ }
129397
+ for (const mapping of COMMON_ERROR_PATTERNS) {
129398
+ const regex = createSafeRegex(mapping.pattern);
129399
+ if (regex.test(errorMessage) || regex.test(errorName)) {
129400
+ return mapping.errorCode;
129401
+ }
129402
+ }
129403
+ if (typeof error48 === "object" && error48 !== null && "name" in error48 && error48.name === "AbortError") {
129404
+ return -32004 /* Timeout */;
129405
+ }
129406
+ return -32603 /* InternalError */;
129407
+ }
129408
+ static handleError(error48, options) {
129409
+ const activeSpan = import_api3.trace.getActiveSpan();
129410
+ if (activeSpan) {
129411
+ if (error48 instanceof Error) {
129412
+ activeSpan.recordException(error48);
129413
+ }
129414
+ activeSpan.setStatus({
129415
+ code: import_api3.SpanStatusCode.ERROR,
129416
+ message: error48 instanceof Error ? error48.message : String(error48)
129417
+ });
129418
+ }
129419
+ const {
129420
+ context = {},
129421
+ operation,
129422
+ input,
129423
+ rethrow = false,
129424
+ errorCode: explicitErrorCode,
129425
+ includeStack = true,
129426
+ critical = false,
129427
+ errorMapper
129428
+ } = options;
129429
+ const sanitizedInput = input !== undefined ? sanitizeInputForLogging(input) : undefined;
129430
+ const originalErrorName = getErrorName(error48);
129431
+ const originalErrorMessage = getErrorMessage(error48);
129432
+ const originalStack = error48 instanceof Error ? error48.stack : undefined;
129433
+ let finalError;
129434
+ let loggedErrorCode;
129435
+ const errorDataSeed = error48 instanceof McpError && typeof error48.data === "object" && error48.data !== null ? { ...error48.data } : {};
129436
+ const consolidatedData = {
129437
+ ...errorDataSeed,
129438
+ ...context,
129439
+ originalErrorName,
129440
+ originalMessage: originalErrorMessage
129441
+ };
129442
+ if (originalStack && !(error48 instanceof McpError && error48.data?.originalStack)) {
129443
+ consolidatedData.originalStack = originalStack;
129444
+ }
129445
+ const cause = error48 instanceof Error ? error48 : undefined;
129446
+ const rootCause = (() => {
129447
+ let current = cause;
129448
+ let depth = 0;
129449
+ while (current && current instanceof Error && current.cause && depth < 5) {
129450
+ current = current.cause;
129451
+ depth += 1;
129452
+ }
129453
+ return current instanceof Error ? { name: current.name, message: current.message } : undefined;
129454
+ })();
129455
+ if (rootCause) {
129456
+ consolidatedData["rootCause"] = rootCause;
129457
+ }
129458
+ if (error48 instanceof McpError) {
129459
+ loggedErrorCode = error48.code;
129460
+ finalError = errorMapper ? errorMapper(error48) : new McpError(error48.code, error48.message, consolidatedData, {
129461
+ cause
129462
+ });
129463
+ } else {
129464
+ loggedErrorCode = explicitErrorCode || ErrorHandler.determineErrorCode(error48);
129465
+ const message = `Error in ${operation}: ${originalErrorMessage}`;
129466
+ finalError = errorMapper ? errorMapper(error48) : new McpError(loggedErrorCode, message, consolidatedData, {
129467
+ cause
129468
+ });
129469
+ }
129470
+ if (finalError !== error48 && error48 instanceof Error && finalError instanceof Error && !finalError.stack && error48.stack) {
129471
+ finalError.stack = error48.stack;
129472
+ }
129473
+ const logRequestId = typeof context.requestId === "string" && context.requestId ? context.requestId : generateUUID();
129474
+ const logTimestamp = typeof context.timestamp === "string" && context.timestamp ? context.timestamp : new Date().toISOString();
129475
+ const stack = finalError instanceof Error ? finalError.stack : originalStack;
129476
+ const logContext = {
129477
+ requestId: logRequestId,
129478
+ timestamp: logTimestamp,
129479
+ operation,
129480
+ input: sanitizedInput,
129481
+ critical,
129482
+ errorCode: loggedErrorCode,
129483
+ originalErrorType: originalErrorName,
129484
+ finalErrorType: getErrorName(finalError),
129485
+ ...Object.fromEntries(Object.entries(context).filter(([key]) => key !== "requestId" && key !== "timestamp")),
129486
+ errorData: finalError instanceof McpError && finalError.data ? finalError.data : consolidatedData,
129487
+ ...includeStack && stack ? { stack } : {}
129488
+ };
129489
+ logger.error(`Error in ${operation}: ${finalError.message || originalErrorMessage}`, logContext);
129490
+ if (rethrow) {
129491
+ throw finalError;
129492
+ }
129493
+ return finalError;
129494
+ }
129495
+ static mapError(error48, mappings, defaultFactory) {
129496
+ const errorMessage = getErrorMessage(error48);
129497
+ const errorName = getErrorName(error48);
129498
+ for (const mapping of mappings) {
129499
+ const regex = createSafeRegex(mapping.pattern);
129500
+ if (regex.test(errorMessage) || regex.test(errorName)) {
129501
+ return mapping.factory(error48, mapping.additionalContext);
129502
+ }
129503
+ }
129504
+ if (defaultFactory) {
129505
+ return defaultFactory(error48);
129506
+ }
129507
+ return error48 instanceof Error ? error48 : new Error(String(error48));
129508
+ }
129509
+ static formatError(error48) {
129510
+ if (error48 instanceof McpError) {
129511
+ return {
129512
+ code: error48.code,
129513
+ message: error48.message,
129514
+ data: typeof error48.data === "object" && error48.data !== null ? error48.data : {}
129515
+ };
129516
+ }
129517
+ if (error48 instanceof Error) {
129518
+ return {
129519
+ code: ErrorHandler.determineErrorCode(error48),
129520
+ message: error48.message,
129521
+ data: { errorType: error48.name || "Error" }
129522
+ };
129523
+ }
129524
+ return {
129525
+ code: -32099 /* UnknownError */,
129526
+ message: getErrorMessage(error48),
129527
+ data: { errorType: getErrorName(error48) }
129528
+ };
129529
+ }
129530
+ static async tryCatch(fn, options) {
129531
+ try {
129532
+ return await Promise.resolve(fn());
129533
+ } catch (caughtError) {
129534
+ throw ErrorHandler.handleError(caughtError, {
129535
+ ...options,
129536
+ rethrow: true
129537
+ });
129538
+ }
129539
+ }
129540
+ }
129541
+ // src/utils/internal/runtime.ts
129542
+ var safeHas = (key) => {
129543
+ try {
129544
+ return typeof globalThis[key] !== "undefined";
129545
+ } catch {
129546
+ return false;
129547
+ }
129548
+ };
129549
+ var isBun = typeof globalThis.Bun !== "undefined" || typeof process.versions?.bun === "string";
129550
+ var isNode = !isBun && typeof process !== "undefined" && typeof process.versions?.node === "string";
129551
+ var hasProcess = typeof process !== "undefined";
129552
+ var hasBuffer = typeof Buffer !== "undefined";
129553
+ var hasTextEncoder = safeHas("TextEncoder");
129554
+ var hasPerformanceNow = typeof globalThis.performance?.now === "function";
129555
+ var isWorkerLike = !isNode && !isBun && typeof globalThis.WorkerGlobalScope !== "undefined";
129556
+ var isBrowserLike = !isNode && !isBun && !isWorkerLike && safeHas("window");
129557
+ var runtimeCaps = {
129558
+ isNode,
129559
+ isBun,
129560
+ isWorkerLike,
129561
+ isBrowserLike,
129562
+ hasProcess,
129563
+ hasBuffer,
129564
+ hasTextEncoder,
129565
+ hasPerformanceNow
129566
+ };
129567
+ function detectRuntime() {
129568
+ if (runtimeCaps.isBun) {
129569
+ return "bun";
129570
+ }
129571
+ if (runtimeCaps.isNode) {
129572
+ return "node";
129573
+ }
129574
+ if (runtimeCaps.isWorkerLike) {
129575
+ return "worker";
129576
+ }
129577
+ if (runtimeCaps.isBrowserLike) {
129578
+ return "browser";
129579
+ }
129580
+ return "unknown";
129581
+ }
129582
+ function getRuntimeDescription() {
129583
+ const runtime = detectRuntime();
129584
+ switch (runtime) {
129585
+ case "bun":
129586
+ return `Bun ${process.versions?.bun || "unknown"}`;
129587
+ case "node":
129588
+ return `Node.js ${process.versions?.node || "unknown"}`;
129589
+ case "worker":
129590
+ return "Cloudflare Workers / Web Worker";
129591
+ case "browser":
129592
+ return "Browser";
129593
+ default:
129594
+ return "Unknown runtime";
129595
+ }
129596
+ }
129597
+
129598
+ // src/utils/internal/performance.ts
129599
+ init_config();
129600
+ init_errors3();
129601
+ var import_api4 = __toESM(require_src(), 1);
129602
+
129603
+ // src/utils/telemetry/semconv.ts
129604
+ var ATTR_CODE_FUNCTION = "code.function";
129605
+ var ATTR_CODE_NAMESPACE = "code.namespace";
129606
+ var ATTR_MCP_TOOL_INPUT_BYTES = "mcp.tool.input_bytes";
129607
+ var ATTR_MCP_TOOL_OUTPUT_BYTES = "mcp.tool.output_bytes";
129608
+ var ATTR_MCP_TOOL_DURATION_MS = "mcp.tool.duration_ms";
129609
+ var ATTR_MCP_TOOL_SUCCESS = "mcp.tool.success";
129610
+ var ATTR_MCP_TOOL_ERROR_CODE = "mcp.tool.error_code";
129611
+ var ATTR_MCP_TOOL_MEMORY_RSS_BEFORE = "mcp.tool.memory_rss_bytes.before";
129612
+ var ATTR_MCP_TOOL_MEMORY_RSS_AFTER = "mcp.tool.memory_rss_bytes.after";
129613
+ var ATTR_MCP_TOOL_MEMORY_RSS_DELTA = "mcp.tool.memory_rss_bytes.delta";
129614
+ var ATTR_MCP_TOOL_MEMORY_HEAP_USED_BEFORE = "mcp.tool.memory_heap_used_bytes.before";
129615
+ var ATTR_MCP_TOOL_MEMORY_HEAP_USED_AFTER = "mcp.tool.memory_heap_used_bytes.after";
129616
+ var ATTR_MCP_TOOL_MEMORY_HEAP_USED_DELTA = "mcp.tool.memory_heap_used_bytes.delta";
129617
+
129618
+ // src/utils/internal/performance.ts
129619
+ var performanceNow = () => Date.now();
129620
+ async function loadPerfHooks() {
129621
+ return import("perf_hooks");
129622
+ }
129623
+ async function initializePerformance_Hrt() {
129624
+ const globalWithPerf = globalThis;
129625
+ if (typeof globalWithPerf.performance?.now === "function") {
129626
+ const perf = globalWithPerf.performance;
129627
+ performanceNow = () => perf?.now() ?? Date.now();
129628
+ } else {
129629
+ try {
129630
+ const { performance: nodePerformance } = await loadPerfHooks();
129631
+ performanceNow = () => nodePerformance.now();
129632
+ } catch (_e) {
129633
+ performanceNow = () => Date.now();
129634
+ logger.warning("Could not import perf_hooks, falling back to Date.now() for performance timing.");
129635
+ }
129636
+ }
129637
+ }
129638
+ var nowMs = () => performanceNow();
129639
+ var toBytes = (payload) => {
129640
+ if (payload == null)
129641
+ return 0;
129642
+ try {
129643
+ const json2 = JSON.stringify(payload);
129644
+ if (typeof Buffer !== "undefined" && typeof Buffer.byteLength === "function") {
129645
+ const bytes = Buffer.byteLength(json2, "utf8");
129646
+ return bytes;
129647
+ }
129648
+ if (typeof TextEncoder !== "undefined") {
129649
+ return new TextEncoder().encode(json2).length;
129650
+ }
129651
+ return json2.length;
129652
+ } catch {
129653
+ return 0;
129654
+ }
129655
+ };
129656
+ async function measureToolExecution(toolLogicFn, context, inputPayload) {
129657
+ const tracer = import_api4.trace.getTracer(config2.openTelemetry.serviceName, config2.openTelemetry.serviceVersion);
129658
+ const { toolName } = context;
129659
+ return tracer.startActiveSpan(`tool_execution:${toolName}`, async (span) => {
129660
+ const memBefore = typeof process !== "undefined" && typeof process.memoryUsage === "function" ? process.memoryUsage() : { rss: 0, heapUsed: 0 };
129661
+ const t0 = nowMs();
129662
+ span.setAttributes({
129663
+ [ATTR_CODE_FUNCTION]: toolName,
129664
+ [ATTR_CODE_NAMESPACE]: "mcp-tools",
129665
+ [ATTR_MCP_TOOL_INPUT_BYTES]: toBytes(inputPayload),
129666
+ [ATTR_MCP_TOOL_MEMORY_RSS_BEFORE]: memBefore.rss,
129667
+ [ATTR_MCP_TOOL_MEMORY_HEAP_USED_BEFORE]: memBefore.heapUsed
129668
+ });
129669
+ let ok = false;
129670
+ let errorCode;
129671
+ let output;
129672
+ try {
129673
+ const result = await toolLogicFn();
129674
+ ok = true;
129675
+ output = result;
129676
+ span.setStatus({ code: import_api4.SpanStatusCode.OK });
129677
+ span.setAttribute(ATTR_MCP_TOOL_OUTPUT_BYTES, toBytes(output));
129678
+ return result;
129679
+ } catch (err) {
129680
+ if (err instanceof McpError)
129681
+ errorCode = String(err.code);
129682
+ else if (err instanceof Error)
129683
+ errorCode = "UNHANDLED_ERROR";
129684
+ else
129685
+ errorCode = "UNKNOWN_ERROR";
129686
+ if (err instanceof Error)
129687
+ span.recordException(err);
129688
+ span.setStatus({
129689
+ code: import_api4.SpanStatusCode.ERROR,
129690
+ message: err instanceof Error ? err.message : String(err)
129691
+ });
129692
+ throw err;
129693
+ } finally {
129694
+ const t1 = nowMs();
129695
+ const durationMs = Number((t1 - t0).toFixed(2));
129696
+ const memAfter = typeof process !== "undefined" && typeof process.memoryUsage === "function" ? process.memoryUsage() : { rss: 0, heapUsed: 0 };
129697
+ const rssDelta = memAfter.rss - memBefore.rss;
129698
+ const heapUsedDelta = memAfter.heapUsed - memBefore.heapUsed;
129699
+ span.setAttributes({
129700
+ [ATTR_MCP_TOOL_DURATION_MS]: durationMs,
129701
+ [ATTR_MCP_TOOL_SUCCESS]: ok,
129702
+ [ATTR_MCP_TOOL_MEMORY_RSS_AFTER]: memAfter.rss,
129703
+ [ATTR_MCP_TOOL_MEMORY_HEAP_USED_AFTER]: memAfter.heapUsed,
129704
+ [ATTR_MCP_TOOL_MEMORY_RSS_DELTA]: rssDelta,
129705
+ [ATTR_MCP_TOOL_MEMORY_HEAP_USED_DELTA]: heapUsedDelta
129706
+ });
129707
+ if (errorCode)
129708
+ span.setAttribute(ATTR_MCP_TOOL_ERROR_CODE, errorCode);
129709
+ span.end();
129710
+ logger.info("Tool execution finished.", {
129711
+ ...context,
129712
+ metrics: {
129713
+ durationMs,
129714
+ isSuccess: ok,
129715
+ errorCode,
129716
+ inputBytes: toBytes(inputPayload),
129717
+ outputBytes: toBytes(output),
129718
+ memory: {
129719
+ rss: {
129720
+ before: memBefore.rss,
129721
+ after: memAfter.rss,
129722
+ delta: rssDelta
129723
+ },
129724
+ heapUsed: {
129725
+ before: memBefore.heapUsed,
129726
+ after: memAfter.heapUsed,
129727
+ delta: heapUsedDelta
129728
+ }
129729
+ }
129730
+ }
129731
+ });
129732
+ }
129733
+ });
129734
+ }
129735
+
129736
+ // src/utils/internal/startupBanner.ts
129737
+ function logStartupBanner(message, transportType) {
129738
+ if (process.stdout.isTTY) {
129739
+ if (transportType === "stdio") {
129740
+ console.error(message);
129741
+ } else {
129742
+ console.log(message);
129743
+ }
129744
+ }
129745
+ }
129746
+
129747
+ // src/utils/security/idGenerator.ts
129748
+ init_errors3();
129749
+ import { randomUUID as cryptoRandomUUID, randomBytes } from "crypto";
129750
+
129751
+ class IdGenerator {
129752
+ static DEFAULT_CHARSET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
129753
+ static DEFAULT_SEPARATOR = "_";
129754
+ static DEFAULT_LENGTH = 6;
129755
+ entityPrefixes = {};
129756
+ prefixToEntityType = {};
129757
+ constructor(entityPrefixes = {}) {
129758
+ this.setEntityPrefixes(entityPrefixes);
129759
+ }
129760
+ setEntityPrefixes(entityPrefixes) {
129761
+ this.entityPrefixes = { ...entityPrefixes };
129762
+ this.prefixToEntityType = Object.entries(this.entityPrefixes).reduce((acc, [type, prefix]) => {
129763
+ acc[prefix.toLowerCase()] = type;
129764
+ return acc;
129765
+ }, {});
129766
+ }
129767
+ getEntityPrefixes() {
129768
+ return { ...this.entityPrefixes };
129769
+ }
129770
+ generateRandomString(length = IdGenerator.DEFAULT_LENGTH, charset = IdGenerator.DEFAULT_CHARSET) {
129771
+ let result = "";
129772
+ const maxValidByteValue = Math.floor(256 / charset.length) * charset.length;
129773
+ while (result.length < length) {
129774
+ const byteBuffer = randomBytes(1);
129775
+ const byte = byteBuffer[0];
129776
+ if (byte !== undefined && byte < maxValidByteValue) {
129777
+ const charIndex = byte % charset.length;
129778
+ const char = charset[charIndex];
129779
+ if (char) {
129780
+ result += char;
129781
+ }
129782
+ }
129783
+ }
129784
+ return result;
129785
+ }
129786
+ generate(prefix, options = {}) {
129787
+ const {
129788
+ length = IdGenerator.DEFAULT_LENGTH,
129789
+ separator = IdGenerator.DEFAULT_SEPARATOR,
129790
+ charset = IdGenerator.DEFAULT_CHARSET
129791
+ } = options;
129792
+ const randomPart = this.generateRandomString(length, charset);
129793
+ const generatedId = prefix ? `${prefix}${separator}${randomPart}` : randomPart;
129794
+ return generatedId;
129795
+ }
129796
+ generateForEntity(entityType, options = {}) {
129797
+ const prefix = this.entityPrefixes[entityType];
129798
+ if (!prefix) {
129799
+ throw new McpError(-32007 /* ValidationError */, `Unknown entity type: ${entityType}. No prefix registered.`);
129800
+ }
129801
+ return this.generate(prefix, options);
129802
+ }
129803
+ isValid(id, entityType, options = {}) {
129804
+ const prefix = this.entityPrefixes[entityType];
129805
+ const {
129806
+ length = IdGenerator.DEFAULT_LENGTH,
129807
+ separator = IdGenerator.DEFAULT_SEPARATOR,
129808
+ charset = IdGenerator.DEFAULT_CHARSET
129809
+ } = options;
129810
+ if (!prefix) {
129811
+ return false;
129812
+ }
129813
+ const escapedCharsetForClass = charset.replace(/[[\]\\^-]/g, "\\$&");
129814
+ const charsetRegexPart = `[${escapedCharsetForClass}]`;
129815
+ const pattern = new RegExp(`^${this.escapeRegex(prefix)}${this.escapeRegex(separator)}${charsetRegexPart}{${length}}$`);
129816
+ return pattern.test(id);
129817
+ }
129818
+ escapeRegex(str) {
129819
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
129820
+ }
129821
+ stripPrefix(id, separator = IdGenerator.DEFAULT_SEPARATOR) {
129822
+ const parts = id.split(separator);
129823
+ return parts.length > 1 ? parts.slice(1).join(separator) : id;
129824
+ }
129825
+ getEntityType(id, separator = IdGenerator.DEFAULT_SEPARATOR) {
129826
+ const parts = id.split(separator);
129827
+ if (parts.length < 2 || !parts[0]) {
129828
+ throw new McpError(-32007 /* ValidationError */, `Invalid ID format: ${id}. Expected format like: PREFIX${separator}RANDOMLPART`);
129829
+ }
129830
+ const prefix = parts[0];
129831
+ const entityType = this.prefixToEntityType[prefix.toLowerCase()];
129832
+ if (!entityType) {
129833
+ throw new McpError(-32007 /* ValidationError */, `Unknown entity type for prefix: ${prefix}`);
129834
+ }
129835
+ return entityType;
129836
+ }
129837
+ normalize(id, separator = IdGenerator.DEFAULT_SEPARATOR) {
129838
+ const entityType = this.getEntityType(id, separator);
129839
+ const registeredPrefix = this.entityPrefixes[entityType];
129840
+ const idParts = id.split(separator);
129841
+ const randomPart = idParts.slice(1).join(separator);
129842
+ return `${registeredPrefix}${separator}${randomPart.toUpperCase()}`;
129843
+ }
129844
+ }
129845
+ var idGenerator = new IdGenerator;
129846
+ var generateUUID = () => {
129847
+ return cryptoRandomUUID();
129848
+ };
129849
+ var generateRequestContextId = () => {
129850
+ const generateSecureRandomString = (length, charset2) => {
129851
+ let result = "";
129852
+ const maxValidByteValue = Math.floor(256 / charset2.length) * charset2.length;
129853
+ while (result.length < length) {
129854
+ const byteBuffer = randomBytes(1);
129855
+ const byte = byteBuffer[0];
129856
+ if (byte !== undefined && byte < maxValidByteValue) {
129857
+ const charIndex = byte % charset2.length;
129858
+ const char = charset2[charIndex];
129859
+ if (char) {
129860
+ result += char;
129861
+ }
129862
+ }
129863
+ }
129864
+ return result;
129865
+ };
129866
+ const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
129867
+ const part1 = generateSecureRandomString(5, charset);
129868
+ const part2 = generateSecureRandomString(5, charset);
129869
+ return `${part1}-${part2}`;
129870
+ };
129871
+
129872
+ // src/utils/security/rateLimiter.ts
129873
+ init_tokens();
129874
+ init_errors3();
129875
+ var import_api5 = __toESM(require_src(), 1);
129876
+ var import_tsyringe = __toESM(require_cjs2(), 1);
129877
+ class RateLimiter {
129878
+ config;
129879
+ logger;
129880
+ limits;
129881
+ cleanupTimer = null;
129882
+ effectiveConfig;
129883
+ constructor(config3, logger2) {
129884
+ this.config = config3;
129885
+ this.logger = logger2;
129886
+ const defaultConfig = {
129887
+ windowMs: 15 * 60 * 1000,
129888
+ maxRequests: 100,
129889
+ errorMessage: "Rate limit exceeded. Please try again in {waitTime} seconds.",
129890
+ skipInDevelopment: false,
129891
+ cleanupInterval: 5 * 60 * 1000
129892
+ };
129893
+ this.effectiveConfig = { ...defaultConfig };
129894
+ this.limits = new Map;
129895
+ this.startCleanupTimer();
129896
+ }
129897
+ startCleanupTimer() {
129898
+ if (this.cleanupTimer) {
129899
+ clearInterval(this.cleanupTimer);
129900
+ }
129901
+ const interval = this.effectiveConfig.cleanupInterval;
129902
+ if (interval && interval > 0) {
129903
+ this.cleanupTimer = setInterval(() => {
129904
+ this.cleanupExpiredEntries();
129905
+ }, interval);
129906
+ if (this.cleanupTimer.unref) {
129907
+ this.cleanupTimer.unref();
129908
+ }
129909
+ }
129910
+ }
129911
+ cleanupExpiredEntries() {
129912
+ const now = Date.now();
129913
+ let expiredCount = 0;
129914
+ for (const [key, entry] of this.limits.entries()) {
129915
+ if (now >= entry.resetTime) {
129916
+ this.limits.delete(key);
129917
+ expiredCount++;
129918
+ }
129919
+ }
129920
+ if (expiredCount > 0) {
129921
+ const logContext = requestContextService.createRequestContext({
129922
+ operation: "RateLimiter.cleanupExpiredEntries",
129923
+ additionalContext: {
129924
+ cleanedCount: expiredCount,
129925
+ totalRemainingAfterClean: this.limits.size
129926
+ }
129927
+ });
129928
+ this.logger.debug(`Cleaned up ${expiredCount} expired rate limit entries`, logContext);
129929
+ }
129930
+ }
129931
+ configure(config3) {
129932
+ Object.assign(this.effectiveConfig, config3);
129933
+ if (config3.cleanupInterval !== undefined) {
129934
+ this.startCleanupTimer();
129935
+ }
129936
+ }
129937
+ getConfig() {
129938
+ return { ...this.effectiveConfig };
129939
+ }
129940
+ reset() {
129941
+ this.limits.clear();
129942
+ const logContext = requestContextService.createRequestContext({
129943
+ operation: "RateLimiter.reset"
129944
+ });
129945
+ this.logger.debug("Rate limiter reset, all limits cleared", logContext);
129946
+ }
129947
+ check(key, context) {
129948
+ const activeSpan = import_api5.trace.getActiveSpan();
129949
+ activeSpan?.setAttribute("mcp.rate_limit.checked", true);
129950
+ if (this.effectiveConfig.skipInDevelopment && this.config.environment === "development") {
129951
+ activeSpan?.setAttribute("mcp.rate_limit.skipped", "development");
129952
+ return;
129953
+ }
129954
+ const limitKey = this.effectiveConfig.keyGenerator ? this.effectiveConfig.keyGenerator(key, context) : key;
129955
+ activeSpan?.setAttribute("mcp.rate_limit.key", limitKey);
129956
+ const now = Date.now();
129957
+ let entry = this.limits.get(limitKey);
129958
+ if (!entry || now >= entry.resetTime) {
129959
+ entry = {
129960
+ count: 1,
129961
+ resetTime: now + this.effectiveConfig.windowMs
129962
+ };
129963
+ this.limits.set(limitKey, entry);
129964
+ } else {
129965
+ entry.count++;
129966
+ }
129967
+ const remaining = Math.max(0, this.effectiveConfig.maxRequests - entry.count);
129968
+ activeSpan?.setAttributes({
129969
+ "mcp.rate_limit.limit": this.effectiveConfig.maxRequests,
129970
+ "mcp.rate_limit.count": entry.count,
129971
+ "mcp.rate_limit.remaining": remaining
129972
+ });
129973
+ if (entry.count > this.effectiveConfig.maxRequests) {
129974
+ const waitTime = Math.ceil((entry.resetTime - now) / 1000);
129975
+ const errorMessage = (this.effectiveConfig.errorMessage || "Rate limit exceeded. Please try again in {waitTime} seconds.").replace("{waitTime}", waitTime.toString());
129976
+ activeSpan?.addEvent("rate_limit_exceeded", {
129977
+ "mcp.rate_limit.wait_time_seconds": waitTime
129978
+ });
129979
+ throw new McpError(-32003 /* RateLimited */, errorMessage, {
129980
+ waitTimeSeconds: waitTime,
129981
+ key: limitKey,
129982
+ limit: this.effectiveConfig.maxRequests,
129983
+ windowMs: this.effectiveConfig.windowMs
129984
+ });
129985
+ }
129986
+ }
129987
+ getStatus(key) {
129988
+ const entry = this.limits.get(key);
129989
+ if (!entry)
129990
+ return null;
129991
+ return {
129992
+ current: entry.count,
129993
+ limit: this.effectiveConfig.maxRequests,
129994
+ remaining: Math.max(0, this.effectiveConfig.maxRequests - entry.count),
129995
+ resetTime: entry.resetTime
129996
+ };
129997
+ }
129998
+ dispose() {
129999
+ if (this.cleanupTimer) {
130000
+ clearInterval(this.cleanupTimer);
130001
+ this.cleanupTimer = null;
130002
+ }
130003
+ this.limits.clear();
130004
+ }
130005
+ }
130006
+ RateLimiter = __legacyDecorateClassTS([
130007
+ import_tsyringe.injectable(),
130008
+ __legacyDecorateParamTS(0, import_tsyringe.inject(AppConfig)),
130009
+ __legacyDecorateParamTS(1, import_tsyringe.inject(Logger2)),
130010
+ __legacyMetadataTS("design:paramtypes", [
130011
+ Object,
130012
+ Object
130013
+ ])
130014
+ ], RateLimiter);
130308
130015
 
130309
130016
  // src/container/index.ts
130310
130017
  var import_reflect_metadata = __toESM(require_Reflect(), 1);
@@ -132765,13 +132472,8 @@ if (shouldShowDeprecationWarning())
132765
132472
  init_config();
132766
132473
  init_tokens();
132767
132474
 
132768
- // src/services/git/core/GitProviderFactory.ts
132769
- init_utils();
132770
-
132771
132475
  // src/services/git/core/BaseGitProvider.ts
132772
132476
  init_errors3();
132773
- init_utils();
132774
-
132775
132477
  class BaseGitProvider {
132776
132478
  checkCapability(capability) {
132777
132479
  if (!this.capabilities[capability]) {
@@ -132805,12 +132507,12 @@ class BaseGitProvider {
132805
132507
  workingDirectory
132806
132508
  });
132807
132509
  }
132808
- createOperationContext(requestContext2, workingDirectory, tenantId) {
132510
+ createOperationContext(requestContext, workingDirectory, tenantId) {
132809
132511
  const context = {
132810
- requestContext: requestContext2,
132512
+ requestContext,
132811
132513
  workingDirectory
132812
132514
  };
132813
- const finalTenantId = tenantId || requestContext2.tenantId;
132515
+ const finalTenantId = tenantId || requestContext.tenantId;
132814
132516
  if (finalTenantId) {
132815
132517
  context.tenantId = finalTenantId;
132816
132518
  }
@@ -133196,8 +132898,8 @@ Stdout: ${stdout}`;
133196
132898
  });
133197
132899
  }
133198
132900
  async function spawnGitCommand(args, cwd, env, timeout = 60000, signal, allowNonZeroExit = false) {
133199
- const runtime2 = detectRuntime2();
133200
- if (runtime2 === "bun") {
132901
+ const runtime = detectRuntime2();
132902
+ if (runtime === "bun") {
133201
132903
  return spawnWithBun(args, cwd, env, timeout, signal, allowNonZeroExit);
133202
132904
  } else {
133203
132905
  return spawnWithNode(args, cwd, env, timeout, signal, allowNonZeroExit);
@@ -133269,6 +132971,15 @@ function parseGitStatus(output) {
133269
132971
  const parts2 = line.split(" ");
133270
132972
  if (parts2[1] === "branch.head" && parts2[2]) {
133271
132973
  result.currentBranch = parts2[2] === "(detached)" ? null : parts2[2];
132974
+ } else if (parts2[1] === "branch.upstream" && parts2[2]) {
132975
+ result.upstream = parts2[2];
132976
+ } else if (parts2[1] === "branch.ab" && parts2[2] && parts2[3]) {
132977
+ const ahead = parseInt(parts2[2].replace(/^\+/, ""), 10);
132978
+ const behind = parseInt(parts2[3].replace(/^-/, ""), 10);
132979
+ if (Number.isFinite(ahead))
132980
+ result.ahead = ahead;
132981
+ if (Number.isFinite(behind))
132982
+ result.behind = behind;
133272
132983
  }
133273
132984
  continue;
133274
132985
  }
@@ -133669,7 +133380,6 @@ async function listDirtyFiles(execGit, cwd, ctx) {
133669
133380
  return files;
133670
133381
  }
133671
133382
  // src/services/git/providers/cli/operations/commits/commit.ts
133672
- init_utils();
133673
133383
  async function executeCommit(options, context, execGit) {
133674
133384
  try {
133675
133385
  if (options.filesToStage?.length) {
@@ -133760,7 +133470,9 @@ var COMMIT_START_MARKER = "<<<COMMIT_START>>>";
133760
133470
  var COMMIT_END_MARKER = "<<<COMMIT_END>>>";
133761
133471
  async function executeLog(options, context, execGit) {
133762
133472
  try {
133763
- const formatStr = `${COMMIT_START_MARKER}%H${GIT_FIELD_DELIMITER}%h${GIT_FIELD_DELIMITER}%an${GIT_FIELD_DELIMITER}%ae${GIT_FIELD_DELIMITER}%at${GIT_FIELD_DELIMITER}%s${GIT_FIELD_DELIMITER}%b${GIT_FIELD_DELIMITER}%P${COMMIT_END_MARKER}`;
133473
+ const fullFormat = `${COMMIT_START_MARKER}%H${GIT_FIELD_DELIMITER}%h${GIT_FIELD_DELIMITER}%an${GIT_FIELD_DELIMITER}%ae${GIT_FIELD_DELIMITER}%at${GIT_FIELD_DELIMITER}%s${GIT_FIELD_DELIMITER}%b${GIT_FIELD_DELIMITER}%P${COMMIT_END_MARKER}`;
133474
+ const onelineFormat = `${COMMIT_START_MARKER}%H${GIT_FIELD_DELIMITER}%h${GIT_FIELD_DELIMITER}%s${COMMIT_END_MARKER}`;
133475
+ const formatStr = options.oneline ? onelineFormat : fullFormat;
133764
133476
  const args = [`--format=${formatStr}`];
133765
133477
  if (options.maxCount) {
133766
133478
  args.push(`-n${options.maxCount}`);
@@ -133803,7 +133515,11 @@ async function executeLog(options, context, execGit) {
133803
133515
  const formatPart = section.substring(0, endIdx);
133804
133516
  const extraPart = section.substring(endIdx + COMMIT_END_MARKER.length).trim();
133805
133517
  const fields = formatPart.split(GIT_FIELD_DELIMITER);
133806
- const commit = {
133518
+ const commit = options.oneline ? {
133519
+ hash: fields[0] || "",
133520
+ shortHash: fields[1] || "",
133521
+ subject: fields[2] || ""
133522
+ } : {
133807
133523
  hash: fields[0] || "",
133808
133524
  shortHash: fields[1] || "",
133809
133525
  author: fields[2] || "",
@@ -133812,7 +133528,7 @@ async function executeLog(options, context, execGit) {
133812
133528
  subject: fields[5] || "",
133813
133529
  parents: (fields[7] || "").split(" ").filter((p) => p)
133814
133530
  };
133815
- if (fields[6]) {
133531
+ if (!options.oneline && fields[6]) {
133816
133532
  commit.body = fields[6];
133817
133533
  }
133818
133534
  if (extraPart) {
@@ -133860,11 +133576,13 @@ async function executeShow(options, context, execGit) {
133860
133576
  command: "cat-file",
133861
133577
  args: ["-t", options.object]
133862
133578
  });
133863
- const typeResult = await execGit(typeCmd, context.workingDirectory, context.requestContext);
133579
+ const cmd = buildGitCommand({ command: "show", args });
133580
+ const [typeResult, result] = await Promise.all([
133581
+ execGit(typeCmd, context.workingDirectory, context.requestContext),
133582
+ execGit(cmd, context.workingDirectory, context.requestContext)
133583
+ ]);
133864
133584
  const detectedType = typeResult.stdout.trim();
133865
133585
  const objectType = ["commit", "tree", "blob", "tag"].includes(detectedType) ? detectedType : "commit";
133866
- const cmd = buildGitCommand({ command: "show", args });
133867
- const result = await execGit(cmd, context.workingDirectory, context.requestContext);
133868
133586
  const showResult = {
133869
133587
  object: options.object,
133870
133588
  type: objectType,
@@ -134060,6 +133778,21 @@ async function executeBranch(options, context, execGit) {
134060
133778
  try {
134061
133779
  const args = [];
134062
133780
  switch (options.mode) {
133781
+ case "show-current": {
133782
+ const cmd = buildGitCommand({
133783
+ command: "symbolic-ref",
133784
+ args: ["--quiet", "--short", "HEAD"]
133785
+ });
133786
+ try {
133787
+ const res = await execGit(cmd, context.workingDirectory, context.requestContext);
133788
+ return {
133789
+ mode: "show-current",
133790
+ current: res.stdout.trim() || null
133791
+ };
133792
+ } catch {
133793
+ return { mode: "show-current", current: null };
133794
+ }
133795
+ }
134063
133796
  case "list": {
134064
133797
  const format = [
134065
133798
  "%(refname)",
@@ -134078,6 +133811,9 @@ async function executeBranch(options, context, execGit) {
134078
133811
  const noMergedRef = typeof options.noMerged === "string" ? options.noMerged : "HEAD";
134079
133812
  args.push(`--no-merged=${noMergedRef}`);
134080
133813
  }
133814
+ if (typeof options.limit === "number" && options.limit > 0) {
133815
+ args.push(`--count=${options.limit}`);
133816
+ }
134081
133817
  const cmd = buildGitCommand({ command: "for-each-ref", args });
134082
133818
  const result = await execGit(cmd, context.workingDirectory, context.requestContext);
134083
133819
  const branches = parseBranchRef(result.stdout);
@@ -134718,7 +134454,7 @@ function parseFilesChanged(stdout) {
134718
134454
  return files;
134719
134455
  }
134720
134456
  // src/services/git/providers/cli/operations/tags/tag.ts
134721
- init_utils();
134457
+ init_errors3();
134722
134458
  async function executeTag(options, context, execGit) {
134723
134459
  try {
134724
134460
  const args = [];
@@ -134729,17 +134465,26 @@ async function executeTag(options, context, execGit) {
134729
134465
  "%(if)%(*objectname:short)%(then)%(*objectname:short)%(else)%(objectname:short)%(end)",
134730
134466
  "%(if)%(contents:subject)%(then)%(contents:subject)%(end)",
134731
134467
  "%(if)%(taggername)%(then)%(taggername) %(taggeremail)%(end)",
134732
- "%(if)%(creatordate:unix)%(then)%(creatordate:unix)%(end)"
134733
- ].join(GIT_FIELD_DELIMITER);
134468
+ "%(if)%(creatordate:unix)%(then)%(creatordate:unix)%(end)",
134469
+ "%(if)%(contents:body)%(then)%(contents:body)%(end)"
134470
+ ].join(GIT_FIELD_DELIMITER) + GIT_RECORD_DELIMITER;
134471
+ const forEachRefArgs = [
134472
+ `--format=${format}`,
134473
+ "--sort=-version:refname",
134474
+ "--sort=-creatordate"
134475
+ ];
134476
+ if (typeof options.limit === "number" && options.limit > 0) {
134477
+ forEachRefArgs.push(`--count=${options.limit}`);
134478
+ }
134479
+ forEachRefArgs.push("refs/tags");
134734
134480
  const refCmd = buildGitCommand({
134735
134481
  command: "for-each-ref",
134736
- args: [`--format=${format}`, "--sort=-creatordate", "refs/tags"]
134482
+ args: forEachRefArgs
134737
134483
  });
134738
134484
  const result = await execGit(refCmd, context.workingDirectory, context.requestContext);
134739
134485
  const tags = [];
134740
- for (const line of result.stdout.split(`
134741
- `).filter((l) => l.trim())) {
134742
- const [name, commit, message, tagger, timestamp] = line.split(GIT_FIELD_DELIMITER);
134486
+ for (const record2 of result.stdout.split(GIT_RECORD_DELIMITER).map((r2) => r2.replace(/^\n/, "")).filter((r2) => r2.length > 0)) {
134487
+ const [name, commit, message, tagger, timestamp, annotationBody] = record2.split(GIT_FIELD_DELIMITER);
134743
134488
  if (!name)
134744
134489
  continue;
134745
134490
  const tag = {
@@ -134752,6 +134497,8 @@ async function executeTag(options, context, execGit) {
134752
134497
  tag.tagger = tagger;
134753
134498
  if (timestamp)
134754
134499
  tag.timestamp = parseInt(timestamp, 10);
134500
+ if (annotationBody)
134501
+ tag.annotationBody = annotationBody.trimEnd();
134755
134502
  tags.push(tag);
134756
134503
  }
134757
134504
  return { mode: "list", tags };
@@ -134826,6 +134573,17 @@ async function executeTag(options, context, execGit) {
134826
134573
  };
134827
134574
  return deleteResult;
134828
134575
  }
134576
+ case "verify": {
134577
+ if (!options.tagName) {
134578
+ throw new Error("Tag name is required for verify operation");
134579
+ }
134580
+ const cmd = buildGitCommand({
134581
+ command: "tag",
134582
+ args: ["-v", options.tagName]
134583
+ });
134584
+ const result = await execGit(cmd, context.workingDirectory, context.requestContext, { allowNonZeroExit: true });
134585
+ return parseVerifyOutput(options.tagName, result.stderr, result.exitCode ?? 0);
134586
+ }
134829
134587
  default:
134830
134588
  throw new Error("Unknown tag operation mode");
134831
134589
  }
@@ -134833,6 +134591,93 @@ async function executeTag(options, context, execGit) {
134833
134591
  throw mapGitError(error48, "tag");
134834
134592
  }
134835
134593
  }
134594
+ function parseVerifyOutput(tagName, stderr, exitCode) {
134595
+ if (/^error: tag '.+' not found/m.test(stderr)) {
134596
+ throw new McpError(-32600 /* InvalidRequest */, `Tag not found: ${tagName}`, { tagName });
134597
+ }
134598
+ const base = {
134599
+ mode: "verify",
134600
+ verifiedTag: tagName,
134601
+ rawOutput: stderr
134602
+ };
134603
+ if (/^error: no signature found$/m.test(stderr)) {
134604
+ return {
134605
+ ...base,
134606
+ verified: false,
134607
+ warning: "Tag has no signature. Create with a signing key and `GIT_SIGN_COMMITS=true` to produce a signed tag."
134608
+ };
134609
+ }
134610
+ if (/gpg\.ssh\.allowedSignersFile needs to be configured/.test(stderr) || /No principal matched/.test(stderr)) {
134611
+ return {
134612
+ ...base,
134613
+ verified: false,
134614
+ signatureType: "ssh",
134615
+ warning: "SSH signature verification requires `gpg.ssh.allowedSignersFile` to be configured. The tag may be validly signed; this environment cannot verify it."
134616
+ };
134617
+ }
134618
+ const gpgBadMatch = /(?:gpg|gpgsm): BAD signature from "([^"]+)"/.exec(stderr);
134619
+ if (gpgBadMatch) {
134620
+ return {
134621
+ ...base,
134622
+ verified: false,
134623
+ signatureType: stderr.includes("gpgsm:") ? "x509" : "gpg",
134624
+ signerIdentity: gpgBadMatch[1],
134625
+ warning: "Signature does not validate (BAD signature)."
134626
+ };
134627
+ }
134628
+ const sshBadMatch = /Signature verification failed.*? for "([^"]+)"|Could not verify signature/i.exec(stderr);
134629
+ if (sshBadMatch && exitCode !== 0) {
134630
+ const result = {
134631
+ ...base,
134632
+ verified: false,
134633
+ signatureType: "ssh",
134634
+ warning: "SSH signature does not validate."
134635
+ };
134636
+ if (sshBadMatch[1])
134637
+ result.signerIdentity = sshBadMatch[1];
134638
+ return result;
134639
+ }
134640
+ const gpgGoodMatch = /gpg: Good signature from "([^"]+)"/.exec(stderr);
134641
+ if (gpgGoodMatch) {
134642
+ const result = {
134643
+ ...base,
134644
+ verified: true,
134645
+ signatureType: "gpg",
134646
+ signerIdentity: gpgGoodMatch[1]
134647
+ };
134648
+ const keyMatch = /using \S+ key ([0-9A-Fa-f]{8,})/.exec(stderr);
134649
+ if (keyMatch)
134650
+ result.signerKey = keyMatch[1];
134651
+ return result;
134652
+ }
134653
+ const x509GoodMatch = /gpgsm: Good signature from "([^"]+)"/.exec(stderr);
134654
+ if (x509GoodMatch) {
134655
+ return {
134656
+ ...base,
134657
+ verified: true,
134658
+ signatureType: "x509",
134659
+ signerIdentity: x509GoodMatch[1]
134660
+ };
134661
+ }
134662
+ const sshGoodMatch = /Good "git" signature for (.+?) with \S+ key (SHA256:\S+)/.exec(stderr);
134663
+ if (sshGoodMatch) {
134664
+ return {
134665
+ ...base,
134666
+ verified: true,
134667
+ signatureType: "ssh",
134668
+ signerIdentity: sshGoodMatch[1].trim(),
134669
+ signerKey: sshGoodMatch[2]
134670
+ };
134671
+ }
134672
+ if (exitCode === 0) {
134673
+ return { ...base, verified: true };
134674
+ }
134675
+ return {
134676
+ ...base,
134677
+ verified: false,
134678
+ warning: "Verification failed but the output format was not recognized. See `rawOutput` for details."
134679
+ };
134680
+ }
134836
134681
  // src/services/git/providers/cli/operations/stash/stash.ts
134837
134682
  async function executeStash(options, context, execGit) {
134838
134683
  try {
@@ -134840,6 +134685,9 @@ async function executeStash(options, context, execGit) {
134840
134685
  switch (options.mode) {
134841
134686
  case "list": {
134842
134687
  args.push("--format=%gd\t%ct\t%gs");
134688
+ if (typeof options.limit === "number" && options.limit > 0) {
134689
+ args.push(`-n${options.limit}`);
134690
+ }
134843
134691
  const cmd = buildGitCommand({ command: "stash", args });
134844
134692
  const result = await execGit(cmd, context.workingDirectory, context.requestContext);
134845
134693
  const stashes = result.stdout.split(`
@@ -135556,7 +135404,6 @@ var import_tsyringe4 = __toESM(require_cjs2(), 1);
135556
135404
 
135557
135405
  // src/storage/providers/fileSystem/fileSystemProvider.ts
135558
135406
  init_errors3();
135559
- init_utils();
135560
135407
  import { existsSync as existsSync2, mkdirSync } from "fs";
135561
135408
  import { readFile, readdir, rm, writeFile } from "fs/promises";
135562
135409
  import path2 from "path";
@@ -135791,7 +135638,6 @@ class FileSystemProvider {
135791
135638
  }
135792
135639
 
135793
135640
  // src/storage/providers/inMemory/inMemoryProvider.ts
135794
- init_utils();
135795
135641
  var DEFAULT_LIST_LIMIT2 = 1000;
135796
135642
 
135797
135643
  class InMemoryProvider {
@@ -135904,7 +135750,6 @@ class InMemoryProvider {
135904
135750
  // src/storage/providers/supabase/supabaseProvider.ts
135905
135751
  var import_tsyringe3 = __toESM(require_cjs2(), 1);
135906
135752
  init_tokens();
135907
- init_utils();
135908
135753
  var TABLE_NAME = "kv_store";
135909
135754
  var DEFAULT_LIST_LIMIT3 = 1000;
135910
135755
 
@@ -136074,7 +135919,6 @@ SupabaseProvider = __legacyDecorateClassTS([
136074
135919
 
136075
135920
  // src/storage/providers/cloudflare/r2Provider.ts
136076
135921
  init_errors3();
136077
- init_utils();
136078
135922
  var R2_ENVELOPE_VERSION = 1;
136079
135923
  var DEFAULT_LIST_LIMIT4 = 1000;
136080
135924
 
@@ -136270,7 +136114,6 @@ class R2Provider {
136270
136114
 
136271
136115
  // src/storage/providers/cloudflare/kvProvider.ts
136272
136116
  init_errors3();
136273
- init_utils();
136274
136117
  var DEFAULT_LIST_LIMIT5 = 1000;
136275
136118
 
136276
136119
  class KvProvider {
@@ -136437,7 +136280,6 @@ class KvProvider {
136437
136280
  }
136438
136281
 
136439
136282
  // src/storage/core/storageFactory.ts
136440
- init_utils();
136441
136283
  var isServerless3 = typeof process === "undefined" || process.env.IS_SERVERLESS === "true";
136442
136284
  function createStorageProvider(config3, deps = {}) {
136443
136285
  const context = requestContextService.createRequestContext({
@@ -136486,8 +136328,6 @@ function createStorageProvider(config3, deps = {}) {
136486
136328
 
136487
136329
  // src/container/registrations/core.ts
136488
136330
  init_errors3();
136489
- init_utils();
136490
- init_rateLimiter();
136491
136331
  var registerCoreServices = () => {
136492
136332
  const config3 = parseConfig();
136493
136333
  import_tsyringe5.container.register(AppConfig, { useValue: config3 });
@@ -136529,12 +136369,9 @@ var import_tsyringe6 = __toESM(require_cjs2(), 1);
136529
136369
 
136530
136370
  // src/mcp-server/resources/definitions/git-working-directory.resource.ts
136531
136371
  init_zod();
136532
- init_utils();
136533
136372
 
136534
136373
  // src/mcp-server/transports/auth/lib/authUtils.ts
136535
136374
  init_errors3();
136536
- init_utils();
136537
- init_authContext();
136538
136375
  function withRequiredScopes(requiredScopes) {
136539
136376
  const operationName = "withRequiredScopesCheck";
136540
136377
  const initialContext = requestContextService.createRequestContext({
@@ -145154,7 +144991,6 @@ var EMPTY_COMPLETION_RESULT = {
145154
144991
 
145155
144992
  // src/mcp-server/resources/utils/resourceHandlerFactory.ts
145156
144993
  init_errors3();
145157
- init_utils();
145158
144994
  function defaultResponseFormatter(result, meta3) {
145159
144995
  return [
145160
144996
  {
@@ -145240,7 +145076,6 @@ async function registerResource(server, def) {
145240
145076
  }
145241
145077
 
145242
145078
  // src/mcp-server/resources/resource-registration.ts
145243
- init_utils();
145244
145079
  class ResourceRegistry {
145245
145080
  resourceDefs;
145246
145081
  constructor(resourceDefs) {
@@ -145331,11 +145166,10 @@ Begin by calling \`git_wrapup_instructions\` and creating your task list.`
145331
145166
  var allPromptDefinitions = [gitWrapupPrompt];
145332
145167
 
145333
145168
  // src/mcp-server/prompts/prompt-registration.ts
145334
- init_utils();
145335
145169
  class PromptRegistry {
145336
145170
  logger;
145337
- constructor(logger3) {
145338
- this.logger = logger3;
145171
+ constructor(logger2) {
145172
+ this.logger = logger2;
145339
145173
  }
145340
145174
  registerAll(server) {
145341
145175
  const context = requestContextService.createRequestContext({
@@ -145368,7 +145202,6 @@ PromptRegistry = __legacyDecorateClassTS([
145368
145202
 
145369
145203
  // src/mcp-server/tools/tool-registration.ts
145370
145204
  var import_tsyringe9 = __toESM(require_cjs2(), 1);
145371
- init_utils();
145372
145205
 
145373
145206
  // src/mcp-server/tools/definitions/git-changelog-analyze.tool.ts
145374
145207
  init_zod();
@@ -145530,12 +145363,10 @@ var defaultJsonFormatter = createJsonFormatter();
145530
145363
 
145531
145364
  // src/mcp-server/tools/utils/toolHandlerFactory.ts
145532
145365
  init_tokens();
145533
- init_utils();
145534
145366
  var import_tsyringe8 = __toESM(require_cjs2(), 1);
145535
145367
 
145536
145368
  // src/mcp-server/tools/utils/git-validators.ts
145537
145369
  init_errors3();
145538
- init_utils();
145539
145370
  import path3 from "node:path";
145540
145371
  async function resolveWorkingDirectory(pathInput, appContext, storage) {
145541
145372
  let workingDir;
@@ -145808,6 +145639,7 @@ var InputSchema = exports_external.object({
145808
145639
  path: PathSchema,
145809
145640
  reviewTypes: exports_external.array(ReviewTypeSchema).min(1).describe("Types of changelog review to perform. At least one required. Options: security, features, storyline, gaps, breaking_changes, quality."),
145810
145641
  maxCommits: exports_external.number().int().min(1).max(1000).default(200).describe("Maximum recent commits to fetch for cross-referencing (1-1000)."),
145642
+ maxTags: exports_external.number().int().min(1).max(1000).default(100).describe("Maximum recent tags to fetch for release context (1-1000). Applied at the git command so large tag catalogs do not bloat the response."),
145811
145643
  sinceTag: exports_external.string().optional().describe('Only include git history since this tag (e.g., "v1.2.0"). Narrows the analysis window.'),
145812
145644
  branch: CommitRefSchema.optional().describe("Branch to analyze (defaults to current branch).")
145813
145645
  });
@@ -145860,7 +145692,7 @@ async function gitChangelogAnalyzeLogic(input, { provider, targetPath, appContex
145860
145692
  }
145861
145693
  const [logResult, tagResult, statusResult] = await Promise.all([
145862
145694
  provider.log(logOptions, operationContext),
145863
- provider.tag({ mode: "list" }, operationContext),
145695
+ provider.tag({ mode: "list", limit: input.maxTags }, operationContext),
145864
145696
  provider.status({ includeUntracked: false }, operationContext)
145865
145697
  ]);
145866
145698
  const reviewInstructions = buildReviewInstructions(input.reviewTypes);
@@ -145873,8 +145705,8 @@ async function gitChangelogAnalyzeLogic(input, { provider, targetPath, appContex
145873
145705
  commits: logResult.commits.map((c) => ({
145874
145706
  hash: c.shortHash,
145875
145707
  subject: c.subject,
145876
- author: c.author,
145877
- timestamp: c.timestamp,
145708
+ author: c.author ?? "",
145709
+ timestamp: c.timestamp ?? 0,
145878
145710
  ...c.refs && c.refs.length > 0 && { refs: c.refs }
145879
145711
  })),
145880
145712
  tags: (tagResult.tags ?? []).map((t2) => ({
@@ -146303,162 +146135,246 @@ var gitReflogTool = {
146303
146135
 
146304
146136
  // src/mcp-server/tools/definitions/git-set-working-dir.tool.ts
146305
146137
  init_zod();
146138
+ init_errors3();
146139
+
146140
+ // src/mcp-server/tools/utils/repo-snapshot.ts
146141
+ init_zod();
146142
+ var RepoSnapshotStatusSchema = exports_external.object({
146143
+ branch: exports_external.string().nullable().describe("Current branch (null on detached HEAD)."),
146144
+ isClean: exports_external.boolean().describe("True when the working tree has no changes."),
146145
+ staged: exports_external.array(exports_external.string()).describe("Paths staged for the next commit."),
146146
+ unstaged: exports_external.array(exports_external.string()).describe("Paths with unstaged modifications."),
146147
+ untracked: exports_external.array(exports_external.string()).describe("Untracked paths."),
146148
+ conflicts: exports_external.array(exports_external.string()).describe("Paths with merge conflicts."),
146149
+ upstream: exports_external.string().optional().describe("Upstream ref being tracked by the current branch."),
146150
+ ahead: exports_external.number().int().optional().describe("Commits ahead of upstream (if tracking)."),
146151
+ behind: exports_external.number().int().optional().describe("Commits behind upstream (if tracking).")
146152
+ });
146153
+ var RepoSnapshotCommitSchema = exports_external.object({
146154
+ hash: exports_external.string().describe("Short commit hash."),
146155
+ author: exports_external.string().describe("Author name."),
146156
+ date: exports_external.string().describe("Author date (ISO 8601)."),
146157
+ subject: exports_external.string().describe("First line of the commit message.")
146158
+ });
146159
+ var RepoSnapshotTagSchema = exports_external.object({
146160
+ name: exports_external.string().describe("Tag name."),
146161
+ date: exports_external.string().optional().describe("Creator date (ISO 8601); absent for lightweight tags with no metadata."),
146162
+ tagger: exports_external.string().optional().describe("Tagger identity (annotated tags only)."),
146163
+ annotationSubject: exports_external.string().optional().describe("First line of the tag annotation (annotated tags only)."),
146164
+ annotationBody: exports_external.string().optional().describe("Remaining annotation body after the subject (annotated tags only).")
146165
+ });
146166
+ var RepoSnapshotRemoteSchema = exports_external.object({
146167
+ name: exports_external.string().describe("Remote name."),
146168
+ fetchUrl: exports_external.string().describe("Fetch URL."),
146169
+ pushUrl: exports_external.string().describe("Push URL (may differ from fetch URL).")
146170
+ });
146171
+ var NOT_A_REPO_HINT = "Repository snapshot unavailable — the path may not be a git repository. Initialize it via git_init or point at an existing repo.";
146172
+ function reasonMessage(reason) {
146173
+ if (reason instanceof Error)
146174
+ return reason.message;
146175
+ if (typeof reason === "string")
146176
+ return reason;
146177
+ if (reason === null || reason === undefined)
146178
+ return "unknown error";
146179
+ try {
146180
+ return JSON.stringify(reason);
146181
+ } catch {
146182
+ return "unknown error";
146183
+ }
146184
+ }
146185
+ function isNotARepoError(reason) {
146186
+ if (!reason)
146187
+ return false;
146188
+ return /not a git repository/i.test(reasonMessage(reason));
146189
+ }
146190
+ function isEmptyRepoError(reason) {
146191
+ if (!reason)
146192
+ return false;
146193
+ return /does not have any commits yet/i.test(reasonMessage(reason));
146194
+ }
146195
+ function toIsoDate(unixSeconds) {
146196
+ if (typeof unixSeconds !== "number" || !Number.isFinite(unixSeconds)) {
146197
+ return;
146198
+ }
146199
+ return new Date(unixSeconds * 1000).toISOString();
146200
+ }
146201
+ async function gatherRepoSnapshot(deps, options = {}) {
146202
+ const { provider, appContext, workingDirectory } = deps;
146203
+ const commitLimit = options.commitLimit ?? 2;
146204
+ const tagLimit = options.tagLimit ?? 2;
146205
+ const tenantId = appContext.tenantId || "default-tenant";
146206
+ const context = {
146207
+ workingDirectory,
146208
+ requestContext: appContext,
146209
+ tenantId
146210
+ };
146211
+ const fetchStatus = provider.status({ includeUntracked: true }, context);
146212
+ const fetchLog = provider.log({ maxCount: commitLimit }, context);
146213
+ const fetchTags = provider.tag({ mode: "list", limit: tagLimit }, context);
146214
+ const fetchRemotes = options.includeRemotes ? provider.remote({ mode: "list" }, context) : Promise.resolve(undefined);
146215
+ const [statusRes, logRes, tagsRes, remotesRes] = await Promise.allSettled([
146216
+ fetchStatus,
146217
+ fetchLog,
146218
+ fetchTags,
146219
+ fetchRemotes
146220
+ ]);
146221
+ const settled = [statusRes, logRes, tagsRes, remotesRes];
146222
+ const rejections = settled.filter((s2) => s2.status === "rejected");
146223
+ if (rejections.length > 0 && rejections.every((r2) => isNotARepoError(r2.reason))) {
146224
+ logger.debug("Repository snapshot skipped: path is not a git repository", {
146225
+ ...appContext,
146226
+ workingDirectory
146227
+ });
146228
+ return { warnings: [NOT_A_REPO_HINT] };
146229
+ }
146230
+ const warnings = [];
146231
+ const status = statusRes.status === "fulfilled" ? {
146232
+ branch: statusRes.value.currentBranch,
146233
+ isClean: statusRes.value.isClean,
146234
+ staged: [
146235
+ ...statusRes.value.stagedChanges.added ?? [],
146236
+ ...statusRes.value.stagedChanges.modified ?? [],
146237
+ ...statusRes.value.stagedChanges.deleted ?? [],
146238
+ ...statusRes.value.stagedChanges.renamed ?? [],
146239
+ ...statusRes.value.stagedChanges.copied ?? []
146240
+ ],
146241
+ unstaged: [
146242
+ ...statusRes.value.unstagedChanges.added ?? [],
146243
+ ...statusRes.value.unstagedChanges.modified ?? [],
146244
+ ...statusRes.value.unstagedChanges.deleted ?? []
146245
+ ],
146246
+ untracked: statusRes.value.untrackedFiles,
146247
+ conflicts: statusRes.value.conflictedFiles,
146248
+ ...statusRes.value.upstream ? { upstream: statusRes.value.upstream } : {},
146249
+ ...typeof statusRes.value.ahead === "number" ? { ahead: statusRes.value.ahead } : {},
146250
+ ...typeof statusRes.value.behind === "number" ? { behind: statusRes.value.behind } : {}
146251
+ } : {
146252
+ branch: null,
146253
+ isClean: false,
146254
+ staged: [],
146255
+ unstaged: [],
146256
+ untracked: [],
146257
+ conflicts: []
146258
+ };
146259
+ if (statusRes.status === "rejected") {
146260
+ warnings.push(`status unavailable: ${reasonMessage(statusRes.reason)}`);
146261
+ }
146262
+ const recentCommits = logRes.status === "fulfilled" ? logRes.value.commits.map((commit) => ({
146263
+ hash: commit.shortHash,
146264
+ author: commit.author ?? "",
146265
+ date: typeof commit.timestamp === "number" ? new Date(commit.timestamp * 1000).toISOString() : "",
146266
+ subject: commit.subject
146267
+ })) : [];
146268
+ if (logRes.status === "rejected" && !isEmptyRepoError(logRes.reason)) {
146269
+ warnings.push(`recent commits unavailable: ${reasonMessage(logRes.reason)}`);
146270
+ }
146271
+ const recentTags = tagsRes.status === "fulfilled" && tagsRes.value.mode === "list" ? (tagsRes.value.tags ?? []).map((tag) => {
146272
+ const entry = { name: tag.name };
146273
+ const date6 = toIsoDate(tag.timestamp);
146274
+ if (date6)
146275
+ entry.date = date6;
146276
+ if (tag.tagger)
146277
+ entry.tagger = tag.tagger;
146278
+ if (tag.message)
146279
+ entry.annotationSubject = tag.message;
146280
+ if (tag.annotationBody)
146281
+ entry.annotationBody = tag.annotationBody;
146282
+ return entry;
146283
+ }) : [];
146284
+ if (tagsRes.status === "rejected") {
146285
+ warnings.push(`recent tags unavailable: ${reasonMessage(tagsRes.reason)}`);
146286
+ }
146287
+ let remotes;
146288
+ if (options.includeRemotes) {
146289
+ if (remotesRes.status === "fulfilled" && remotesRes.value && remotesRes.value.mode === "list") {
146290
+ remotes = (remotesRes.value.remotes ?? []).map((r2) => ({
146291
+ name: r2.name,
146292
+ fetchUrl: r2.fetchUrl,
146293
+ pushUrl: r2.pushUrl
146294
+ }));
146295
+ } else if (remotesRes.status === "rejected") {
146296
+ warnings.push(`remotes unavailable: ${reasonMessage(remotesRes.reason)}`);
146297
+ remotes = [];
146298
+ } else {
146299
+ remotes = [];
146300
+ }
146301
+ }
146302
+ const snapshot = {
146303
+ status,
146304
+ recentCommits,
146305
+ recentTags,
146306
+ ...remotes !== undefined ? { remotes } : {}
146307
+ };
146308
+ return { snapshot, warnings };
146309
+ }
146310
+
146311
+ // src/mcp-server/tools/definitions/git-set-working-dir.tool.ts
146306
146312
  var TOOL_NAME8 = "git_set_working_dir";
146307
146313
  var TOOL_TITLE8 = "Git Set Working Directory";
146308
- var TOOL_DESCRIPTION8 = "Set the session working directory for all git operations. This allows subsequent git commands to omit the path parameter and use this directory as the default.";
146314
+ var TOOL_DESCRIPTION8 = "Set the session working directory for all git operations so subsequent calls can omit the path parameter. Always returns a repository snapshot (status, recent commits, recent tags, remotes) to orient the caller.";
146309
146315
  var InputSchema8 = exports_external.object({
146310
146316
  path: exports_external.string().min(1).describe("Absolute path to the git repository to use as the working directory."),
146311
146317
  validateGitRepo: exports_external.boolean().default(true).describe("Validate that the path is a Git repository."),
146312
- initializeIfNotPresent: exports_external.boolean().default(false).describe("If not a Git repository, initialize it with 'git init'."),
146313
- includeMetadata: exports_external.boolean().default(false).describe("Include repository metadata (status, branches, remotes, recent commits) in the response. Set to true for immediate repository context understanding. Defaults to false to minimize response size.")
146318
+ initializeIfNotPresent: exports_external.boolean().default(false).describe("If not a Git repository, initialize it with 'git init'.")
146314
146319
  });
146315
146320
  var OutputSchema9 = exports_external.object({
146316
146321
  success: exports_external.boolean().describe("Indicates if the operation was successful."),
146317
146322
  path: exports_external.string().describe("The working directory that was set."),
146318
146323
  message: exports_external.string().describe("Confirmation message."),
146319
- repositoryContext: exports_external.object({
146320
- status: exports_external.object({
146321
- branch: exports_external.string().nullable().describe("Current branch name (null if detached HEAD)."),
146322
- isClean: exports_external.boolean().describe("True if working directory is clean."),
146323
- stagedCount: exports_external.number().int().describe("Number of staged files ready for commit."),
146324
- unstagedCount: exports_external.number().int().describe("Number of files with unstaged changes."),
146325
- untrackedCount: exports_external.number().int().describe("Number of untracked files."),
146326
- conflictsCount: exports_external.number().int().describe("Number of files with merge conflicts.")
146327
- }).describe("Current repository working tree status."),
146328
- branches: exports_external.object({
146329
- current: exports_external.string().nullable().describe("Current branch name (null if detached HEAD)."),
146330
- totalLocal: exports_external.number().int().describe("Total number of local branches."),
146331
- totalRemote: exports_external.number().int().describe("Total number of remote-tracking branches."),
146332
- upstream: exports_external.string().optional().describe("Upstream branch name if current branch is tracking one."),
146333
- ahead: exports_external.number().int().optional().describe("Commits ahead of upstream (if tracking)."),
146334
- behind: exports_external.number().int().optional().describe("Commits behind upstream (if tracking).")
146335
- }).describe("Branch information and tracking status."),
146336
- remotes: exports_external.array(exports_external.object({
146337
- name: exports_external.string().describe("Remote name."),
146338
- fetchUrl: exports_external.string().describe("Fetch URL."),
146339
- pushUrl: exports_external.string().describe("Push URL (may differ from fetch).")
146340
- })).describe("Configured remote repositories."),
146341
- recentCommits: exports_external.array(exports_external.object({
146342
- hash: exports_external.string().describe("Commit hash (short form)."),
146343
- author: exports_external.string().describe("Commit author name."),
146344
- date: exports_external.string().describe("Commit date (ISO 8601 format)."),
146345
- message: exports_external.string().describe("Commit message (first line).")
146346
- })).describe("Recent commits (up to 5 most recent).")
146347
- }).optional().describe("Rich repository metadata including status, branches, remotes, and recent history. Only included when includeMetadata parameter is true.")
146348
- });
146349
- async function gatherRepositoryContext(targetPath, dependencies) {
146324
+ repository: exports_external.object({
146325
+ status: RepoSnapshotStatusSchema,
146326
+ recentCommits: exports_external.array(RepoSnapshotCommitSchema).describe("Up to 2 most recent commits on the current branch."),
146327
+ recentTags: exports_external.array(RepoSnapshotTagSchema).describe("Up to 2 most recent tags by creator date."),
146328
+ remotes: exports_external.array(RepoSnapshotRemoteSchema).describe("Configured remote repositories.")
146329
+ }).optional().describe("Best-effort repository snapshot. Omitted when the path is not a git repository (see enrichmentWarnings)."),
146330
+ enrichmentWarnings: exports_external.array(exports_external.string()).optional().describe("Actionable notes when snapshot gathering was skipped or partially failed.")
146331
+ });
146332
+ async function ensureRepositoryReady(input, dependencies, tenantId) {
146333
+ if (!input.validateGitRepo)
146334
+ return;
146350
146335
  const { provider, appContext } = dependencies;
146351
- const tenantId = appContext.tenantId || "default-tenant";
146352
- const context = {
146353
- workingDirectory: targetPath,
146336
+ const opContext = {
146337
+ workingDirectory: input.path,
146354
146338
  requestContext: appContext,
146355
146339
  tenantId
146356
146340
  };
146357
146341
  try {
146358
- const [
146359
- statusResult,
146360
- localBranchesResult,
146361
- remoteBranchesResult,
146362
- remotesResult,
146363
- logResult
146364
- ] = await Promise.allSettled([
146365
- provider.status({ includeUntracked: true }, context),
146366
- provider.branch({ mode: "list" }, context),
146367
- provider.branch({ mode: "list", remote: true }, context),
146368
- provider.remote({ mode: "list" }, context),
146369
- provider.log({ maxCount: 5 }, context)
146370
- ]);
146371
- const status = statusResult.status === "fulfilled" ? {
146372
- branch: statusResult.value.currentBranch,
146373
- isClean: statusResult.value.isClean,
146374
- stagedCount: (statusResult.value.stagedChanges.added?.length || 0) + (statusResult.value.stagedChanges.modified?.length || 0) + (statusResult.value.stagedChanges.deleted?.length || 0) + (statusResult.value.stagedChanges.renamed?.length || 0) + (statusResult.value.stagedChanges.copied?.length || 0),
146375
- unstagedCount: (statusResult.value.unstagedChanges.added?.length || 0) + (statusResult.value.unstagedChanges.modified?.length || 0) + (statusResult.value.unstagedChanges.deleted?.length || 0),
146376
- untrackedCount: statusResult.value.untrackedFiles.length,
146377
- conflictsCount: statusResult.value.conflictedFiles.length
146378
- } : {
146379
- branch: null,
146380
- isClean: false,
146381
- stagedCount: 0,
146382
- unstagedCount: 0,
146383
- untrackedCount: 0,
146384
- conflictsCount: 0
146385
- };
146386
- const localBranches = localBranchesResult.status === "fulfilled" && localBranchesResult.value.mode === "list" ? localBranchesResult.value.branches : [];
146387
- const remoteBranchCount = remoteBranchesResult.status === "fulfilled" && remoteBranchesResult.value.mode === "list" ? remoteBranchesResult.value.branches.length : 0;
146388
- const currentBranch = localBranches.find((b) => b.current);
146389
- const branches = {
146390
- current: currentBranch?.name || null,
146391
- totalLocal: localBranches.length,
146392
- totalRemote: remoteBranchCount,
146393
- upstream: currentBranch?.upstream,
146394
- ahead: currentBranch?.ahead,
146395
- behind: currentBranch?.behind
146396
- };
146397
- const remotes = remotesResult.status === "fulfilled" && remotesResult.value.mode === "list" ? remotesResult.value.remotes || [] : [];
146398
- const recentCommits = logResult.status === "fulfilled" ? logResult.value.commits.map((commit) => ({
146399
- hash: commit.shortHash,
146400
- author: commit.author,
146401
- date: new Date(commit.timestamp * 1000).toISOString(),
146402
- message: commit.subject
146403
- })) : [];
146404
- return {
146405
- status,
146406
- branches,
146407
- remotes,
146408
- recentCommits
146409
- };
146410
- } catch (error48) {
146411
- const { logger: logger3 } = await Promise.resolve().then(() => (init_utils(), exports_utils));
146412
- logger3.debug("Failed to gather repository context", {
146413
- ...appContext,
146414
- error: error48 instanceof Error ? error48.message : String(error48),
146415
- targetPath
146416
- });
146342
+ await provider.validateRepository(input.path, opContext);
146417
146343
  return;
146344
+ } catch (error48) {
146345
+ if (input.initializeIfNotPresent) {
146346
+ await provider.init({ path: input.path, initialBranch: "main", bare: false }, opContext);
146347
+ return;
146348
+ }
146349
+ const original = error48 instanceof Error ? error48.message : String(error48);
146350
+ throw new McpError(-32007 /* ValidationError */, `Path is not a git repository: ${input.path}. Pass initializeIfNotPresent: true to run 'git init' here, or point at an existing repository. Underlying error: ${original}`, { path: input.path });
146418
146351
  }
146419
146352
  }
146420
146353
  async function gitSetWorkingDirLogic(input, dependencies) {
146421
146354
  const { provider, storage, appContext } = dependencies;
146422
146355
  const tenantId = appContext.tenantId || "default-tenant";
146423
- if (input.validateGitRepo) {
146424
- try {
146425
- await provider.validateRepository(input.path, {
146426
- workingDirectory: input.path,
146427
- requestContext: appContext,
146428
- tenantId
146429
- });
146430
- } catch (error48) {
146431
- if (input.initializeIfNotPresent) {
146432
- await provider.init({
146433
- path: input.path,
146434
- initialBranch: "main",
146435
- bare: false
146436
- }, {
146437
- workingDirectory: input.path,
146438
- requestContext: appContext,
146439
- tenantId
146440
- });
146441
- } else {
146442
- throw error48;
146443
- }
146444
- }
146445
- }
146356
+ await ensureRepositoryReady(input, dependencies, tenantId);
146446
146357
  const storageKey = `session:workingDir:${tenantId}`;
146447
146358
  await storage.set(storageKey, input.path, appContext);
146448
- const repositoryContext = input.includeMetadata ? await gatherRepositoryContext(input.path, dependencies) : undefined;
146359
+ const { snapshot, warnings } = await gatherRepoSnapshot({ provider, appContext, workingDirectory: input.path }, { commitLimit: 2, tagLimit: 2, includeRemotes: true });
146449
146360
  return {
146450
146361
  success: true,
146451
146362
  path: input.path,
146452
146363
  message: `Working directory set to: ${input.path}`,
146453
- repositoryContext
146364
+ ...snapshot ? {
146365
+ repository: {
146366
+ status: snapshot.status,
146367
+ recentCommits: snapshot.recentCommits,
146368
+ recentTags: snapshot.recentTags,
146369
+ remotes: snapshot.remotes ?? []
146370
+ }
146371
+ } : {},
146372
+ ...warnings.length > 0 ? { enrichmentWarnings: warnings } : {}
146454
146373
  };
146455
146374
  }
146456
146375
  function filterGitSetWorkingDirOutput(result, level) {
146457
146376
  if (level === "minimal") {
146458
- return {
146459
- success: result.success,
146460
- path: result.path
146461
- };
146377
+ return { success: result.success, path: result.path };
146462
146378
  }
146463
146379
  return result;
146464
146380
  }
@@ -146488,6 +146404,9 @@ var InputSchema9 = exports_external.object({
146488
146404
  var OutputSchema10 = exports_external.object({
146489
146405
  success: exports_external.boolean().describe("Indicates if the operation was successful."),
146490
146406
  currentBranch: exports_external.string().nullable().describe("Current branch name."),
146407
+ upstream: exports_external.string().optional().describe("Upstream ref the current branch is tracking (if any)."),
146408
+ ahead: exports_external.number().int().optional().describe("Commits ahead of upstream (if tracking)."),
146409
+ behind: exports_external.number().int().optional().describe("Commits behind upstream (if tracking)."),
146491
146410
  isClean: exports_external.boolean().describe("True if working directory is clean (no staged, unstaged, or untracked changes). When includeUntracked is false, untracked files are excluded from this check."),
146492
146411
  stagedChanges: exports_external.object({
146493
146412
  added: exports_external.array(exports_external.string()).optional().describe("Files added to the index (staged)."),
@@ -146515,6 +146434,9 @@ async function gitStatusLogic(input, { provider, targetPath, appContext }) {
146515
146434
  return {
146516
146435
  success: true,
146517
146436
  currentBranch: result.currentBranch,
146437
+ ...result.upstream !== undefined && { upstream: result.upstream },
146438
+ ...result.ahead !== undefined && { ahead: result.ahead },
146439
+ ...result.behind !== undefined && { behind: result.behind },
146518
146440
  isClean: result.isClean,
146519
146441
  stagedChanges: result.stagedChanges,
146520
146442
  unstagedChanges: result.unstagedChanges,
@@ -146548,26 +146470,24 @@ var gitStatusTool = {
146548
146470
 
146549
146471
  // src/mcp-server/tools/definitions/git-wrapup-instructions.tool.ts
146550
146472
  init_zod();
146551
- init_utils();
146552
146473
  import { readFileSync } from "fs";
146553
146474
  import path4 from "path";
146554
146475
  init_config();
146555
146476
  var TOOL_NAME10 = "git_wrapup_instructions";
146556
146477
  var TOOL_TITLE10 = "Git Wrap-up Instructions";
146557
- var TOOL_DESCRIPTION10 = "Returns a Git wrap-up protocol: an acceptance-criteria checklist the agent must satisfy before the session is considered shipped. Uses the operator's custom instructions if configured, otherwise emits a generic goals-strict/mechanism-generic default. Includes current repository status to guide next actions.";
146478
+ var TOOL_DESCRIPTION10 = "Returns a Git wrap-up protocol: an acceptance-criteria checklist the agent must satisfy before the session is considered shipped. Uses the operator's custom instructions if configured, otherwise emits a generic goals-strict/mechanism-generic default. Enriches the response with a repository snapshot (status, recent commits, recent tags) so the agent has immediate orientation for the commit and release steps.";
146558
146479
  var InputSchema10 = exports_external.object({
146559
146480
  acknowledgement: exports_external.enum(["Y", "y", "Yes", "yes"]).describe("Acknowledgement to initiate the wrap-up workflow."),
146560
146481
  createTag: exports_external.boolean().optional().describe("Controls whether the tag criterion appears in the emitted protocol. Omit or set `true` to include the tag step. Set `false` to omit it entirely — e.g., when tagging is deferred to a separate release step.")
146561
146482
  });
146562
146483
  var OutputSchema11 = exports_external.object({
146563
- instructions: exports_external.string().describe("The set of instructions for the wrap-up workflow."),
146564
- gitStatus: exports_external.object({
146565
- branch: exports_external.string().describe("Current branch name."),
146566
- staged: exports_external.array(exports_external.string()).describe("Files staged for commit."),
146567
- unstaged: exports_external.array(exports_external.string()).describe("Files with unstaged changes."),
146568
- untracked: exports_external.array(exports_external.string()).describe("Untracked files.")
146569
- }).optional().describe("The current structured git status."),
146570
- gitStatusError: exports_external.string().optional().describe("Any error message if getting git status failed.")
146484
+ instructions: exports_external.string().describe("The wrap-up protocol to satisfy before the session ships."),
146485
+ repository: exports_external.object({
146486
+ status: RepoSnapshotStatusSchema,
146487
+ recentCommits: exports_external.array(RepoSnapshotCommitSchema).describe("Up to 2 most recent commits on the current branch."),
146488
+ recentTags: exports_external.array(RepoSnapshotTagSchema).describe("Up to 2 most recent tags by creator date.")
146489
+ }).optional().describe("Best-effort repository snapshot. Omitted when no working directory is set or when the path is not a git repository."),
146490
+ enrichmentWarnings: exports_external.array(exports_external.string()).optional().describe("Actionable notes when snapshot gathering was skipped or partially failed.")
146571
146491
  });
146572
146492
  function buildDefaultInstructions(input) {
146573
146493
  const tagCriterion = input.createTag === false ? "" : "\n- [ ] Annotated tag at the project's convention (typically `v<version>`) with a concise message summarizing the real changes — no filler. Flag if a tag already exists at this commit.";
@@ -146636,49 +146556,32 @@ var customInstructions = loadCustomInstructions(config2?.git?.wrapupInstructions
146636
146556
  async function gitWrapupInstructionsLogic(input, { provider, storage, appContext }) {
146637
146557
  const tenantId = appContext.tenantId || "default-tenant";
146638
146558
  const finalInstructions = customInstructions ?? buildDefaultInstructions(input);
146639
- let gitStatus;
146640
- let gitStatusError;
146641
- try {
146642
- const storageKey = `session:workingDir:${tenantId}`;
146643
- const workingDir = await storage.get(storageKey, appContext);
146644
- if (workingDir) {
146645
- const result = await provider.status({ includeUntracked: true }, {
146646
- workingDirectory: workingDir,
146647
- requestContext: appContext,
146648
- tenantId
146649
- });
146650
- gitStatus = {
146651
- branch: result.currentBranch || "detached HEAD",
146652
- staged: [
146653
- ...result.stagedChanges.added || [],
146654
- ...result.stagedChanges.modified || [],
146655
- ...result.stagedChanges.deleted || []
146656
- ],
146657
- unstaged: [
146658
- ...result.unstagedChanges.modified || [],
146659
- ...result.unstagedChanges.deleted || []
146660
- ],
146661
- untracked: result.untrackedFiles
146662
- };
146663
- } else {
146664
- gitStatusError = "No working directory set for session, git status skipped.";
146665
- }
146666
- } catch (error48) {
146667
- const errorMessage = error48 instanceof Error ? error48.message : "Unknown error";
146668
- gitStatusError = `Failed to get git status: ${errorMessage}`;
146669
- logger.warning(gitStatusError, { ...appContext, error: error48 });
146559
+ const storageKey = `session:workingDir:${tenantId}`;
146560
+ const workingDir = await storage.get(storageKey, appContext);
146561
+ if (!workingDir) {
146562
+ return {
146563
+ instructions: finalInstructions,
146564
+ enrichmentWarnings: [
146565
+ "No session working directory set. Call git_set_working_dir first to include a repository snapshot (status, recent commits, recent tags) in this response."
146566
+ ]
146567
+ };
146670
146568
  }
146569
+ const { snapshot, warnings } = await gatherRepoSnapshot({ provider, appContext, workingDirectory: workingDir }, { commitLimit: 2, tagLimit: 2 });
146671
146570
  return {
146672
146571
  instructions: finalInstructions,
146673
- gitStatus,
146674
- gitStatusError
146572
+ ...snapshot ? {
146573
+ repository: {
146574
+ status: snapshot.status,
146575
+ recentCommits: snapshot.recentCommits,
146576
+ recentTags: snapshot.recentTags
146577
+ }
146578
+ } : {},
146579
+ ...warnings.length > 0 ? { enrichmentWarnings: warnings } : {}
146675
146580
  };
146676
146581
  }
146677
146582
  function filterGitWrapupInstructionsOutput(result, level) {
146678
146583
  if (level === "minimal") {
146679
- return {
146680
- instructions: result.instructions
146681
- };
146584
+ return { instructions: result.instructions };
146682
146585
  }
146683
146586
  return result;
146684
146587
  }
@@ -147110,7 +147013,8 @@ var CommitSchema = exports_external.object({
147110
147013
  var OutputSchema15 = exports_external.object({
147111
147014
  success: exports_external.boolean().describe("Indicates if the operation was successful."),
147112
147015
  commits: exports_external.array(CommitSchema).describe("Array of commit objects."),
147113
- totalCount: exports_external.number().int().describe("Total number of commits returned (may be limited by maxCount).")
147016
+ totalCount: exports_external.number().int().describe("Total number of commits returned (may be limited by maxCount)."),
147017
+ note: exports_external.string().optional().describe("Set when filters returned zero commits. Echoes the criteria and suggests broadening so callers can self-correct without inspecting the request.")
147114
147018
  });
147115
147019
  async function gitLogLogic(input, { provider, targetPath, appContext }) {
147116
147020
  const result = await provider.log({
@@ -147131,15 +147035,25 @@ async function gitLogLogic(input, { provider, targetPath, appContext }) {
147131
147035
  requestContext: appContext,
147132
147036
  tenantId: appContext.tenantId || "default-tenant"
147133
147037
  });
147134
- const commits = input.oneline ? result.commits.map(({ hash: hash2, shortHash, subject }) => ({
147135
- hash: hash2,
147136
- shortHash,
147137
- subject
147138
- })) : result.commits;
147038
+ const appliedFilters = [];
147039
+ if (input.author)
147040
+ appliedFilters.push(`author=${input.author}`);
147041
+ if (input.grep)
147042
+ appliedFilters.push(`grep=${input.grep}`);
147043
+ if (input.since)
147044
+ appliedFilters.push(`since=${input.since}`);
147045
+ if (input.until)
147046
+ appliedFilters.push(`until=${input.until}`);
147047
+ if (input.filePath)
147048
+ appliedFilters.push(`filePath=${input.filePath}`);
147049
+ if (input.branch)
147050
+ appliedFilters.push(`branch=${input.branch}`);
147051
+ const note = result.commits.length === 0 && appliedFilters.length > 0 ? `No commits matched the applied filters (${appliedFilters.join(", ")}). Try removing filters or broadening the date/author/path criteria.` : undefined;
147139
147052
  return {
147140
147053
  success: true,
147141
- commits,
147142
- totalCount: result.totalCount
147054
+ commits: result.commits,
147055
+ totalCount: result.totalCount,
147056
+ ...note && { note }
147143
147057
  };
147144
147058
  }
147145
147059
  function filterGitLogOutput(result, level) {
@@ -147258,7 +147172,8 @@ var InputSchema16 = exports_external.object({
147258
147172
  all: AllSchema.describe("For list operation: show both local and remote branches."),
147259
147173
  remote: exports_external.boolean().default(false).describe("For list operation: show only remote branches."),
147260
147174
  merged: exports_external.preprocess((val) => val === "true" ? true : val === "false" ? false : val, exports_external.union([exports_external.boolean(), CommitRefSchema])).optional().describe("For list operation: show only branches merged into HEAD (true) or specified commit (string)."),
147261
- noMerged: exports_external.preprocess((val) => val === "true" ? true : val === "false" ? false : val, exports_external.union([exports_external.boolean(), CommitRefSchema])).optional().describe("For list operation: show only branches not merged into HEAD (true) or specified commit (string).")
147175
+ noMerged: exports_external.preprocess((val) => val === "true" ? true : val === "false" ? false : val, exports_external.union([exports_external.boolean(), CommitRefSchema])).optional().describe("For list operation: show only branches not merged into HEAD (true) or specified commit (string)."),
147176
+ limit: LimitSchema.describe("For list operation: cap the number of branches returned (applied at the git command). Use on repos with many branches.")
147262
147177
  });
147263
147178
  var BranchInfoSchema = exports_external.object({
147264
147179
  name: exports_external.string().describe("Branch name."),
@@ -147277,18 +147192,18 @@ var OutputSchema17 = exports_external.object({
147277
147192
  });
147278
147193
  async function gitBranchLogic(input, { provider, targetPath, appContext }) {
147279
147194
  if (input.operation === "show-current") {
147280
- const result2 = await provider.branch({ mode: "list" }, {
147195
+ const result2 = await provider.branch({ mode: "show-current" }, {
147281
147196
  workingDirectory: targetPath,
147282
147197
  requestContext: appContext,
147283
147198
  tenantId: appContext.tenantId || "default-tenant"
147284
147199
  });
147285
- const current = result2.mode === "list" ? result2.branches.find((b) => b.current) : undefined;
147200
+ const current = result2.mode === "show-current" ? result2.current : null;
147286
147201
  return {
147287
147202
  success: true,
147288
147203
  operation: "show-current",
147289
147204
  branches: undefined,
147290
- currentBranch: current?.name,
147291
- message: current ? `Current branch: ${current.name}` : "Not on any branch (detached HEAD)"
147205
+ currentBranch: current ?? undefined,
147206
+ message: current ? `Current branch: ${current}` : "Not on any branch (detached HEAD)"
147292
147207
  };
147293
147208
  }
147294
147209
  const { path: _path, operation, name, newName, ...rest } = input;
@@ -147318,6 +147233,9 @@ async function gitBranchLogic(input, { provider, targetPath, appContext }) {
147318
147233
  if (rest.noMerged !== undefined) {
147319
147234
  branchOptions.noMerged = rest.noMerged;
147320
147235
  }
147236
+ if (rest.limit !== undefined) {
147237
+ branchOptions.limit = rest.limit;
147238
+ }
147321
147239
  const result = await provider.branch(branchOptions, {
147322
147240
  workingDirectory: targetPath,
147323
147241
  requestContext: appContext,
@@ -147347,7 +147265,7 @@ async function gitBranchLogic(input, { provider, targetPath, appContext }) {
147347
147265
  currentBranch: undefined,
147348
147266
  message: `Branch '${result.deleted}' deleted successfully.`
147349
147267
  };
147350
- } else {
147268
+ } else if (result.mode === "rename") {
147351
147269
  return {
147352
147270
  success: true,
147353
147271
  operation: "rename",
@@ -147356,6 +147274,7 @@ async function gitBranchLogic(input, { provider, targetPath, appContext }) {
147356
147274
  message: `Branch '${result.renamed.from}' renamed to '${result.renamed.to}'.`
147357
147275
  };
147358
147276
  }
147277
+ throw new Error(`Unexpected branch result mode: ${result.mode}`);
147359
147278
  }
147360
147279
  function filterGitBranchOutput(result, level) {
147361
147280
  if (level === "minimal") {
@@ -148113,7 +148032,8 @@ var InputSchema26 = exports_external.object({
148113
148032
  message: exports_external.string().optional().describe("Stash message description (for push operation)."),
148114
148033
  stashRef: exports_external.string().optional().describe("Stash reference like stash@{0} (for pop/apply/drop operations)."),
148115
148034
  includeUntracked: exports_external.boolean().default(false).describe("Include untracked files in the stash (for push operation)."),
148116
- keepIndex: exports_external.boolean().default(false).describe("Don't revert staged changes (for push operation).")
148035
+ keepIndex: exports_external.boolean().default(false).describe("Don't revert staged changes (for push operation)."),
148036
+ limit: LimitSchema.describe("For list mode: cap the number of stash entries returned (applied at the git command).")
148117
148037
  });
148118
148038
  var StashInfoSchema = exports_external.object({
148119
148039
  ref: exports_external.string().describe("Stash reference (e.g., stash@{0})."),
@@ -148147,6 +148067,9 @@ async function gitStashLogic(input, { provider, targetPath, appContext }) {
148147
148067
  if (input.keepIndex !== undefined) {
148148
148068
  stashOptions.keepIndex = input.keepIndex;
148149
148069
  }
148070
+ if (input.limit !== undefined) {
148071
+ stashOptions.limit = input.limit;
148072
+ }
148150
148073
  const result = await provider.stash(stashOptions, {
148151
148074
  workingDirectory: targetPath,
148152
148075
  requestContext: appContext,
@@ -148190,20 +148113,22 @@ init_zod();
148190
148113
  init_errors3();
148191
148114
  var TOOL_NAME27 = "git_tag";
148192
148115
  var TOOL_TITLE27 = "Git Tag";
148193
- var TOOL_DESCRIPTION27 = "Manage tags: list all tags, create a new tag, or delete a tag. Tags are used to mark specific points in history (releases, milestones).";
148116
+ var TOOL_DESCRIPTION27 = "Manage tags: list all tags, create a new tag, delete a tag, or verify a signed tag. Tags are used to mark specific points in history (releases, milestones). Verify runs `git tag -v` and returns a structured result distinguishing unsigned tags, missing trust configuration, bad signatures, and valid signatures.";
148194
148117
  var InputSchema27 = exports_external.object({
148195
148118
  path: PathSchema,
148196
- mode: exports_external.enum(["list", "create", "delete"]).default("list").describe("The tag operation to perform."),
148197
- tagName: TagNameSchema.optional().describe("Tag name for create/delete operations."),
148119
+ mode: exports_external.enum(["list", "create", "delete", "verify"]).default("list").describe("The tag operation to perform."),
148120
+ tagName: TagNameSchema.optional().describe("Tag name for create/delete/verify operations."),
148198
148121
  commit: CommitRefSchema.optional().describe("Commit to tag (default: HEAD for create operation)."),
148199
148122
  message: exports_external.string().optional().describe("Tag message. Providing a message always produces an annotated tag (git does not support messages on lightweight tags). For release tags, summarize notable changes."),
148200
148123
  annotated: exports_external.boolean().default(false).describe('Create an annotated tag with a default "Tag <name>" message. Only effective when no message is provided and signing is disabled — otherwise the tag is always annotated.'),
148201
- force: ForceSchema.describe("Overwrite an existing tag (create mode only; has no effect on list or delete).")
148124
+ force: ForceSchema.describe("Overwrite an existing tag (create mode only; has no effect on list or delete)."),
148125
+ limit: LimitSchema.describe("For list mode: cap the number of tags returned (applied at the git command via `--count=N`). Use on repos with many tags.")
148202
148126
  });
148203
148127
  var TagInfoSchema = exports_external.object({
148204
148128
  name: exports_external.string().describe("Tag name."),
148205
148129
  commit: exports_external.string().describe("Commit hash the tag points to."),
148206
- message: exports_external.string().optional().describe("Tag message (for annotated tags)."),
148130
+ message: exports_external.string().optional().describe("First line of the tag annotation (annotated tags only). See `annotationBody` for the remainder."),
148131
+ annotationBody: exports_external.string().optional().describe("Remaining annotation body after the subject line (annotated tags only)."),
148207
148132
  tagger: exports_external.string().optional().describe("Tagger name and email."),
148208
148133
  timestamp: exports_external.number().int().optional().describe("Tag creation timestamp.")
148209
148134
  });
@@ -148214,10 +148139,17 @@ var OutputSchema28 = exports_external.object({
148214
148139
  created: exports_external.string().optional().describe("Created tag name (for create mode)."),
148215
148140
  deleted: exports_external.string().optional().describe("Deleted tag name (for delete mode)."),
148216
148141
  signed: exports_external.boolean().optional().describe("Whether the created tag was signed. Only populated for create mode. False when GIT_SIGN_COMMITS=false or when signing failed and fell back to unsigned."),
148217
- signingWarning: exports_external.string().optional().describe("Populated only when signing was requested but failed, and the tag was created unsigned as a fallback.")
148142
+ signingWarning: exports_external.string().optional().describe("Populated only when signing was requested but failed, and the tag was created unsigned as a fallback."),
148143
+ verifiedTag: exports_external.string().optional().describe("Verified tag name (for verify mode). Echoes the input so callers can correlate results in batched flows."),
148144
+ verified: exports_external.boolean().optional().describe("Whether the signature validated (for verify mode). `false` for unsigned tags, missing trust config, bad signatures, or unparseable output — inspect `warning` to distinguish."),
148145
+ signatureType: exports_external.enum(["gpg", "ssh", "x509"]).optional().describe("Signature algorithm family when detectable from `git tag -v` output (verify mode). Absent for unsigned tags or unparseable output."),
148146
+ signerIdentity: exports_external.string().optional().describe("Signer identity as emitted by git — e.g., `Name <email>` for GPG or the SSH principal. Verify mode only."),
148147
+ signerKey: exports_external.string().optional().describe("Key material emitted by git — GPG fingerprint/key ID or SSH key fingerprint (`SHA256:…`). Verify mode only; absent when git did not surface it."),
148148
+ warning: exports_external.string().optional().describe("Populated on verify failure with a human-readable reason distinguishing unsigned tags, missing trust configuration, bad signatures, and unparseable output."),
148149
+ rawOutput: exports_external.string().optional().describe("Raw stderr from `git tag -v` for callers that need the full verification output (verify mode only).")
148218
148150
  });
148219
148151
  async function gitTagLogic(input, { provider, targetPath, appContext }) {
148220
- if ((input.mode === "create" || input.mode === "delete") && !input.tagName) {
148152
+ if ((input.mode === "create" || input.mode === "delete" || input.mode === "verify") && !input.tagName) {
148221
148153
  throw new McpError(-32602 /* InvalidParams */, `Tag name is required for ${input.mode} operation.`);
148222
148154
  }
148223
148155
  const tagOptions = {
@@ -148234,6 +148166,9 @@ async function gitTagLogic(input, { provider, targetPath, appContext }) {
148234
148166
  if (input.message !== undefined) {
148235
148167
  tagOptions.message = normalizeMessage(input.message);
148236
148168
  }
148169
+ if (input.limit !== undefined) {
148170
+ tagOptions.limit = input.limit;
148171
+ }
148237
148172
  const result = await provider.tag(tagOptions, {
148238
148173
  workingDirectory: targetPath,
148239
148174
  requestContext: appContext,
@@ -148252,6 +148187,27 @@ async function gitTagLogic(input, { provider, targetPath, appContext }) {
148252
148187
  if (result.signingWarning) {
148253
148188
  output.signingWarning = result.signingWarning;
148254
148189
  }
148190
+ if (result.verifiedTag !== undefined) {
148191
+ output.verifiedTag = result.verifiedTag;
148192
+ }
148193
+ if (result.verified !== undefined) {
148194
+ output.verified = result.verified;
148195
+ }
148196
+ if (result.signatureType !== undefined) {
148197
+ output.signatureType = result.signatureType;
148198
+ }
148199
+ if (result.signerIdentity !== undefined) {
148200
+ output.signerIdentity = result.signerIdentity;
148201
+ }
148202
+ if (result.signerKey !== undefined) {
148203
+ output.signerKey = result.signerKey;
148204
+ }
148205
+ if (result.warning !== undefined) {
148206
+ output.warning = result.warning;
148207
+ }
148208
+ if (result.rawOutput !== undefined) {
148209
+ output.rawOutput = result.rawOutput;
148210
+ }
148255
148211
  return output;
148256
148212
  }
148257
148213
  function filterGitTagOutput(result, level) {
@@ -148260,10 +148216,16 @@ function filterGitTagOutput(result, level) {
148260
148216
  success: result.success,
148261
148217
  mode: result.mode,
148262
148218
  ...result.signed !== undefined && { signed: result.signed },
148263
- ...result.signingWarning && { signingWarning: result.signingWarning }
148219
+ ...result.signingWarning && { signingWarning: result.signingWarning },
148220
+ ...result.verified !== undefined && { verified: result.verified },
148221
+ ...result.warning && { warning: result.warning }
148264
148222
  };
148265
148223
  }
148266
- return result;
148224
+ if (level === "full") {
148225
+ return result;
148226
+ }
148227
+ const { rawOutput: _raw, ...rest } = result;
148228
+ return rest;
148267
148229
  }
148268
148230
  var responseFormatter27 = createJsonFormatter({
148269
148231
  filter: filterGitTagOutput
@@ -148479,7 +148441,6 @@ var registerTools = (container4) => {
148479
148441
  };
148480
148442
 
148481
148443
  // src/mcp-server/server.ts
148482
- init_utils();
148483
148444
  async function createMcpServerInstance() {
148484
148445
  const context = requestContextService.createRequestContext({
148485
148446
  operation: "createMcpServerInstance"
@@ -148523,7 +148484,6 @@ async function createMcpServerInstance() {
148523
148484
 
148524
148485
  // src/mcp-server/transports/manager.ts
148525
148486
  init_tokens();
148526
- init_utils();
148527
148487
  var import_tsyringe14 = __toESM(require_cjs2(), 1);
148528
148488
 
148529
148489
  // node_modules/@modelcontextprotocol/sdk/dist/esm/server/auth/errors.js
@@ -151031,11 +150991,11 @@ var MemoryEventStore = class {
151031
150991
  #eventIdToStreamIdMap;
151032
150992
  #idGenerator;
151033
150993
  constructor(options = {}) {
151034
- const { streamBufferSize = 100, eventsPerStreamBufferSize = 100, idGenerator: idGenerator3 = () => crypto.randomUUID() } = options;
150994
+ const { streamBufferSize = 100, eventsPerStreamBufferSize = 100, idGenerator: idGenerator2 = () => crypto.randomUUID() } = options;
151035
150995
  this.#idToIndexMap = /* @__PURE__ */ new Map;
151036
150996
  this.#eventIdToStreamIdMap = /* @__PURE__ */ new Map;
151037
150997
  this.#eventsPerStreamBufferSize = eventsPerStreamBufferSize;
151038
- this.#idGenerator = idGenerator3;
150998
+ this.#idGenerator = idGenerator2;
151039
150999
  this.#items = new RingBuffer(streamBufferSize, ({ streamId, events }) => {
151040
151000
  this.#idToIndexMap.delete(streamId);
151041
151001
  events.reset();
@@ -152279,13 +152239,8 @@ var serve = (options, listeningListener) => {
152279
152239
  init_config();
152280
152240
  import http3 from "http";
152281
152241
  import { randomUUID } from "node:crypto";
152282
-
152283
- // src/mcp-server/transports/auth/index.ts
152284
- init_authContext();
152285
-
152286
152242
  // src/mcp-server/transports/auth/authFactory.ts
152287
152243
  init_config();
152288
- init_utils();
152289
152244
  var import_tsyringe13 = __toESM(require_cjs2(), 1);
152290
152245
 
152291
152246
  // node_modules/jose/dist/webapi/lib/buffer_utils.js
@@ -153773,7 +153728,6 @@ function createRemoteJWKSet(url2, options) {
153773
153728
  // src/mcp-server/transports/auth/strategies/jwtStrategy.ts
153774
153729
  init_tokens();
153775
153730
  init_errors3();
153776
- init_utils();
153777
153731
  var import_tsyringe11 = __toESM(require_cjs2(), 1);
153778
153732
  class JwtStrategy {
153779
153733
  config;
@@ -153782,9 +153736,9 @@ class JwtStrategy {
153782
153736
  env;
153783
153737
  devMcpClientId;
153784
153738
  devMcpScopes;
153785
- constructor(config3, logger3) {
153739
+ constructor(config3, logger2) {
153786
153740
  this.config = config3;
153787
- this.logger = logger3;
153741
+ this.logger = logger2;
153788
153742
  const context = requestContextService.createRequestContext({
153789
153743
  operation: "JwtStrategy.constructor"
153790
153744
  });
@@ -153889,15 +153843,14 @@ JwtStrategy = __legacyDecorateClassTS([
153889
153843
  // src/mcp-server/transports/auth/strategies/oauthStrategy.ts
153890
153844
  init_tokens();
153891
153845
  init_errors3();
153892
- init_utils();
153893
153846
  var import_tsyringe12 = __toESM(require_cjs2(), 1);
153894
153847
  class OauthStrategy {
153895
153848
  config;
153896
153849
  logger;
153897
153850
  jwks;
153898
- constructor(config3, logger3) {
153851
+ constructor(config3, logger2) {
153899
153852
  this.config = config3;
153900
- this.logger = logger3;
153853
+ this.logger = logger2;
153901
153854
  const context = requestContextService.createRequestContext({
153902
153855
  operation: "OauthStrategy.constructor"
153903
153856
  });
@@ -154042,8 +153995,6 @@ function createAuthStrategy() {
154042
153995
  }
154043
153996
  // src/mcp-server/transports/auth/authMiddleware.ts
154044
153997
  init_errors3();
154045
- init_utils();
154046
- init_authContext();
154047
153998
  function createAuthMiddleware(strategy) {
154048
153999
  return async function authMiddleware(c, next) {
154049
154000
  const context = requestContextService.createRequestContext({
@@ -154092,7 +154043,6 @@ function createAuthMiddleware(strategy) {
154092
154043
  }
154093
154044
  // src/mcp-server/transports/http/httpErrorHandler.ts
154094
154045
  init_errors3();
154095
- init_utils();
154096
154046
  var httpErrorHandler = async (err, c) => {
154097
154047
  const context = requestContextService.createRequestContext({
154098
154048
  operation: "httpErrorHandler",
@@ -154177,8 +154127,6 @@ var httpErrorHandler = async (err, c) => {
154177
154127
  };
154178
154128
 
154179
154129
  // src/mcp-server/transports/http/sessionManager.ts
154180
- init_utils();
154181
-
154182
154130
  class SessionManager {
154183
154131
  static instance = null;
154184
154132
  sessions = new Map;
@@ -154337,7 +154285,6 @@ class SessionManager {
154337
154285
  }
154338
154286
 
154339
154287
  // src/mcp-server/transports/http/httpTransport.ts
154340
- init_utils();
154341
154288
  function createHttpApp(createMcpServer, parentContext) {
154342
154289
  const app = new Hono2;
154343
154290
  const transportContext = {
@@ -154713,7 +154660,6 @@ class StdioServerTransport {
154713
154660
  }
154714
154661
 
154715
154662
  // src/mcp-server/transports/stdio/stdioTransport.ts
154716
- init_utils();
154717
154663
  async function startStdioTransport(server, parentContext) {
154718
154664
  const operationContext = {
154719
154665
  ...parentContext,
@@ -154760,9 +154706,9 @@ class TransportManager {
154760
154706
  logger;
154761
154707
  createMcpServer;
154762
154708
  serverInstance = null;
154763
- constructor(config3, logger3, createMcpServer) {
154709
+ constructor(config3, logger2, createMcpServer) {
154764
154710
  this.config = config3;
154765
- this.logger = logger3;
154711
+ this.logger = logger2;
154766
154712
  this.createMcpServer = createMcpServer;
154767
154713
  }
154768
154714
  async start() {
@@ -154815,7 +154761,6 @@ TransportManager = __legacyDecorateClassTS([
154815
154761
  ], TransportManager);
154816
154762
 
154817
154763
  // src/container/registrations/mcp.ts
154818
- init_utils();
154819
154764
  var registerMcpServices = () => {
154820
154765
  import_tsyringe15.container.registerSingleton(ToolRegistry);
154821
154766
  import_tsyringe15.container.registerSingleton(ResourceRegistry);
@@ -154911,11 +154856,11 @@ var start = async () => {
154911
154856
  }
154912
154857
  await logger.initialize(validatedMcpLogLevel, config3.mcpTransportType);
154913
154858
  logger.info(`Logger initialized. Effective MCP logging level: ${validatedMcpLogLevel}.`, requestContextService.createRequestContext({ operation: "LoggerInit" }));
154914
- const runtime2 = detectRuntime();
154859
+ const runtime = detectRuntime();
154915
154860
  const runtimeDesc = getRuntimeDescription();
154916
154861
  logger.info(`Runtime detected: ${runtimeDesc}`, requestContextService.createRequestContext({
154917
154862
  operation: "RuntimeDetection",
154918
- runtime: runtime2,
154863
+ runtime,
154919
154864
  runtimeVersion: runtimeDesc
154920
154865
  }));
154921
154866
  logger.info(`Storage service initialized with provider: ${config3.storage.providerType}`, requestContextService.createRequestContext({ operation: "StorageInit" }));