@cyanheads/git-mcp-server 2.12.0 → 2.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +38 -38
  2. package/dist/index.js +1855 -2035
  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.12.0",
15287
+ version: "2.13.0",
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",
@@ -15517,6 +15517,17 @@ var import_dotenv, packageManifest, emptyStringAsUndefined = (val) => {
15517
15517
  return;
15518
15518
  }
15519
15519
  return val;
15520
+ }, parseBoolEnv = (defaultValue) => (val) => {
15521
+ if (typeof val === "boolean")
15522
+ return val;
15523
+ if (typeof val === "string") {
15524
+ const lower = val.trim().toLowerCase();
15525
+ if (["true", "1", "yes", "on"].includes(lower))
15526
+ return true;
15527
+ if (["false", "0", "no", "off", ""].includes(lower))
15528
+ return false;
15529
+ }
15530
+ return defaultValue;
15520
15531
  }, expandTildePath = (path2) => {
15521
15532
  if (typeof path2 !== "string" || path2.trim() === "") {
15522
15533
  return;
@@ -15737,7 +15748,7 @@ var init_config = __esm(() => {
15737
15748
  }),
15738
15749
  git: exports_external.object({
15739
15750
  provider: exports_external.preprocess(emptyStringAsUndefined, exports_external.enum(["auto", "cli", "isomorphic"]).default("auto")),
15740
- signCommits: exports_external.coerce.boolean().default(false),
15751
+ signCommits: exports_external.preprocess(parseBoolEnv(true), exports_external.boolean()),
15741
15752
  authorName: exports_external.string().regex(/^[^\n\r\0]*$/, "Git author name must not contain newlines or null bytes").optional(),
15742
15753
  authorEmail: exports_external.string().email().optional(),
15743
15754
  committerName: exports_external.string().regex(/^[^\n\r\0]*$/, "Git committer name must not contain newlines or null bytes").optional(),
@@ -105568,75 +105579,6 @@ var require_index_incubating = __commonJS((exports) => {
105568
105579
  __exportStar(require_experimental_events(), exports);
105569
105580
  });
105570
105581
 
105571
- // src/mcp-server/transports/auth/lib/authContext.ts
105572
- import { AsyncLocalStorage } from "async_hooks";
105573
- var authContext;
105574
- var init_authContext = __esm(() => {
105575
- authContext = new AsyncLocalStorage;
105576
- });
105577
-
105578
- // src/utils/internal/requestContext.ts
105579
- var import_api2, requestContextServiceInstance, requestContextService;
105580
- var init_requestContext = __esm(() => {
105581
- init_authContext();
105582
- init_utils();
105583
- init_logger();
105584
- import_api2 = __toESM(require_src(), 1);
105585
- requestContextServiceInstance = {
105586
- config: {},
105587
- configure(config3) {
105588
- this.config = {
105589
- ...this.config,
105590
- ...config3
105591
- };
105592
- const logContext = this.createRequestContext({
105593
- operation: "RequestContextService.configure",
105594
- additionalContext: { newConfigState: { ...this.config } }
105595
- });
105596
- logger.debug("RequestContextService configuration updated", logContext);
105597
- return { ...this.config };
105598
- },
105599
- getConfig() {
105600
- return { ...this.config };
105601
- },
105602
- createRequestContext(params = {}) {
105603
- const { parentContext, additionalContext, operation, ...rest } = params;
105604
- const inheritedContext = parentContext && typeof parentContext === "object" ? { ...parentContext } : {};
105605
- let inheritedTenantId;
105606
- if (inheritedContext && typeof inheritedContext === "object" && "tenantId" in inheritedContext && typeof inheritedContext.tenantId === "string") {
105607
- inheritedTenantId = inheritedContext.tenantId;
105608
- }
105609
- const authStore = authContext.getStore();
105610
- const tenantIdFromAuth = authStore?.authInfo?.tenantId;
105611
- const inheritedRequestId = inheritedContext.requestId;
105612
- const requestId = typeof inheritedRequestId === "string" && inheritedRequestId ? inheritedRequestId : generateRequestContextId();
105613
- const timestamp = new Date().toISOString();
105614
- const restTenantId = typeof rest.tenantId === "string" ? rest.tenantId : undefined;
105615
- const additionalTenantId = additionalContext && typeof additionalContext === "object" && typeof additionalContext.tenantId === "string" ? additionalContext.tenantId : undefined;
105616
- const resolvedTenantId = additionalTenantId ?? restTenantId ?? inheritedTenantId ?? tenantIdFromAuth;
105617
- const context = {
105618
- ...inheritedContext,
105619
- ...rest,
105620
- requestId,
105621
- timestamp,
105622
- ...resolvedTenantId ? { tenantId: resolvedTenantId } : {},
105623
- ...additionalContext && typeof additionalContext === "object" ? additionalContext : {},
105624
- ...operation && typeof operation === "string" ? { operation } : {}
105625
- };
105626
- const activeSpan = import_api2.trace.getActiveSpan();
105627
- if (activeSpan && typeof activeSpan.spanContext === "function") {
105628
- const spanContext = activeSpan.spanContext();
105629
- if (spanContext) {
105630
- context.traceId = spanContext.traceId;
105631
- context.spanId = spanContext.spanId;
105632
- }
105633
- }
105634
- return context;
105635
- }
105636
- };
105637
- requestContextService = requestContextServiceInstance;
105638
- });
105639
-
105640
105582
  // node_modules/validator/lib/util/assertString.js
105641
105583
  var require_assertString = __commonJS((exports, module) => {
105642
105584
  Object.defineProperty(exports, "__esModule", {
@@ -112035,1408 +111977,6 @@ var require_validator = __commonJS((exports, module) => {
112035
111977
  module.exports.default = exports.default;
112036
111978
  });
112037
111979
 
112038
- // src/utils/security/sanitization.ts
112039
- class Sanitization {
112040
- static instance;
112041
- sensitiveFields = [
112042
- "password",
112043
- "token",
112044
- "secret",
112045
- "apiKey",
112046
- "credential",
112047
- "jwt",
112048
- "ssn",
112049
- "cvv",
112050
- "authorization",
112051
- "cookie",
112052
- "clientsecret",
112053
- "client_secret",
112054
- "private_key",
112055
- "privatekey"
112056
- ];
112057
- constructor() {}
112058
- static getInstance() {
112059
- if (!Sanitization.instance) {
112060
- Sanitization.instance = new Sanitization;
112061
- }
112062
- return Sanitization.instance;
112063
- }
112064
- setSensitiveFields(fields) {
112065
- this.sensitiveFields = [
112066
- ...new Set([
112067
- ...this.sensitiveFields,
112068
- ...fields.map((f3) => f3.toLowerCase())
112069
- ])
112070
- ];
112071
- const logContext = requestContextService.createRequestContext({
112072
- operation: "Sanitization.setSensitiveFields",
112073
- additionalContext: {
112074
- newSensitiveFieldCount: this.sensitiveFields.length
112075
- }
112076
- });
112077
- logger.debug("Updated sensitive fields list for log sanitization", logContext);
112078
- }
112079
- getSensitiveFields() {
112080
- return [...this.sensitiveFields];
112081
- }
112082
- getSensitivePinoFields() {
112083
- return this.sensitiveFields.map((field) => field.replace(/[-_]/g, ""));
112084
- }
112085
- sanitizeUrl(input, allowedProtocols = ["http", "https"]) {
112086
- try {
112087
- const trimmedInput = input.trim();
112088
- if (!import_validator.default.isURL(trimmedInput, {
112089
- protocols: allowedProtocols,
112090
- require_protocol: true,
112091
- require_host: true
112092
- })) {
112093
- throw new Error("Invalid URL format or protocol not in allowed list.");
112094
- }
112095
- const lowercasedInput = trimmedInput.toLowerCase();
112096
- if (lowercasedInput.startsWith("javascript:") || lowercasedInput.startsWith("data:") || lowercasedInput.startsWith("vbscript:")) {
112097
- throw new Error("Disallowed pseudo-protocol (javascript:, data:, or vbscript:) in URL.");
112098
- }
112099
- return trimmedInput;
112100
- } catch (error48) {
112101
- throw new McpError(-32007 /* ValidationError */, error48 instanceof Error ? error48.message : "Invalid or unsafe URL provided.", { input });
112102
- }
112103
- }
112104
- sanitizePath(input, options = {}) {
112105
- if (isServerless || !pathModule) {
112106
- throw new McpError(-32603 /* InternalError */, "File-based path sanitization is not supported in this environment.");
112107
- }
112108
- const path2 = pathModule;
112109
- const originalInput = input;
112110
- const resolvedRootDir = options.rootDir ? path2.resolve(options.rootDir) : undefined;
112111
- const effectiveOptions = {
112112
- toPosix: options.toPosix ?? false,
112113
- allowAbsolute: options.allowAbsolute ?? false,
112114
- ...resolvedRootDir && { rootDir: resolvedRootDir }
112115
- };
112116
- let wasAbsoluteInitially = false;
112117
- try {
112118
- if (!input || typeof input !== "string")
112119
- throw new Error("Invalid path input: must be a non-empty string.");
112120
- if (input.includes("\x00"))
112121
- throw new Error("Path contains null byte, which is disallowed.");
112122
- let normalized = path2.normalize(input);
112123
- wasAbsoluteInitially = path2.isAbsolute(normalized);
112124
- if (effectiveOptions.toPosix) {
112125
- normalized = normalized.replace(/\\/g, "/");
112126
- }
112127
- let finalSanitizedPath;
112128
- if (resolvedRootDir) {
112129
- let fullPath;
112130
- if (path2.isAbsolute(normalized)) {
112131
- fullPath = path2.normalize(normalized);
112132
- } else {
112133
- fullPath = path2.resolve(resolvedRootDir, normalized);
112134
- }
112135
- const normalizedRoot = path2.normalize(resolvedRootDir);
112136
- const normalizedFull = path2.normalize(fullPath);
112137
- if (!normalizedFull.startsWith(normalizedRoot + path2.sep) && normalizedFull !== normalizedRoot) {
112138
- throw new Error("Path traversal detected: attempts to escape the defined root directory.");
112139
- }
112140
- finalSanitizedPath = path2.relative(normalizedRoot, normalizedFull);
112141
- finalSanitizedPath = finalSanitizedPath === "" ? "." : finalSanitizedPath;
112142
- if (path2.isAbsolute(finalSanitizedPath) && !effectiveOptions.allowAbsolute) {
112143
- throw new Error("Path resolved to absolute outside root when absolute paths are disallowed.");
112144
- }
112145
- } else {
112146
- if (path2.isAbsolute(normalized)) {
112147
- if (!effectiveOptions.allowAbsolute) {
112148
- throw new Error("Absolute paths are disallowed by current options.");
112149
- } else {
112150
- finalSanitizedPath = normalized;
112151
- }
112152
- } else {
112153
- const resolvedAgainstCwd = path2.resolve(normalized);
112154
- const currentWorkingDir = path2.resolve(".");
112155
- if (!resolvedAgainstCwd.startsWith(currentWorkingDir + path2.sep) && resolvedAgainstCwd !== currentWorkingDir) {
112156
- throw new Error("Relative path traversal detected (escapes current working directory context).");
112157
- }
112158
- finalSanitizedPath = normalized;
112159
- }
112160
- }
112161
- return {
112162
- sanitizedPath: finalSanitizedPath,
112163
- originalInput,
112164
- wasAbsolute: wasAbsoluteInitially,
112165
- convertedToRelative: wasAbsoluteInitially && !path2.isAbsolute(finalSanitizedPath) && !effectiveOptions.allowAbsolute,
112166
- optionsUsed: effectiveOptions
112167
- };
112168
- } catch (error48) {
112169
- logger.warning("Path sanitization error", requestContextService.createRequestContext({
112170
- operation: "Sanitization.sanitizePath.error",
112171
- additionalContext: {
112172
- originalPathInput: originalInput,
112173
- pathOptionsUsed: effectiveOptions,
112174
- errorMessage: error48 instanceof Error ? error48.message : String(error48)
112175
- }
112176
- }));
112177
- throw new McpError(-32007 /* ValidationError */, error48 instanceof Error ? error48.message : "Invalid or unsafe path provided.", { input: originalInput });
112178
- }
112179
- }
112180
- sanitizeJson(input, maxSize) {
112181
- try {
112182
- if (typeof input !== "string")
112183
- throw new Error("Invalid input: expected a JSON string.");
112184
- const computeBytes = (s2) => {
112185
- if (typeof Buffer !== "undefined" && typeof Buffer.byteLength === "function") {
112186
- return Buffer.byteLength(s2, "utf8");
112187
- }
112188
- if (typeof TextEncoder !== "undefined") {
112189
- return new TextEncoder().encode(s2).length;
112190
- }
112191
- return s2.length;
112192
- };
112193
- if (maxSize !== undefined && computeBytes(input) > maxSize) {
112194
- throw new McpError(-32007 /* ValidationError */, `JSON string exceeds maximum allowed size of ${maxSize} bytes.`, { actualSize: computeBytes(input), maxSize });
112195
- }
112196
- return JSON.parse(input);
112197
- } catch (error48) {
112198
- if (error48 instanceof McpError)
112199
- throw error48;
112200
- throw new McpError(-32007 /* ValidationError */, error48 instanceof Error ? error48.message : "Invalid JSON format.", {
112201
- inputPreview: input.length > 100 ? `${input.substring(0, 100)}...` : input
112202
- });
112203
- }
112204
- }
112205
- sanitizeNumber(input, min, max) {
112206
- let value;
112207
- if (typeof input === "string") {
112208
- const trimmedInput = input.trim();
112209
- if (trimmedInput === "" || !import_validator.default.isNumeric(trimmedInput)) {
112210
- throw new McpError(-32007 /* ValidationError */, "Invalid number format: input is empty or not numeric.", { input });
112211
- }
112212
- value = parseFloat(trimmedInput);
112213
- } else if (typeof input === "number") {
112214
- value = input;
112215
- } else {
112216
- throw new McpError(-32007 /* ValidationError */, "Invalid input type: expected number or string.", { input: String(input) });
112217
- }
112218
- if (isNaN(value) || !isFinite(value)) {
112219
- throw new McpError(-32007 /* ValidationError */, "Invalid number value (NaN or Infinity).", { input });
112220
- }
112221
- let clamped = false;
112222
- const originalValueForLog = value;
112223
- if (min !== undefined && value < min) {
112224
- value = min;
112225
- clamped = true;
112226
- }
112227
- if (max !== undefined && value > max) {
112228
- value = max;
112229
- clamped = true;
112230
- }
112231
- if (clamped) {
112232
- logger.debug("Number clamped to range.", requestContextService.createRequestContext({
112233
- operation: "Sanitization.sanitizeNumber.clamped",
112234
- additionalContext: {
112235
- originalInput: String(input),
112236
- parsedValue: originalValueForLog,
112237
- minValue: min,
112238
- maxValue: max,
112239
- clampedValue: value
112240
- }
112241
- }));
112242
- }
112243
- return value;
112244
- }
112245
- sanitizeForLogging(input) {
112246
- try {
112247
- if (!input || typeof input !== "object")
112248
- return input;
112249
- const clonedInput = typeof globalThis.structuredClone === "function" ? globalThis.structuredClone(input) : JSON.parse(JSON.stringify(input));
112250
- this.redactSensitiveFields(clonedInput);
112251
- return clonedInput;
112252
- } catch (error48) {
112253
- logger.error("Error during log sanitization, returning placeholder.", requestContextService.createRequestContext({
112254
- operation: "Sanitization.sanitizeForLogging.error",
112255
- additionalContext: {
112256
- errorMessage: error48 instanceof Error ? error48.message : String(error48)
112257
- }
112258
- }));
112259
- return "[Log Sanitization Failed]";
112260
- }
112261
- }
112262
- redactSensitiveFields(obj) {
112263
- if (!obj || typeof obj !== "object")
112264
- return;
112265
- if (Array.isArray(obj)) {
112266
- obj.forEach((item) => this.redactSensitiveFields(item));
112267
- return;
112268
- }
112269
- const normalize = (str) => str.toLowerCase().replace(/[^a-z0-9]/g, "");
112270
- const normalizedSensitiveSet = new Set(this.sensitiveFields.map((f3) => normalize(f3)).filter(Boolean));
112271
- const wordSensitiveSet = new Set(this.sensitiveFields.map((f3) => f3.toLowerCase()).filter(Boolean));
112272
- for (const key in obj) {
112273
- if (Object.prototype.hasOwnProperty.call(obj, key)) {
112274
- const value = obj[key];
112275
- const normalizedKey = normalize(key);
112276
- const keyWords = key.replace(/([A-Z])/g, " $1").toLowerCase().split(/[\s_-]+/).filter(Boolean);
112277
- const isExactSensitive = normalizedSensitiveSet.has(normalizedKey);
112278
- const isWordSensitive = keyWords.some((w) => wordSensitiveSet.has(w));
112279
- const isSensitive = isExactSensitive || isWordSensitive;
112280
- if (isSensitive) {
112281
- obj[key] = "[REDACTED]";
112282
- } else if (value && typeof value === "object") {
112283
- this.redactSensitiveFields(value);
112284
- }
112285
- }
112286
- }
112287
- }
112288
- }
112289
- var import_validator, isServerless, pathModule, sanitization, sanitizeInputForLogging = (input) => sanitization.sanitizeForLogging(input);
112290
- var init_sanitization = __esm(() => {
112291
- init_errors3();
112292
- init_utils();
112293
- import_validator = __toESM(require_validator(), 1);
112294
- isServerless = typeof process === "undefined" || process.env.IS_SERVERLESS === "true";
112295
- if (!isServerless) {
112296
- import("path").then((mod2) => {
112297
- pathModule = mod2.default;
112298
- }).catch(() => {});
112299
- }
112300
- sanitization = Sanitization.getInstance();
112301
- });
112302
-
112303
- // src/utils/internal/logger.ts
112304
- import pino from "pino";
112305
- var mcpToPinoLevel, pinoToMcpLevelSeverity, isServerless2, Logger, logger;
112306
- var init_logger = __esm(() => {
112307
- init_config();
112308
- init_requestContext();
112309
- init_sanitization();
112310
- mcpToPinoLevel = {
112311
- emerg: "fatal",
112312
- alert: "fatal",
112313
- crit: "error",
112314
- error: "error",
112315
- warning: "warn",
112316
- notice: "info",
112317
- info: "info",
112318
- debug: "debug"
112319
- };
112320
- pinoToMcpLevelSeverity = {
112321
- fatal: 0,
112322
- error: 2,
112323
- warn: 4,
112324
- info: 6,
112325
- debug: 7
112326
- };
112327
- isServerless2 = typeof process === "undefined" || process.env.IS_SERVERLESS === "true";
112328
- Logger = class Logger {
112329
- static instance = new Logger;
112330
- pinoLogger;
112331
- interactionLogger;
112332
- initialized = false;
112333
- currentMcpLevel = "info";
112334
- transportType;
112335
- rateLimitThreshold = 10;
112336
- rateLimitWindow = 60000;
112337
- messageCounts = new Map;
112338
- suppressedMessages = new Map;
112339
- cleanupTimer;
112340
- constructor() {}
112341
- static getInstance() {
112342
- return Logger.instance;
112343
- }
112344
- async createPinoLogger(level, transportType) {
112345
- const pinoLevel = mcpToPinoLevel[level] || "info";
112346
- const pinoOptions = {
112347
- level: pinoLevel,
112348
- base: {
112349
- env: config2.environment,
112350
- version: config2.mcpServerVersion,
112351
- pid: !isServerless2 ? process.pid : undefined
112352
- },
112353
- redact: {
112354
- paths: sanitization.getSensitivePinoFields(),
112355
- censor: "[REDACTED]"
112356
- }
112357
- };
112358
- if (isServerless2) {
112359
- return pino(pinoOptions);
112360
- }
112361
- const { default: fs2 } = await import("fs");
112362
- const { default: path2 } = await import("path");
112363
- const transports = [];
112364
- const isDevelopment = config2.environment === "development";
112365
- const isTest = config2.environment === "testing";
112366
- const noColorEnv = process.env.NO_COLOR === "1" || process.env.FORCE_COLOR === "0";
112367
- const useColoredOutput = isDevelopment && transportType !== "stdio" && !noColorEnv;
112368
- if (useColoredOutput && !isServerless2) {
112369
- try {
112370
- const { createRequire: createRequire2 } = await import("node:module");
112371
- const require2 = createRequire2(import.meta.url);
112372
- const prettyTarget = require2.resolve("pino-pretty");
112373
- transports.push({
112374
- target: prettyTarget,
112375
- options: { colorize: true, translateTime: "yyyy-mm-dd HH:MM:ss" }
112376
- });
112377
- } catch (err) {
112378
- if (process.stderr?.isTTY) {
112379
- console.warn(`[Logger Init] Pretty transport unavailable (${err instanceof Error ? err.message : String(err)}); falling back to stdout JSON.`);
112380
- }
112381
- transports.push({ target: "pino/file", options: { destination: 1 } });
112382
- }
112383
- } else if (!isTest) {
112384
- transports.push({ target: "pino/file", options: { destination: 2 } });
112385
- }
112386
- if (config2.logsPath) {
112387
- try {
112388
- if (!fs2.existsSync(config2.logsPath)) {
112389
- fs2.mkdirSync(config2.logsPath, { recursive: true });
112390
- }
112391
- transports.push({
112392
- level: pinoLevel,
112393
- target: "pino/file",
112394
- options: {
112395
- destination: path2.join(config2.logsPath, "combined.log"),
112396
- mkdir: true
112397
- }
112398
- });
112399
- transports.push({
112400
- level: "error",
112401
- target: "pino/file",
112402
- options: {
112403
- destination: path2.join(config2.logsPath, "error.log"),
112404
- mkdir: true
112405
- }
112406
- });
112407
- } catch (err) {
112408
- if (process.stderr?.isTTY) {
112409
- console.error(`[Logger Init] Failed to configure file logging: ${err instanceof Error ? err.message : String(err)}`);
112410
- }
112411
- }
112412
- }
112413
- return pino({ ...pinoOptions, transport: { targets: transports } });
112414
- }
112415
- async createInteractionLogger() {
112416
- if (isServerless2 || !config2.logsPath)
112417
- return;
112418
- const { default: path2 } = await import("path");
112419
- return pino({
112420
- transport: {
112421
- target: "pino/file",
112422
- options: {
112423
- destination: path2.join(config2.logsPath, "interactions.log"),
112424
- mkdir: true
112425
- }
112426
- }
112427
- });
112428
- }
112429
- async initialize(level = "info", transportType) {
112430
- if (this.initialized) {
112431
- this.warning("Logger already initialized.", requestContextService.createRequestContext({
112432
- operation: "loggerReinit"
112433
- }));
112434
- return;
112435
- }
112436
- this.currentMcpLevel = level;
112437
- this.transportType = transportType;
112438
- this.pinoLogger = await this.createPinoLogger(level, transportType);
112439
- this.interactionLogger = await this.createInteractionLogger();
112440
- if (!isServerless2 && !this.cleanupTimer) {
112441
- this.cleanupTimer = setInterval(() => this.flushSuppressedMessages(), this.rateLimitWindow);
112442
- this.cleanupTimer.unref?.();
112443
- }
112444
- this.initialized = true;
112445
- this.info(`Logger initialized. MCP level: ${level}.`, requestContextService.createRequestContext({ operation: "loggerInit" }));
112446
- }
112447
- setLevel(newLevel) {
112448
- if (!this.pinoLogger || !this.initialized) {
112449
- if (process.stderr?.isTTY) {
112450
- console.error("Cannot set level: Logger not initialized.");
112451
- }
112452
- return;
112453
- }
112454
- this.currentMcpLevel = newLevel;
112455
- this.pinoLogger.level = mcpToPinoLevel[newLevel] || "info";
112456
- this.info(`Log level changed to ${newLevel}.`, requestContextService.createRequestContext({
112457
- operation: "loggerSetLevel"
112458
- }));
112459
- }
112460
- async close() {
112461
- if (!this.initialized)
112462
- return Promise.resolve();
112463
- this.info("Logger shutting down.", requestContextService.createRequestContext({ operation: "loggerClose" }));
112464
- if (this.cleanupTimer)
112465
- clearInterval(this.cleanupTimer);
112466
- this.flushSuppressedMessages();
112467
- await Promise.all([
112468
- new Promise((resolve) => {
112469
- if (this.pinoLogger) {
112470
- this.pinoLogger.flush((err) => {
112471
- if (err && process.stderr?.isTTY && this.transportType !== "stdio") {
112472
- console.error("Error flushing main logger:", err);
112473
- }
112474
- resolve();
112475
- });
112476
- } else {
112477
- resolve();
112478
- }
112479
- }),
112480
- new Promise((resolve) => {
112481
- if (this.interactionLogger) {
112482
- this.interactionLogger.flush((err) => {
112483
- if (err && process.stderr?.isTTY && this.transportType !== "stdio") {
112484
- console.error("Error flushing interaction logger:", err);
112485
- }
112486
- resolve();
112487
- });
112488
- } else {
112489
- resolve();
112490
- }
112491
- })
112492
- ]);
112493
- this.initialized = false;
112494
- }
112495
- isInitialized() {
112496
- return this.initialized;
112497
- }
112498
- isRateLimited(message) {
112499
- const now = Date.now();
112500
- const entry = this.messageCounts.get(message);
112501
- if (!entry) {
112502
- this.messageCounts.set(message, { count: 1, firstSeen: now });
112503
- return false;
112504
- }
112505
- if (now - entry.firstSeen > this.rateLimitWindow) {
112506
- this.messageCounts.set(message, { count: 1, firstSeen: now });
112507
- return false;
112508
- }
112509
- entry.count++;
112510
- if (entry.count > this.rateLimitThreshold) {
112511
- this.suppressedMessages.set(message, (this.suppressedMessages.get(message) || 0) + 1);
112512
- return true;
112513
- }
112514
- return false;
112515
- }
112516
- flushSuppressedMessages() {
112517
- if (this.suppressedMessages.size === 0)
112518
- return;
112519
- for (const [message, count] of this.suppressedMessages.entries()) {
112520
- this.warning(`Log message suppressed ${count} times due to rate limiting.`, requestContextService.createRequestContext({
112521
- operation: "loggerRateLimitFlush",
112522
- additionalContext: { originalMessage: message }
112523
- }));
112524
- }
112525
- this.suppressedMessages.clear();
112526
- this.messageCounts.clear();
112527
- }
112528
- log(level, msg, context, error48) {
112529
- if (!this.pinoLogger || !this.initialized)
112530
- return;
112531
- const pinoLevel = mcpToPinoLevel[level] || "info";
112532
- const currentPinoLevel = mcpToPinoLevel[this.currentMcpLevel] || "info";
112533
- const levelSeverity = pinoToMcpLevelSeverity[pinoLevel];
112534
- const currentLevelSeverity = pinoToMcpLevelSeverity[currentPinoLevel];
112535
- if (typeof levelSeverity === "number" && typeof currentLevelSeverity === "number" && levelSeverity > currentLevelSeverity) {
112536
- return;
112537
- }
112538
- if (this.isRateLimited(msg))
112539
- return;
112540
- const logObject = { ...context };
112541
- if (error48)
112542
- logObject.err = pino.stdSerializers.err(error48);
112543
- this.pinoLogger[pinoLevel](logObject, msg);
112544
- }
112545
- debug(msg, context) {
112546
- this.log("debug", msg, context);
112547
- }
112548
- info(msg, context) {
112549
- this.log("info", msg, context);
112550
- }
112551
- notice(msg, context) {
112552
- this.log("notice", msg, context);
112553
- }
112554
- warning(msg, context) {
112555
- this.log("warning", msg, context);
112556
- }
112557
- error(msg, errorOrContext, context) {
112558
- const errorObj = errorOrContext instanceof Error ? errorOrContext : undefined;
112559
- const actualContext = errorOrContext instanceof Error ? context : errorOrContext;
112560
- this.log("error", msg, actualContext, errorObj);
112561
- }
112562
- crit(msg, errorOrContext, context) {
112563
- const errorObj = errorOrContext instanceof Error ? errorOrContext : undefined;
112564
- const actualContext = errorOrContext instanceof Error ? context : errorOrContext;
112565
- this.log("crit", msg, actualContext, errorObj);
112566
- }
112567
- alert(msg, errorOrContext, context) {
112568
- const errorObj = errorOrContext instanceof Error ? errorOrContext : undefined;
112569
- const actualContext = errorOrContext instanceof Error ? context : errorOrContext;
112570
- this.log("alert", msg, actualContext, errorObj);
112571
- }
112572
- emerg(msg, errorOrContext, context) {
112573
- const errorObj = errorOrContext instanceof Error ? errorOrContext : undefined;
112574
- const actualContext = errorOrContext instanceof Error ? context : errorOrContext;
112575
- this.log("emerg", msg, actualContext, errorObj);
112576
- }
112577
- fatal(msg, errorOrContext, context) {
112578
- this.emerg(msg, errorOrContext, context);
112579
- }
112580
- logInteraction(interactionName, data) {
112581
- if (!this.interactionLogger) {
112582
- if (!isServerless2)
112583
- this.warning("Interaction logger not available.", data.context || {});
112584
- return;
112585
- }
112586
- this.interactionLogger.info({ interactionName, ...data });
112587
- }
112588
- };
112589
- logger = Logger.getInstance();
112590
- });
112591
-
112592
- // src/utils/internal/error-handler/mappings.ts
112593
- var ERROR_TYPE_MAPPINGS, COMMON_ERROR_PATTERNS;
112594
- var init_mappings = __esm(() => {
112595
- ERROR_TYPE_MAPPINGS = {
112596
- SyntaxError: -32007 /* ValidationError */,
112597
- TypeError: -32007 /* ValidationError */,
112598
- ReferenceError: -32603 /* InternalError */,
112599
- RangeError: -32007 /* ValidationError */,
112600
- URIError: -32007 /* ValidationError */,
112601
- EvalError: -32603 /* InternalError */,
112602
- AggregateError: -32603 /* InternalError */
112603
- };
112604
- COMMON_ERROR_PATTERNS = [
112605
- {
112606
- pattern: /auth|unauthorized|unauthenticated|not.*logged.*in|invalid.*token|expired.*token/i,
112607
- errorCode: -32006 /* Unauthorized */
112608
- },
112609
- {
112610
- pattern: /permission|forbidden|access.*denied|not.*allowed/i,
112611
- errorCode: -32005 /* Forbidden */
112612
- },
112613
- {
112614
- pattern: /not found|missing|no such|doesn't exist|couldn't find/i,
112615
- errorCode: -32001 /* NotFound */
112616
- },
112617
- {
112618
- pattern: /invalid|validation|malformed|bad request|wrong format|missing required/i,
112619
- errorCode: -32007 /* ValidationError */
112620
- },
112621
- {
112622
- pattern: /conflict|already exists|duplicate|unique constraint/i,
112623
- errorCode: -32002 /* Conflict */
112624
- },
112625
- {
112626
- pattern: /rate limit|too many requests|throttled/i,
112627
- errorCode: -32003 /* RateLimited */
112628
- },
112629
- {
112630
- pattern: /timeout|timed out|deadline exceeded/i,
112631
- errorCode: -32004 /* Timeout */
112632
- },
112633
- {
112634
- pattern: /abort(ed)?|cancell?ed/i,
112635
- errorCode: -32004 /* Timeout */
112636
- },
112637
- {
112638
- pattern: /service unavailable|bad gateway|gateway timeout|upstream error/i,
112639
- errorCode: -32000 /* ServiceUnavailable */
112640
- },
112641
- {
112642
- pattern: /zod|zoderror|schema validation/i,
112643
- errorCode: -32007 /* ValidationError */
112644
- }
112645
- ];
112646
- });
112647
-
112648
- // src/utils/internal/error-handler/helpers.ts
112649
- function createSafeRegex(pattern) {
112650
- if (pattern instanceof RegExp) {
112651
- let flags = pattern.flags.replace("g", "");
112652
- if (!flags.includes("i")) {
112653
- flags += "i";
112654
- }
112655
- return new RegExp(pattern.source, flags);
112656
- }
112657
- return new RegExp(pattern, "i");
112658
- }
112659
- function getErrorName(error48) {
112660
- if (error48 instanceof Error) {
112661
- return error48.name || "Error";
112662
- }
112663
- if (error48 === null) {
112664
- return "NullValueEncountered";
112665
- }
112666
- if (error48 === undefined) {
112667
- return "UndefinedValueEncountered";
112668
- }
112669
- if (typeof error48 === "object" && error48 !== null && error48.constructor && typeof error48.constructor.name === "string" && error48.constructor.name !== "Object") {
112670
- return `${error48.constructor.name}Encountered`;
112671
- }
112672
- return `${typeof error48}Encountered`;
112673
- }
112674
- function getErrorMessage(error48) {
112675
- try {
112676
- if (error48 instanceof Error) {
112677
- if ("errors" in error48 && Array.isArray(error48.errors)) {
112678
- const inner = error48.errors.map((e2) => e2 instanceof Error ? e2.message : String(e2)).filter(Boolean).slice(0, 3).join("; ");
112679
- return inner ? `${error48.message}: ${inner}` : error48.message;
112680
- }
112681
- return error48.message;
112682
- }
112683
- if (error48 === null) {
112684
- return "Null value encountered as error";
112685
- }
112686
- if (error48 === undefined) {
112687
- return "Undefined value encountered as error";
112688
- }
112689
- if (typeof error48 === "string") {
112690
- return error48;
112691
- }
112692
- if (typeof error48 === "number" || typeof error48 === "boolean") {
112693
- return String(error48);
112694
- }
112695
- if (typeof error48 === "bigint") {
112696
- return error48.toString();
112697
- }
112698
- if (typeof error48 === "function") {
112699
- return `[function ${error48.name || "anonymous"}]`;
112700
- }
112701
- if (typeof error48 === "object") {
112702
- try {
112703
- const json2 = JSON.stringify(error48);
112704
- if (json2 && json2 !== "{}")
112705
- return json2;
112706
- } catch {}
112707
- const ctor = error48.constructor?.name;
112708
- return `Non-Error object encountered (constructor: ${ctor || "Object"})`;
112709
- }
112710
- if (typeof error48 === "symbol") {
112711
- return error48.toString();
112712
- }
112713
- return "[unrepresentable error]";
112714
- } catch (conversionError) {
112715
- return `Error converting error to string: ${conversionError instanceof Error ? conversionError.message : "Unknown conversion error"}`;
112716
- }
112717
- }
112718
-
112719
- // src/utils/internal/error-handler/errorHandler.ts
112720
- class ErrorHandler {
112721
- static determineErrorCode(error48) {
112722
- if (error48 instanceof McpError) {
112723
- return error48.code;
112724
- }
112725
- const errorName = getErrorName(error48);
112726
- const errorMessage = getErrorMessage(error48);
112727
- const mappedFromType = ERROR_TYPE_MAPPINGS[errorName];
112728
- if (mappedFromType) {
112729
- return mappedFromType;
112730
- }
112731
- for (const mapping of COMMON_ERROR_PATTERNS) {
112732
- const regex = createSafeRegex(mapping.pattern);
112733
- if (regex.test(errorMessage) || regex.test(errorName)) {
112734
- return mapping.errorCode;
112735
- }
112736
- }
112737
- if (typeof error48 === "object" && error48 !== null && "name" in error48 && error48.name === "AbortError") {
112738
- return -32004 /* Timeout */;
112739
- }
112740
- return -32603 /* InternalError */;
112741
- }
112742
- static handleError(error48, options) {
112743
- const activeSpan = import_api3.trace.getActiveSpan();
112744
- if (activeSpan) {
112745
- if (error48 instanceof Error) {
112746
- activeSpan.recordException(error48);
112747
- }
112748
- activeSpan.setStatus({
112749
- code: import_api3.SpanStatusCode.ERROR,
112750
- message: error48 instanceof Error ? error48.message : String(error48)
112751
- });
112752
- }
112753
- const {
112754
- context = {},
112755
- operation,
112756
- input,
112757
- rethrow = false,
112758
- errorCode: explicitErrorCode,
112759
- includeStack = true,
112760
- critical = false,
112761
- errorMapper
112762
- } = options;
112763
- const sanitizedInput = input !== undefined ? sanitizeInputForLogging(input) : undefined;
112764
- const originalErrorName = getErrorName(error48);
112765
- const originalErrorMessage = getErrorMessage(error48);
112766
- const originalStack = error48 instanceof Error ? error48.stack : undefined;
112767
- let finalError;
112768
- let loggedErrorCode;
112769
- const errorDataSeed = error48 instanceof McpError && typeof error48.data === "object" && error48.data !== null ? { ...error48.data } : {};
112770
- const consolidatedData = {
112771
- ...errorDataSeed,
112772
- ...context,
112773
- originalErrorName,
112774
- originalMessage: originalErrorMessage
112775
- };
112776
- if (originalStack && !(error48 instanceof McpError && error48.data?.originalStack)) {
112777
- consolidatedData.originalStack = originalStack;
112778
- }
112779
- const cause = error48 instanceof Error ? error48 : undefined;
112780
- const rootCause = (() => {
112781
- let current = cause;
112782
- let depth = 0;
112783
- while (current && current instanceof Error && current.cause && depth < 5) {
112784
- current = current.cause;
112785
- depth += 1;
112786
- }
112787
- return current instanceof Error ? { name: current.name, message: current.message } : undefined;
112788
- })();
112789
- if (rootCause) {
112790
- consolidatedData["rootCause"] = rootCause;
112791
- }
112792
- if (error48 instanceof McpError) {
112793
- loggedErrorCode = error48.code;
112794
- finalError = errorMapper ? errorMapper(error48) : new McpError(error48.code, error48.message, consolidatedData, {
112795
- cause
112796
- });
112797
- } else {
112798
- loggedErrorCode = explicitErrorCode || ErrorHandler.determineErrorCode(error48);
112799
- const message = `Error in ${operation}: ${originalErrorMessage}`;
112800
- finalError = errorMapper ? errorMapper(error48) : new McpError(loggedErrorCode, message, consolidatedData, {
112801
- cause
112802
- });
112803
- }
112804
- if (finalError !== error48 && error48 instanceof Error && finalError instanceof Error && !finalError.stack && error48.stack) {
112805
- finalError.stack = error48.stack;
112806
- }
112807
- const logRequestId = typeof context.requestId === "string" && context.requestId ? context.requestId : generateUUID();
112808
- const logTimestamp = typeof context.timestamp === "string" && context.timestamp ? context.timestamp : new Date().toISOString();
112809
- const stack = finalError instanceof Error ? finalError.stack : originalStack;
112810
- const logContext = {
112811
- requestId: logRequestId,
112812
- timestamp: logTimestamp,
112813
- operation,
112814
- input: sanitizedInput,
112815
- critical,
112816
- errorCode: loggedErrorCode,
112817
- originalErrorType: originalErrorName,
112818
- finalErrorType: getErrorName(finalError),
112819
- ...Object.fromEntries(Object.entries(context).filter(([key]) => key !== "requestId" && key !== "timestamp")),
112820
- errorData: finalError instanceof McpError && finalError.data ? finalError.data : consolidatedData,
112821
- ...includeStack && stack ? { stack } : {}
112822
- };
112823
- logger.error(`Error in ${operation}: ${finalError.message || originalErrorMessage}`, logContext);
112824
- if (rethrow) {
112825
- throw finalError;
112826
- }
112827
- return finalError;
112828
- }
112829
- static mapError(error48, mappings, defaultFactory) {
112830
- const errorMessage = getErrorMessage(error48);
112831
- const errorName = getErrorName(error48);
112832
- for (const mapping of mappings) {
112833
- const regex = createSafeRegex(mapping.pattern);
112834
- if (regex.test(errorMessage) || regex.test(errorName)) {
112835
- return mapping.factory(error48, mapping.additionalContext);
112836
- }
112837
- }
112838
- if (defaultFactory) {
112839
- return defaultFactory(error48);
112840
- }
112841
- return error48 instanceof Error ? error48 : new Error(String(error48));
112842
- }
112843
- static formatError(error48) {
112844
- if (error48 instanceof McpError) {
112845
- return {
112846
- code: error48.code,
112847
- message: error48.message,
112848
- data: typeof error48.data === "object" && error48.data !== null ? error48.data : {}
112849
- };
112850
- }
112851
- if (error48 instanceof Error) {
112852
- return {
112853
- code: ErrorHandler.determineErrorCode(error48),
112854
- message: error48.message,
112855
- data: { errorType: error48.name || "Error" }
112856
- };
112857
- }
112858
- return {
112859
- code: -32099 /* UnknownError */,
112860
- message: getErrorMessage(error48),
112861
- data: { errorType: getErrorName(error48) }
112862
- };
112863
- }
112864
- static async tryCatch(fn, options) {
112865
- try {
112866
- return await Promise.resolve(fn());
112867
- } catch (caughtError) {
112868
- throw ErrorHandler.handleError(caughtError, {
112869
- ...options,
112870
- rethrow: true
112871
- });
112872
- }
112873
- }
112874
- }
112875
- var import_api3;
112876
- var init_errorHandler = __esm(() => {
112877
- init_errors3();
112878
- init_utils();
112879
- init_logger();
112880
- init_mappings();
112881
- import_api3 = __toESM(require_src(), 1);
112882
- });
112883
-
112884
- // src/utils/internal/error-handler/index.ts
112885
- var init_error_handler = __esm(() => {
112886
- init_errorHandler();
112887
- });
112888
-
112889
- // src/utils/internal/runtime.ts
112890
- function detectRuntime() {
112891
- if (runtimeCaps.isBun) {
112892
- return "bun";
112893
- }
112894
- if (runtimeCaps.isNode) {
112895
- return "node";
112896
- }
112897
- if (runtimeCaps.isWorkerLike) {
112898
- return "worker";
112899
- }
112900
- if (runtimeCaps.isBrowserLike) {
112901
- return "browser";
112902
- }
112903
- return "unknown";
112904
- }
112905
- function getRuntimeDescription() {
112906
- const runtime = detectRuntime();
112907
- switch (runtime) {
112908
- case "bun":
112909
- return `Bun ${process.versions?.bun || "unknown"}`;
112910
- case "node":
112911
- return `Node.js ${process.versions?.node || "unknown"}`;
112912
- case "worker":
112913
- return "Cloudflare Workers / Web Worker";
112914
- case "browser":
112915
- return "Browser";
112916
- default:
112917
- return "Unknown runtime";
112918
- }
112919
- }
112920
- var safeHas = (key) => {
112921
- try {
112922
- return typeof globalThis[key] !== "undefined";
112923
- } catch {
112924
- return false;
112925
- }
112926
- }, isBun, isNode, hasProcess, hasBuffer, hasTextEncoder, hasPerformanceNow, isWorkerLike, isBrowserLike, runtimeCaps;
112927
- var init_runtime = __esm(() => {
112928
- isBun = typeof globalThis.Bun !== "undefined" || typeof process.versions?.bun === "string";
112929
- isNode = !isBun && typeof process !== "undefined" && typeof process.versions?.node === "string";
112930
- hasProcess = typeof process !== "undefined";
112931
- hasBuffer = typeof Buffer !== "undefined";
112932
- hasTextEncoder = safeHas("TextEncoder");
112933
- hasPerformanceNow = typeof globalThis.performance?.now === "function";
112934
- isWorkerLike = !isNode && !isBun && typeof globalThis.WorkerGlobalScope !== "undefined";
112935
- isBrowserLike = !isNode && !isBun && !isWorkerLike && safeHas("window");
112936
- runtimeCaps = {
112937
- isNode,
112938
- isBun,
112939
- isWorkerLike,
112940
- isBrowserLike,
112941
- hasProcess,
112942
- hasBuffer,
112943
- hasTextEncoder,
112944
- hasPerformanceNow
112945
- };
112946
- });
112947
-
112948
- // src/utils/internal/health.ts
112949
- function getHealthSnapshot() {
112950
- return {
112951
- app: {
112952
- name: config2.mcpServerName,
112953
- version: config2.mcpServerVersion,
112954
- environment: config2.environment
112955
- },
112956
- runtime: {
112957
- isNode: runtimeCaps.isNode,
112958
- isWorkerLike: runtimeCaps.isWorkerLike,
112959
- isBrowserLike: runtimeCaps.isBrowserLike
112960
- },
112961
- telemetry: {
112962
- enabled: Boolean(config2.openTelemetry.enabled),
112963
- diagLevel: config2.openTelemetry.logLevel
112964
- },
112965
- logging: {
112966
- initialized: logger.isInitialized()
112967
- }
112968
- };
112969
- }
112970
- var init_health = __esm(() => {
112971
- init_config();
112972
- init_logger();
112973
- init_runtime();
112974
- });
112975
-
112976
- // src/utils/telemetry/semconv.ts
112977
- 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";
112978
-
112979
- // src/utils/internal/performance.ts
112980
- async function loadPerfHooks() {
112981
- return import("perf_hooks");
112982
- }
112983
- async function initializePerformance_Hrt() {
112984
- const globalWithPerf = globalThis;
112985
- if (typeof globalWithPerf.performance?.now === "function") {
112986
- const perf = globalWithPerf.performance;
112987
- performanceNow = () => perf?.now() ?? Date.now();
112988
- } else {
112989
- try {
112990
- const { performance: nodePerformance } = await loadPerfHooks();
112991
- performanceNow = () => nodePerformance.now();
112992
- } catch (_e) {
112993
- performanceNow = () => Date.now();
112994
- logger.warning("Could not import perf_hooks, falling back to Date.now() for performance timing.");
112995
- }
112996
- }
112997
- }
112998
- async function measureToolExecution(toolLogicFn, context, inputPayload) {
112999
- const tracer = import_api4.trace.getTracer(config2.openTelemetry.serviceName, config2.openTelemetry.serviceVersion);
113000
- const { toolName } = context;
113001
- return tracer.startActiveSpan(`tool_execution:${toolName}`, async (span) => {
113002
- const memBefore = typeof process !== "undefined" && typeof process.memoryUsage === "function" ? process.memoryUsage() : { rss: 0, heapUsed: 0 };
113003
- const t0 = nowMs();
113004
- span.setAttributes({
113005
- [ATTR_CODE_FUNCTION]: toolName,
113006
- [ATTR_CODE_NAMESPACE]: "mcp-tools",
113007
- [ATTR_MCP_TOOL_INPUT_BYTES]: toBytes(inputPayload),
113008
- [ATTR_MCP_TOOL_MEMORY_RSS_BEFORE]: memBefore.rss,
113009
- [ATTR_MCP_TOOL_MEMORY_HEAP_USED_BEFORE]: memBefore.heapUsed
113010
- });
113011
- let ok = false;
113012
- let errorCode;
113013
- let output;
113014
- try {
113015
- const result = await toolLogicFn();
113016
- ok = true;
113017
- output = result;
113018
- span.setStatus({ code: import_api4.SpanStatusCode.OK });
113019
- span.setAttribute(ATTR_MCP_TOOL_OUTPUT_BYTES, toBytes(output));
113020
- return result;
113021
- } catch (err) {
113022
- if (err instanceof McpError)
113023
- errorCode = String(err.code);
113024
- else if (err instanceof Error)
113025
- errorCode = "UNHANDLED_ERROR";
113026
- else
113027
- errorCode = "UNKNOWN_ERROR";
113028
- if (err instanceof Error)
113029
- span.recordException(err);
113030
- span.setStatus({
113031
- code: import_api4.SpanStatusCode.ERROR,
113032
- message: err instanceof Error ? err.message : String(err)
113033
- });
113034
- throw err;
113035
- } finally {
113036
- const t1 = nowMs();
113037
- const durationMs = Number((t1 - t0).toFixed(2));
113038
- const memAfter = typeof process !== "undefined" && typeof process.memoryUsage === "function" ? process.memoryUsage() : { rss: 0, heapUsed: 0 };
113039
- const rssDelta = memAfter.rss - memBefore.rss;
113040
- const heapUsedDelta = memAfter.heapUsed - memBefore.heapUsed;
113041
- span.setAttributes({
113042
- [ATTR_MCP_TOOL_DURATION_MS]: durationMs,
113043
- [ATTR_MCP_TOOL_SUCCESS]: ok,
113044
- [ATTR_MCP_TOOL_MEMORY_RSS_AFTER]: memAfter.rss,
113045
- [ATTR_MCP_TOOL_MEMORY_HEAP_USED_AFTER]: memAfter.heapUsed,
113046
- [ATTR_MCP_TOOL_MEMORY_RSS_DELTA]: rssDelta,
113047
- [ATTR_MCP_TOOL_MEMORY_HEAP_USED_DELTA]: heapUsedDelta
113048
- });
113049
- if (errorCode)
113050
- span.setAttribute(ATTR_MCP_TOOL_ERROR_CODE, errorCode);
113051
- span.end();
113052
- logger.info("Tool execution finished.", {
113053
- ...context,
113054
- metrics: {
113055
- durationMs,
113056
- isSuccess: ok,
113057
- errorCode,
113058
- inputBytes: toBytes(inputPayload),
113059
- outputBytes: toBytes(output),
113060
- memory: {
113061
- rss: {
113062
- before: memBefore.rss,
113063
- after: memAfter.rss,
113064
- delta: rssDelta
113065
- },
113066
- heapUsed: {
113067
- before: memBefore.heapUsed,
113068
- after: memAfter.heapUsed,
113069
- delta: heapUsedDelta
113070
- }
113071
- }
113072
- }
113073
- });
113074
- }
113075
- });
113076
- }
113077
- var import_api4, performanceNow = () => Date.now(), nowMs = () => performanceNow(), toBytes = (payload) => {
113078
- if (payload == null)
113079
- return 0;
113080
- try {
113081
- const json2 = JSON.stringify(payload);
113082
- if (typeof Buffer !== "undefined" && typeof Buffer.byteLength === "function") {
113083
- const bytes = Buffer.byteLength(json2, "utf8");
113084
- return bytes;
113085
- }
113086
- if (typeof TextEncoder !== "undefined") {
113087
- return new TextEncoder().encode(json2).length;
113088
- }
113089
- return json2.length;
113090
- } catch {
113091
- return 0;
113092
- }
113093
- };
113094
- var init_performance = __esm(() => {
113095
- init_config();
113096
- init_errors3();
113097
- init_logger();
113098
- import_api4 = __toESM(require_src(), 1);
113099
- });
113100
-
113101
- // src/utils/internal/startupBanner.ts
113102
- function logStartupBanner(message, transportType) {
113103
- if (process.stdout.isTTY) {
113104
- if (transportType === "stdio") {
113105
- console.error(message);
113106
- } else {
113107
- console.log(message);
113108
- }
113109
- }
113110
- }
113111
-
113112
- // src/utils/internal/index.ts
113113
- var init_internal = __esm(() => {
113114
- init_error_handler();
113115
- init_health();
113116
- init_logger();
113117
- init_performance();
113118
- init_requestContext();
113119
- init_runtime();
113120
- });
113121
-
113122
- // src/utils/metrics/tokenCounter.ts
113123
- function getModelHeuristics(model) {
113124
- const key = (model ?? DEFAULT_MODEL).toLowerCase();
113125
- const found = HEURISTICS[key];
113126
- return found ?? HEURISTICS.default;
113127
- }
113128
- function nonEmptyString(s2) {
113129
- return typeof s2 === "string" && s2.length > 0;
113130
- }
113131
- function approxTokenCount(text, charsPerToken) {
113132
- if (!text)
113133
- return 0;
113134
- const normalized = text.replace(/\s+/g, " ").trim();
113135
- if (!normalized)
113136
- return 0;
113137
- return Math.ceil(normalized.length / Math.max(1, charsPerToken));
113138
- }
113139
- async function countTokens(text, context, model) {
113140
- return ErrorHandler.tryCatch(() => {
113141
- const h2 = getModelHeuristics(model);
113142
- return approxTokenCount(text ?? "", h2.charsPerToken);
113143
- }, {
113144
- operation: "countTokens",
113145
- ...context && { context },
113146
- input: {
113147
- textSample: nonEmptyString(text) ? text.length > 53 ? `${text.slice(0, 50)}...` : text : ""
113148
- },
113149
- errorCode: -32603 /* InternalError */
113150
- });
113151
- }
113152
- async function countChatTokens(messages, context, model) {
113153
- return ErrorHandler.tryCatch(() => {
113154
- const h2 = getModelHeuristics(model);
113155
- let tokens = 0;
113156
- for (const message of messages) {
113157
- tokens += h2.tokensPerMessage;
113158
- tokens += 1;
113159
- if (typeof message.content === "string") {
113160
- tokens += approxTokenCount(message.content, h2.charsPerToken);
113161
- } else if (Array.isArray(message.content)) {
113162
- for (const part of message.content) {
113163
- if (part && part.type === "text" && nonEmptyString(part.text)) {
113164
- tokens += approxTokenCount(part.text, h2.charsPerToken);
113165
- } else if (part) {
113166
- logger.warning(`Non-text content part found (type: ${String(part.type)}), token count contribution ignored.`, context);
113167
- }
113168
- }
113169
- }
113170
- if (message.name) {
113171
- tokens += h2.tokensPerName;
113172
- tokens += approxTokenCount(message.name, h2.charsPerToken);
113173
- }
113174
- if (message.role === "assistant" && Array.isArray(message.tool_calls)) {
113175
- for (const toolCall of message.tool_calls) {
113176
- if (toolCall?.type === "function") {
113177
- if (toolCall.function?.name) {
113178
- tokens += approxTokenCount(toolCall.function.name, h2.charsPerToken);
113179
- }
113180
- if (toolCall.function?.arguments) {
113181
- tokens += approxTokenCount(toolCall.function.arguments, h2.charsPerToken);
113182
- }
113183
- }
113184
- }
113185
- }
113186
- if (message.role === "tool" && message.tool_call_id) {
113187
- tokens += approxTokenCount(message.tool_call_id, h2.charsPerToken);
113188
- }
113189
- }
113190
- tokens += h2.replyPrimer;
113191
- return tokens;
113192
- }, {
113193
- operation: "countChatTokens",
113194
- ...context && { context },
113195
- input: { messageCount: messages.length },
113196
- errorCode: -32603 /* InternalError */
113197
- });
113198
- }
113199
- var DEFAULT_MODEL = "gpt-4o", HEURISTICS;
113200
- var init_tokenCounter = __esm(() => {
113201
- init_utils();
113202
- HEURISTICS = {
113203
- "gpt-4o": {
113204
- charsPerToken: 4,
113205
- tokensPerMessage: 3,
113206
- tokensPerName: 1,
113207
- replyPrimer: 3
113208
- },
113209
- "gpt-4o-mini": {
113210
- charsPerToken: 4,
113211
- tokensPerMessage: 3,
113212
- tokensPerName: 1,
113213
- replyPrimer: 3
113214
- },
113215
- default: {
113216
- charsPerToken: 4,
113217
- tokensPerMessage: 3,
113218
- tokensPerName: 1,
113219
- replyPrimer: 3
113220
- }
113221
- };
113222
- });
113223
-
113224
- // src/utils/metrics/registry.ts
113225
- function getMeter() {
113226
- return import_api5.metrics.getMeter(config2.openTelemetry.serviceName, config2.openTelemetry.serviceVersion);
113227
- }
113228
- function isEnabled() {
113229
- return Boolean(config2.openTelemetry.enabled);
113230
- }
113231
- function getCounter(name, description, unit) {
113232
- if (!isEnabled()) {
113233
- return {
113234
- add: () => {
113235
- return;
113236
- },
113237
- bind: () => ({ add: () => {
113238
- return;
113239
- } }),
113240
- unbind: () => {
113241
- return;
113242
- }
113243
- };
113244
- }
113245
- const key = `${name}|${description ?? ""}|${unit ?? ""}`;
113246
- const existing = counters.get(key);
113247
- if (existing)
113248
- return existing;
113249
- const opts = {};
113250
- if (description !== undefined)
113251
- opts.description = description;
113252
- if (unit !== undefined)
113253
- opts.unit = unit;
113254
- const counter = Object.keys(opts).length ? getMeter().createCounter(name, opts) : getMeter().createCounter(name);
113255
- counters.set(key, counter);
113256
- return counter;
113257
- }
113258
- function getHistogram(name, description, unit) {
113259
- if (!isEnabled()) {
113260
- return {
113261
- record: () => {
113262
- return;
113263
- },
113264
- bind: () => ({ record: () => {
113265
- return;
113266
- } }),
113267
- unbind: () => {
113268
- return;
113269
- }
113270
- };
113271
- }
113272
- const key = `${name}|${description ?? ""}|${unit ?? ""}`;
113273
- const existing = histograms.get(key);
113274
- if (existing)
113275
- return existing;
113276
- const opts = {};
113277
- if (description !== undefined)
113278
- opts.description = description;
113279
- if (unit !== undefined)
113280
- opts.unit = unit;
113281
- const histogram = Object.keys(opts).length ? getMeter().createHistogram(name, opts) : getMeter().createHistogram(name);
113282
- histograms.set(key, histogram);
113283
- return histogram;
113284
- }
113285
- function add(name, value, attributes, description, unit) {
113286
- const c = getCounter(name, description, unit);
113287
- c.add(value, attributes);
113288
- }
113289
- function record2(name, value, attributes, description, unit) {
113290
- const h2 = getHistogram(name, description, unit);
113291
- h2.record(value, attributes);
113292
- }
113293
- var import_api5, counters, histograms, metricsRegistry;
113294
- var init_registry = __esm(() => {
113295
- init_config();
113296
- import_api5 = __toESM(require_src(), 1);
113297
- counters = new Map;
113298
- histograms = new Map;
113299
- metricsRegistry = {
113300
- getCounter,
113301
- getHistogram,
113302
- add,
113303
- record: record2,
113304
- enabled: isEnabled
113305
- };
113306
- });
113307
-
113308
- // src/utils/metrics/index.ts
113309
- var init_metrics = __esm(() => {
113310
- init_tokenCounter();
113311
- init_registry();
113312
- });
113313
-
113314
- // src/utils/security/idGenerator.ts
113315
- import { randomUUID as cryptoRandomUUID, randomBytes } from "crypto";
113316
-
113317
- class IdGenerator {
113318
- static DEFAULT_CHARSET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
113319
- static DEFAULT_SEPARATOR = "_";
113320
- static DEFAULT_LENGTH = 6;
113321
- entityPrefixes = {};
113322
- prefixToEntityType = {};
113323
- constructor(entityPrefixes = {}) {
113324
- this.setEntityPrefixes(entityPrefixes);
113325
- }
113326
- setEntityPrefixes(entityPrefixes) {
113327
- this.entityPrefixes = { ...entityPrefixes };
113328
- this.prefixToEntityType = Object.entries(this.entityPrefixes).reduce((acc, [type, prefix]) => {
113329
- acc[prefix.toLowerCase()] = type;
113330
- return acc;
113331
- }, {});
113332
- }
113333
- getEntityPrefixes() {
113334
- return { ...this.entityPrefixes };
113335
- }
113336
- generateRandomString(length = IdGenerator.DEFAULT_LENGTH, charset = IdGenerator.DEFAULT_CHARSET) {
113337
- let result = "";
113338
- const maxValidByteValue = Math.floor(256 / charset.length) * charset.length;
113339
- while (result.length < length) {
113340
- const byteBuffer = randomBytes(1);
113341
- const byte = byteBuffer[0];
113342
- if (byte !== undefined && byte < maxValidByteValue) {
113343
- const charIndex = byte % charset.length;
113344
- const char = charset[charIndex];
113345
- if (char) {
113346
- result += char;
113347
- }
113348
- }
113349
- }
113350
- return result;
113351
- }
113352
- generate(prefix, options = {}) {
113353
- const {
113354
- length = IdGenerator.DEFAULT_LENGTH,
113355
- separator = IdGenerator.DEFAULT_SEPARATOR,
113356
- charset = IdGenerator.DEFAULT_CHARSET
113357
- } = options;
113358
- const randomPart = this.generateRandomString(length, charset);
113359
- const generatedId = prefix ? `${prefix}${separator}${randomPart}` : randomPart;
113360
- return generatedId;
113361
- }
113362
- generateForEntity(entityType, options = {}) {
113363
- const prefix = this.entityPrefixes[entityType];
113364
- if (!prefix) {
113365
- throw new McpError(-32007 /* ValidationError */, `Unknown entity type: ${entityType}. No prefix registered.`);
113366
- }
113367
- return this.generate(prefix, options);
113368
- }
113369
- isValid(id, entityType, options = {}) {
113370
- const prefix = this.entityPrefixes[entityType];
113371
- const {
113372
- length = IdGenerator.DEFAULT_LENGTH,
113373
- separator = IdGenerator.DEFAULT_SEPARATOR,
113374
- charset = IdGenerator.DEFAULT_CHARSET
113375
- } = options;
113376
- if (!prefix) {
113377
- return false;
113378
- }
113379
- const escapedCharsetForClass = charset.replace(/[[\]\\^-]/g, "\\$&");
113380
- const charsetRegexPart = `[${escapedCharsetForClass}]`;
113381
- const pattern = new RegExp(`^${this.escapeRegex(prefix)}${this.escapeRegex(separator)}${charsetRegexPart}{${length}}$`);
113382
- return pattern.test(id);
113383
- }
113384
- escapeRegex(str) {
113385
- return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
113386
- }
113387
- stripPrefix(id, separator = IdGenerator.DEFAULT_SEPARATOR) {
113388
- const parts = id.split(separator);
113389
- return parts.length > 1 ? parts.slice(1).join(separator) : id;
113390
- }
113391
- getEntityType(id, separator = IdGenerator.DEFAULT_SEPARATOR) {
113392
- const parts = id.split(separator);
113393
- if (parts.length < 2 || !parts[0]) {
113394
- throw new McpError(-32007 /* ValidationError */, `Invalid ID format: ${id}. Expected format like: PREFIX${separator}RANDOMLPART`);
113395
- }
113396
- const prefix = parts[0];
113397
- const entityType = this.prefixToEntityType[prefix.toLowerCase()];
113398
- if (!entityType) {
113399
- throw new McpError(-32007 /* ValidationError */, `Unknown entity type for prefix: ${prefix}`);
113400
- }
113401
- return entityType;
113402
- }
113403
- normalize(id, separator = IdGenerator.DEFAULT_SEPARATOR) {
113404
- const entityType = this.getEntityType(id, separator);
113405
- const registeredPrefix = this.entityPrefixes[entityType];
113406
- const idParts = id.split(separator);
113407
- const randomPart = idParts.slice(1).join(separator);
113408
- return `${registeredPrefix}${separator}${randomPart.toUpperCase()}`;
113409
- }
113410
- }
113411
- var idGenerator, generateUUID = () => {
113412
- return cryptoRandomUUID();
113413
- }, generateRequestContextId = () => {
113414
- const generateSecureRandomString = (length, charset2) => {
113415
- let result = "";
113416
- const maxValidByteValue = Math.floor(256 / charset2.length) * charset2.length;
113417
- while (result.length < length) {
113418
- const byteBuffer = randomBytes(1);
113419
- const byte = byteBuffer[0];
113420
- if (byte !== undefined && byte < maxValidByteValue) {
113421
- const charIndex = byte % charset2.length;
113422
- const char = charset2[charIndex];
113423
- if (char) {
113424
- result += char;
113425
- }
113426
- }
113427
- }
113428
- return result;
113429
- };
113430
- const charset = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
113431
- const part1 = generateSecureRandomString(5, charset);
113432
- const part2 = generateSecureRandomString(5, charset);
113433
- return `${part1}-${part2}`;
113434
- };
113435
- var init_idGenerator = __esm(() => {
113436
- init_errors3();
113437
- idGenerator = new IdGenerator;
113438
- });
113439
-
113440
111980
  // node_modules/tsyringe/node_modules/tslib/tslib.js
113441
111981
  var require_tslib = __commonJS((exports, module) => {
113442
111982
  /*! *****************************************************************************
@@ -114582,7 +113122,7 @@ var require_registry2 = __commonJS((exports) => {
114582
113122
  Object.defineProperty(exports, "__esModule", { value: true });
114583
113123
  var tslib_1 = require_tslib();
114584
113124
  var dependency_container_1 = require_dependency_container();
114585
- function registry3(registrations = []) {
113125
+ function registry2(registrations = []) {
114586
113126
  return function(target) {
114587
113127
  registrations.forEach((_a2) => {
114588
113128
  var { token, options } = _a2, provider = tslib_1.__rest(_a2, ["token", "options"]);
@@ -114591,7 +113131,7 @@ var require_registry2 = __commonJS((exports) => {
114591
113131
  return target;
114592
113132
  };
114593
113133
  }
114594
- exports.default = registry3;
113134
+ exports.default = registry2;
114595
113135
  });
114596
113136
 
114597
113137
  // node_modules/tsyringe/dist/cjs/decorators/singleton.js
@@ -114835,195 +113375,6 @@ var init_tokens = __esm(() => {
114835
113375
  GitProviderFactory = Symbol("GitProviderFactory");
114836
113376
  });
114837
113377
 
114838
- // src/utils/security/rateLimiter.ts
114839
- var import_api6, import_tsyringe, RateLimiter;
114840
- var init_rateLimiter = __esm(() => {
114841
- init_tokens();
114842
- init_errors3();
114843
- init_utils();
114844
- import_api6 = __toESM(require_src(), 1);
114845
- import_tsyringe = __toESM(require_cjs2(), 1);
114846
- RateLimiter = class RateLimiter {
114847
- config;
114848
- logger;
114849
- limits;
114850
- cleanupTimer = null;
114851
- effectiveConfig;
114852
- constructor(config3, logger3) {
114853
- this.config = config3;
114854
- this.logger = logger3;
114855
- const defaultConfig = {
114856
- windowMs: 15 * 60 * 1000,
114857
- maxRequests: 100,
114858
- errorMessage: "Rate limit exceeded. Please try again in {waitTime} seconds.",
114859
- skipInDevelopment: false,
114860
- cleanupInterval: 5 * 60 * 1000
114861
- };
114862
- this.effectiveConfig = { ...defaultConfig };
114863
- this.limits = new Map;
114864
- this.startCleanupTimer();
114865
- }
114866
- startCleanupTimer() {
114867
- if (this.cleanupTimer) {
114868
- clearInterval(this.cleanupTimer);
114869
- }
114870
- const interval = this.effectiveConfig.cleanupInterval;
114871
- if (interval && interval > 0) {
114872
- this.cleanupTimer = setInterval(() => {
114873
- this.cleanupExpiredEntries();
114874
- }, interval);
114875
- if (this.cleanupTimer.unref) {
114876
- this.cleanupTimer.unref();
114877
- }
114878
- }
114879
- }
114880
- cleanupExpiredEntries() {
114881
- const now = Date.now();
114882
- let expiredCount = 0;
114883
- for (const [key, entry] of this.limits.entries()) {
114884
- if (now >= entry.resetTime) {
114885
- this.limits.delete(key);
114886
- expiredCount++;
114887
- }
114888
- }
114889
- if (expiredCount > 0) {
114890
- const logContext = requestContextService.createRequestContext({
114891
- operation: "RateLimiter.cleanupExpiredEntries",
114892
- additionalContext: {
114893
- cleanedCount: expiredCount,
114894
- totalRemainingAfterClean: this.limits.size
114895
- }
114896
- });
114897
- this.logger.debug(`Cleaned up ${expiredCount} expired rate limit entries`, logContext);
114898
- }
114899
- }
114900
- configure(config3) {
114901
- Object.assign(this.effectiveConfig, config3);
114902
- if (config3.cleanupInterval !== undefined) {
114903
- this.startCleanupTimer();
114904
- }
114905
- }
114906
- getConfig() {
114907
- return { ...this.effectiveConfig };
114908
- }
114909
- reset() {
114910
- this.limits.clear();
114911
- const logContext = requestContextService.createRequestContext({
114912
- operation: "RateLimiter.reset"
114913
- });
114914
- this.logger.debug("Rate limiter reset, all limits cleared", logContext);
114915
- }
114916
- check(key, context) {
114917
- const activeSpan = import_api6.trace.getActiveSpan();
114918
- activeSpan?.setAttribute("mcp.rate_limit.checked", true);
114919
- if (this.effectiveConfig.skipInDevelopment && this.config.environment === "development") {
114920
- activeSpan?.setAttribute("mcp.rate_limit.skipped", "development");
114921
- return;
114922
- }
114923
- const limitKey = this.effectiveConfig.keyGenerator ? this.effectiveConfig.keyGenerator(key, context) : key;
114924
- activeSpan?.setAttribute("mcp.rate_limit.key", limitKey);
114925
- const now = Date.now();
114926
- let entry = this.limits.get(limitKey);
114927
- if (!entry || now >= entry.resetTime) {
114928
- entry = {
114929
- count: 1,
114930
- resetTime: now + this.effectiveConfig.windowMs
114931
- };
114932
- this.limits.set(limitKey, entry);
114933
- } else {
114934
- entry.count++;
114935
- }
114936
- const remaining = Math.max(0, this.effectiveConfig.maxRequests - entry.count);
114937
- activeSpan?.setAttributes({
114938
- "mcp.rate_limit.limit": this.effectiveConfig.maxRequests,
114939
- "mcp.rate_limit.count": entry.count,
114940
- "mcp.rate_limit.remaining": remaining
114941
- });
114942
- if (entry.count > this.effectiveConfig.maxRequests) {
114943
- const waitTime = Math.ceil((entry.resetTime - now) / 1000);
114944
- const errorMessage = (this.effectiveConfig.errorMessage || "Rate limit exceeded. Please try again in {waitTime} seconds.").replace("{waitTime}", waitTime.toString());
114945
- activeSpan?.addEvent("rate_limit_exceeded", {
114946
- "mcp.rate_limit.wait_time_seconds": waitTime
114947
- });
114948
- throw new McpError(-32003 /* RateLimited */, errorMessage, {
114949
- waitTimeSeconds: waitTime,
114950
- key: limitKey,
114951
- limit: this.effectiveConfig.maxRequests,
114952
- windowMs: this.effectiveConfig.windowMs
114953
- });
114954
- }
114955
- }
114956
- getStatus(key) {
114957
- const entry = this.limits.get(key);
114958
- if (!entry)
114959
- return null;
114960
- return {
114961
- current: entry.count,
114962
- limit: this.effectiveConfig.maxRequests,
114963
- remaining: Math.max(0, this.effectiveConfig.maxRequests - entry.count),
114964
- resetTime: entry.resetTime
114965
- };
114966
- }
114967
- dispose() {
114968
- if (this.cleanupTimer) {
114969
- clearInterval(this.cleanupTimer);
114970
- this.cleanupTimer = null;
114971
- }
114972
- this.limits.clear();
114973
- }
114974
- };
114975
- RateLimiter = __legacyDecorateClassTS([
114976
- import_tsyringe.injectable(),
114977
- __legacyDecorateParamTS(0, import_tsyringe.inject(AppConfig)),
114978
- __legacyDecorateParamTS(1, import_tsyringe.inject(Logger2)),
114979
- __legacyMetadataTS("design:paramtypes", [
114980
- Object,
114981
- Object
114982
- ])
114983
- ], RateLimiter);
114984
- });
114985
-
114986
- // src/utils/security/index.ts
114987
- var init_security = __esm(() => {
114988
- init_idGenerator();
114989
- init_rateLimiter();
114990
- init_sanitization();
114991
- });
114992
-
114993
- // src/utils/index.ts
114994
- var exports_utils = {};
114995
- __export(exports_utils, {
114996
- sanitizeInputForLogging: () => sanitizeInputForLogging,
114997
- sanitization: () => sanitization,
114998
- runtimeCaps: () => runtimeCaps,
114999
- requestContextService: () => requestContextService,
115000
- nowMs: () => nowMs,
115001
- metricsRegistry: () => metricsRegistry,
115002
- measureToolExecution: () => measureToolExecution,
115003
- logger: () => logger,
115004
- logStartupBanner: () => logStartupBanner,
115005
- loadPerfHooks: () => loadPerfHooks,
115006
- initializePerformance_Hrt: () => initializePerformance_Hrt,
115007
- idGenerator: () => idGenerator,
115008
- getRuntimeDescription: () => getRuntimeDescription,
115009
- getHealthSnapshot: () => getHealthSnapshot,
115010
- generateUUID: () => generateUUID,
115011
- generateRequestContextId: () => generateRequestContextId,
115012
- detectRuntime: () => detectRuntime,
115013
- countTokens: () => countTokens,
115014
- countChatTokens: () => countChatTokens,
115015
- Sanitization: () => Sanitization,
115016
- RateLimiter: () => RateLimiter,
115017
- Logger: () => Logger,
115018
- IdGenerator: () => IdGenerator,
115019
- ErrorHandler: () => ErrorHandler
115020
- });
115021
- var init_utils = __esm(() => {
115022
- init_internal();
115023
- init_metrics();
115024
- init_security();
115025
- });
115026
-
115027
113378
  // node_modules/tslib/tslib.js
115028
113379
  var require_tslib2 = __commonJS((exports, module) => {
115029
113380
  var __extends;
@@ -116159,22 +114510,22 @@ var require_transformers = __commonJS((exports) => {
116159
114510
  PostgresTypes2["tsrange"] = "tsrange";
116160
114511
  PostgresTypes2["tstzrange"] = "tstzrange";
116161
114512
  })(PostgresTypes || (exports.PostgresTypes = PostgresTypes = {}));
116162
- var convertChangeData = (columns, record3, options = {}) => {
114513
+ var convertChangeData = (columns, record2, options = {}) => {
116163
114514
  var _a2;
116164
114515
  const skipTypes = (_a2 = options.skipTypes) !== null && _a2 !== undefined ? _a2 : [];
116165
- if (!record3) {
114516
+ if (!record2) {
116166
114517
  return {};
116167
114518
  }
116168
- return Object.keys(record3).reduce((acc, rec_key) => {
116169
- 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);
116170
114521
  return acc;
116171
114522
  }, {});
116172
114523
  };
116173
114524
  exports.convertChangeData = convertChangeData;
116174
- var convertColumn = (columnName, columns, record3, skipTypes) => {
114525
+ var convertColumn = (columnName, columns, record2, skipTypes) => {
116175
114526
  const column = columns.find((x2) => x2.name === columnName);
116176
114527
  const colType = column === null || column === undefined ? undefined : column.type;
116177
- const value = record3[columnName];
114528
+ const value = record2[columnName];
116178
114529
  if (colType && !skipTypes.includes(colType)) {
116179
114530
  return (0, exports.convertCell)(colType, value);
116180
114531
  }
@@ -127939,13 +126290,13 @@ var require_core = __commonJS((exports) => {
127939
126290
  return metaOpts;
127940
126291
  }
127941
126292
  var noLogs = { log() {}, warn() {}, error() {} };
127942
- function getLogger(logger3) {
127943
- if (logger3 === false)
126293
+ function getLogger(logger2) {
126294
+ if (logger2 === false)
127944
126295
  return noLogs;
127945
- if (logger3 === undefined)
126296
+ if (logger2 === undefined)
127946
126297
  return console;
127947
- if (logger3.log && logger3.warn && logger3.error)
127948
- return logger3;
126298
+ if (logger2.log && logger2.warn && logger2.error)
126299
+ return logger2;
127949
126300
  throw new Error("logger must implement log, warn and error methods");
127950
126301
  }
127951
126302
  var KEYWORD_NAME = /^[a-z_$][a-z0-9_$:-]*$/i;
@@ -130290,10 +128641,1377 @@ async function shutdownOpenTelemetry() {
130290
128641
  }
130291
128642
  }
130292
128643
 
130293
- // src/index.ts
130294
- init_utils();
130295
- init_logger();
130296
- 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);
130297
130015
 
130298
130016
  // src/container/index.ts
130299
130017
  var import_reflect_metadata = __toESM(require_Reflect(), 1);
@@ -132754,13 +132472,8 @@ if (shouldShowDeprecationWarning())
132754
132472
  init_config();
132755
132473
  init_tokens();
132756
132474
 
132757
- // src/services/git/core/GitProviderFactory.ts
132758
- init_utils();
132759
-
132760
132475
  // src/services/git/core/BaseGitProvider.ts
132761
132476
  init_errors3();
132762
- init_utils();
132763
-
132764
132477
  class BaseGitProvider {
132765
132478
  checkCapability(capability) {
132766
132479
  if (!this.capabilities[capability]) {
@@ -132794,12 +132507,12 @@ class BaseGitProvider {
132794
132507
  workingDirectory
132795
132508
  });
132796
132509
  }
132797
- createOperationContext(requestContext2, workingDirectory, tenantId) {
132510
+ createOperationContext(requestContext, workingDirectory, tenantId) {
132798
132511
  const context = {
132799
- requestContext: requestContext2,
132512
+ requestContext,
132800
132513
  workingDirectory
132801
132514
  };
132802
- const finalTenantId = tenantId || requestContext2.tenantId;
132515
+ const finalTenantId = tenantId || requestContext.tenantId;
132803
132516
  if (finalTenantId) {
132804
132517
  context.tenantId = finalTenantId;
132805
132518
  }
@@ -133185,8 +132898,8 @@ Stdout: ${stdout}`;
133185
132898
  });
133186
132899
  }
133187
132900
  async function spawnGitCommand(args, cwd, env, timeout = 60000, signal, allowNonZeroExit = false) {
133188
- const runtime2 = detectRuntime2();
133189
- if (runtime2 === "bun") {
132901
+ const runtime = detectRuntime2();
132902
+ if (runtime === "bun") {
133190
132903
  return spawnWithBun(args, cwd, env, timeout, signal, allowNonZeroExit);
133191
132904
  } else {
133192
132905
  return spawnWithNode(args, cwd, env, timeout, signal, allowNonZeroExit);
@@ -133258,6 +132971,15 @@ function parseGitStatus(output) {
133258
132971
  const parts2 = line.split(" ");
133259
132972
  if (parts2[1] === "branch.head" && parts2[2]) {
133260
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;
133261
132983
  }
133262
132984
  continue;
133263
132985
  }
@@ -133677,8 +133399,10 @@ async function executeCommit(options, context, execGit) {
133677
133399
  if (options.noVerify) {
133678
133400
  args.push("--no-verify");
133679
133401
  }
133680
- const shouldSign = options.sign ?? shouldSignCommits();
133681
- if (shouldSign) {
133402
+ const signRequested = shouldSignCommits();
133403
+ let signed = false;
133404
+ let signingWarning;
133405
+ if (signRequested) {
133682
133406
  args.push("--gpg-sign");
133683
133407
  }
133684
133408
  if (options.author) {
@@ -133688,17 +133412,20 @@ async function executeCommit(options, context, execGit) {
133688
133412
  const cmd = buildGitCommand({ command: "commit", args });
133689
133413
  try {
133690
133414
  await execGit(cmd, context.workingDirectory, context.requestContext);
133415
+ signed = signRequested;
133691
133416
  } catch (error48) {
133692
- if (shouldSign && options.forceUnsignedOnFailure) {
133693
- const unsignedArgs = args.filter((a) => a !== "--gpg-sign");
133694
- const unsignedCmd = buildGitCommand({
133695
- command: "commit",
133696
- args: unsignedArgs
133697
- });
133698
- await execGit(unsignedCmd, context.workingDirectory, context.requestContext);
133699
- } else {
133417
+ if (!signRequested) {
133700
133418
  throw error48;
133701
133419
  }
133420
+ const errorMessage = error48 instanceof Error ? error48.message : String(error48);
133421
+ logger.warning("Commit signing failed; retrying unsigned. Set GIT_SIGN_COMMITS=false to suppress this attempt.", { ...context.requestContext, error: error48 });
133422
+ signingWarning = `GIT_SIGN_COMMITS is enabled but signing failed; commit created unsigned. Check signing key availability (gpg-agent running, SSH key accessible). Underlying error: ${errorMessage}`;
133423
+ const unsignedArgs = args.filter((a) => a !== "--gpg-sign");
133424
+ const unsignedCmd = buildGitCommand({
133425
+ command: "commit",
133426
+ args: unsignedArgs
133427
+ });
133428
+ await execGit(unsignedCmd, context.workingDirectory, context.requestContext);
133702
133429
  }
133703
133430
  const hashCmd = buildGitCommand({
133704
133431
  command: "rev-parse",
@@ -133727,8 +133454,12 @@ async function executeCommit(options, context, execGit) {
133727
133454
  message: options.message,
133728
133455
  author: authorName,
133729
133456
  timestamp,
133730
- filesChanged
133457
+ filesChanged,
133458
+ signed
133731
133459
  };
133460
+ if (signingWarning) {
133461
+ result.signingWarning = signingWarning;
133462
+ }
133732
133463
  return result;
133733
133464
  } catch (error48) {
133734
133465
  throw mapGitError(error48, "commit");
@@ -133739,7 +133470,9 @@ var COMMIT_START_MARKER = "<<<COMMIT_START>>>";
133739
133470
  var COMMIT_END_MARKER = "<<<COMMIT_END>>>";
133740
133471
  async function executeLog(options, context, execGit) {
133741
133472
  try {
133742
- 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;
133743
133476
  const args = [`--format=${formatStr}`];
133744
133477
  if (options.maxCount) {
133745
133478
  args.push(`-n${options.maxCount}`);
@@ -133782,7 +133515,11 @@ async function executeLog(options, context, execGit) {
133782
133515
  const formatPart = section.substring(0, endIdx);
133783
133516
  const extraPart = section.substring(endIdx + COMMIT_END_MARKER.length).trim();
133784
133517
  const fields = formatPart.split(GIT_FIELD_DELIMITER);
133785
- const commit = {
133518
+ const commit = options.oneline ? {
133519
+ hash: fields[0] || "",
133520
+ shortHash: fields[1] || "",
133521
+ subject: fields[2] || ""
133522
+ } : {
133786
133523
  hash: fields[0] || "",
133787
133524
  shortHash: fields[1] || "",
133788
133525
  author: fields[2] || "",
@@ -133791,7 +133528,7 @@ async function executeLog(options, context, execGit) {
133791
133528
  subject: fields[5] || "",
133792
133529
  parents: (fields[7] || "").split(" ").filter((p) => p)
133793
133530
  };
133794
- if (fields[6]) {
133531
+ if (!options.oneline && fields[6]) {
133795
133532
  commit.body = fields[6];
133796
133533
  }
133797
133534
  if (extraPart) {
@@ -133839,11 +133576,13 @@ async function executeShow(options, context, execGit) {
133839
133576
  command: "cat-file",
133840
133577
  args: ["-t", options.object]
133841
133578
  });
133842
- 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
+ ]);
133843
133584
  const detectedType = typeResult.stdout.trim();
133844
133585
  const objectType = ["commit", "tree", "blob", "tag"].includes(detectedType) ? detectedType : "commit";
133845
- const cmd = buildGitCommand({ command: "show", args });
133846
- const result = await execGit(cmd, context.workingDirectory, context.requestContext);
133847
133586
  const showResult = {
133848
133587
  object: options.object,
133849
133588
  type: objectType,
@@ -134039,6 +133778,21 @@ async function executeBranch(options, context, execGit) {
134039
133778
  try {
134040
133779
  const args = [];
134041
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
+ }
134042
133796
  case "list": {
134043
133797
  const format = [
134044
133798
  "%(refname)",
@@ -134057,6 +133811,9 @@ async function executeBranch(options, context, execGit) {
134057
133811
  const noMergedRef = typeof options.noMerged === "string" ? options.noMerged : "HEAD";
134058
133812
  args.push(`--no-merged=${noMergedRef}`);
134059
133813
  }
133814
+ if (typeof options.limit === "number" && options.limit > 0) {
133815
+ args.push(`--count=${options.limit}`);
133816
+ }
134060
133817
  const cmd = buildGitCommand({ command: "for-each-ref", args });
134061
133818
  const result = await execGit(cmd, context.workingDirectory, context.requestContext);
134062
133819
  const branches = parseBranchRef(result.stdout);
@@ -134185,8 +133942,7 @@ async function executeMerge(options, context, execGit) {
134185
133942
  if (options.message) {
134186
133943
  args.push("-m", options.message);
134187
133944
  }
134188
- const shouldSign = options.sign ?? shouldSignCommits();
134189
- if (shouldSign) {
133945
+ if (shouldSignCommits()) {
134190
133946
  args.push("-S");
134191
133947
  }
134192
133948
  args.push(options.branch);
@@ -134283,8 +134039,7 @@ ${continueResult.stderr}`),
134283
134039
  if (options.preserve) {
134284
134040
  args.push("--preserve-merges");
134285
134041
  }
134286
- const shouldSign = options.sign ?? shouldSignCommits();
134287
- if (shouldSign) {
134042
+ if (shouldSignCommits()) {
134288
134043
  args.push("--gpg-sign");
134289
134044
  }
134290
134045
  if (options.onto) {
@@ -134366,8 +134121,7 @@ async function executeCherryPick(options, context, execGit) {
134366
134121
  if (options.signoff) {
134367
134122
  args.push("--signoff");
134368
134123
  }
134369
- const shouldSign = options.sign ?? shouldSignCommits();
134370
- if (shouldSign) {
134124
+ if (shouldSignCommits()) {
134371
134125
  args.push("--gpg-sign");
134372
134126
  }
134373
134127
  args.push(...options.commits);
@@ -134643,6 +134397,9 @@ async function executePull(options, context, execGit) {
134643
134397
  if (options.fastForwardOnly) {
134644
134398
  args.push("--ff-only");
134645
134399
  }
134400
+ if (shouldSignCommits()) {
134401
+ args.push("-S");
134402
+ }
134646
134403
  const cmd = buildGitCommand({ command: "pull", args });
134647
134404
  const result = await execGit(cmd, context.workingDirectory, context.requestContext, { allowNonZeroExit: true });
134648
134405
  const hasConflicts = result.stdout.includes("CONFLICT") || result.stderr.includes("CONFLICT");
@@ -134707,17 +134464,26 @@ async function executeTag(options, context, execGit) {
134707
134464
  "%(if)%(*objectname:short)%(then)%(*objectname:short)%(else)%(objectname:short)%(end)",
134708
134465
  "%(if)%(contents:subject)%(then)%(contents:subject)%(end)",
134709
134466
  "%(if)%(taggername)%(then)%(taggername) %(taggeremail)%(end)",
134710
- "%(if)%(creatordate:unix)%(then)%(creatordate:unix)%(end)"
134711
- ].join(GIT_FIELD_DELIMITER);
134467
+ "%(if)%(creatordate:unix)%(then)%(creatordate:unix)%(end)",
134468
+ "%(if)%(contents:body)%(then)%(contents:body)%(end)"
134469
+ ].join(GIT_FIELD_DELIMITER) + GIT_RECORD_DELIMITER;
134470
+ const forEachRefArgs = [
134471
+ `--format=${format}`,
134472
+ "--sort=-version:refname",
134473
+ "--sort=-creatordate"
134474
+ ];
134475
+ if (typeof options.limit === "number" && options.limit > 0) {
134476
+ forEachRefArgs.push(`--count=${options.limit}`);
134477
+ }
134478
+ forEachRefArgs.push("refs/tags");
134712
134479
  const refCmd = buildGitCommand({
134713
134480
  command: "for-each-ref",
134714
- args: [`--format=${format}`, "--sort=-creatordate", "refs/tags"]
134481
+ args: forEachRefArgs
134715
134482
  });
134716
134483
  const result = await execGit(refCmd, context.workingDirectory, context.requestContext);
134717
134484
  const tags = [];
134718
- for (const line of result.stdout.split(`
134719
- `).filter((l) => l.trim())) {
134720
- const [name, commit, message, tagger, timestamp] = line.split(GIT_FIELD_DELIMITER);
134485
+ for (const record2 of result.stdout.split(GIT_RECORD_DELIMITER).map((r2) => r2.replace(/^\n/, "")).filter((r2) => r2.length > 0)) {
134486
+ const [name, commit, message, tagger, timestamp, annotationBody] = record2.split(GIT_FIELD_DELIMITER);
134721
134487
  if (!name)
134722
134488
  continue;
134723
134489
  const tag = {
@@ -134730,6 +134496,8 @@ async function executeTag(options, context, execGit) {
134730
134496
  tag.tagger = tagger;
134731
134497
  if (timestamp)
134732
134498
  tag.timestamp = parseInt(timestamp, 10);
134499
+ if (annotationBody)
134500
+ tag.annotationBody = annotationBody.trimEnd();
134733
134501
  tags.push(tag);
134734
134502
  }
134735
134503
  return { mode: "list", tags };
@@ -134738,7 +134506,9 @@ async function executeTag(options, context, execGit) {
134738
134506
  if (!options.tagName) {
134739
134507
  throw new Error("Tag name is required for create operation");
134740
134508
  }
134741
- const shouldSign = options.sign ?? shouldSignCommits();
134509
+ const signRequested = shouldSignCommits();
134510
+ let signed = false;
134511
+ let signingWarning;
134742
134512
  const buildCreateArgs = (sign) => {
134743
134513
  const createArgs = [options.tagName];
134744
134514
  if (sign) {
@@ -134757,31 +134527,36 @@ async function executeTag(options, context, execGit) {
134757
134527
  }
134758
134528
  return createArgs;
134759
134529
  };
134760
- const configOverride = shouldSign ? [] : ["-c", "tag.gpgSign=false"];
134761
- const createCmd = [
134762
- ...configOverride,
134763
- ...buildGitCommand({
134764
- command: "tag",
134765
- args: buildCreateArgs(shouldSign)
134766
- })
134767
- ];
134530
+ const buildCmd = (sign) => {
134531
+ const configOverride = sign ? [] : ["-c", "tag.gpgSign=false"];
134532
+ return [
134533
+ ...configOverride,
134534
+ ...buildGitCommand({
134535
+ command: "tag",
134536
+ args: buildCreateArgs(sign)
134537
+ })
134538
+ ];
134539
+ };
134768
134540
  try {
134769
- await execGit(createCmd, context.workingDirectory, context.requestContext);
134541
+ await execGit(buildCmd(signRequested), context.workingDirectory, context.requestContext);
134542
+ signed = signRequested;
134770
134543
  } catch (error48) {
134771
- if (shouldSign && options.forceUnsignedOnFailure) {
134772
- const unsignedCmd = buildGitCommand({
134773
- command: "tag",
134774
- args: buildCreateArgs(false)
134775
- });
134776
- await execGit(unsignedCmd, context.workingDirectory, context.requestContext);
134777
- } else {
134544
+ if (!signRequested) {
134778
134545
  throw error48;
134779
134546
  }
134547
+ const errorMessage = error48 instanceof Error ? error48.message : String(error48);
134548
+ logger.warning("Tag signing failed; retrying unsigned. Set GIT_SIGN_COMMITS=false to suppress this attempt.", { ...context.requestContext, error: error48 });
134549
+ signingWarning = `GIT_SIGN_COMMITS is enabled but signing failed; tag created unsigned. Check signing key availability (gpg-agent running, SSH key accessible). Underlying error: ${errorMessage}`;
134550
+ await execGit(buildCmd(false), context.workingDirectory, context.requestContext);
134780
134551
  }
134781
134552
  const createResult = {
134782
134553
  mode: "create",
134783
- created: options.tagName
134554
+ created: options.tagName,
134555
+ signed
134784
134556
  };
134557
+ if (signingWarning) {
134558
+ createResult.signingWarning = signingWarning;
134559
+ }
134785
134560
  return createResult;
134786
134561
  }
134787
134562
  case "delete": {
@@ -134811,6 +134586,9 @@ async function executeStash(options, context, execGit) {
134811
134586
  switch (options.mode) {
134812
134587
  case "list": {
134813
134588
  args.push("--format=%gd\t%ct\t%gs");
134589
+ if (typeof options.limit === "number" && options.limit > 0) {
134590
+ args.push(`-n${options.limit}`);
134591
+ }
134814
134592
  const cmd = buildGitCommand({ command: "stash", args });
134815
134593
  const result = await execGit(cmd, context.workingDirectory, context.requestContext);
134816
134594
  const stashes = result.stdout.split(`
@@ -135527,7 +135305,6 @@ var import_tsyringe4 = __toESM(require_cjs2(), 1);
135527
135305
 
135528
135306
  // src/storage/providers/fileSystem/fileSystemProvider.ts
135529
135307
  init_errors3();
135530
- init_utils();
135531
135308
  import { existsSync as existsSync2, mkdirSync } from "fs";
135532
135309
  import { readFile, readdir, rm, writeFile } from "fs/promises";
135533
135310
  import path2 from "path";
@@ -135762,7 +135539,6 @@ class FileSystemProvider {
135762
135539
  }
135763
135540
 
135764
135541
  // src/storage/providers/inMemory/inMemoryProvider.ts
135765
- init_utils();
135766
135542
  var DEFAULT_LIST_LIMIT2 = 1000;
135767
135543
 
135768
135544
  class InMemoryProvider {
@@ -135875,7 +135651,6 @@ class InMemoryProvider {
135875
135651
  // src/storage/providers/supabase/supabaseProvider.ts
135876
135652
  var import_tsyringe3 = __toESM(require_cjs2(), 1);
135877
135653
  init_tokens();
135878
- init_utils();
135879
135654
  var TABLE_NAME = "kv_store";
135880
135655
  var DEFAULT_LIST_LIMIT3 = 1000;
135881
135656
 
@@ -136045,7 +135820,6 @@ SupabaseProvider = __legacyDecorateClassTS([
136045
135820
 
136046
135821
  // src/storage/providers/cloudflare/r2Provider.ts
136047
135822
  init_errors3();
136048
- init_utils();
136049
135823
  var R2_ENVELOPE_VERSION = 1;
136050
135824
  var DEFAULT_LIST_LIMIT4 = 1000;
136051
135825
 
@@ -136241,7 +136015,6 @@ class R2Provider {
136241
136015
 
136242
136016
  // src/storage/providers/cloudflare/kvProvider.ts
136243
136017
  init_errors3();
136244
- init_utils();
136245
136018
  var DEFAULT_LIST_LIMIT5 = 1000;
136246
136019
 
136247
136020
  class KvProvider {
@@ -136408,7 +136181,6 @@ class KvProvider {
136408
136181
  }
136409
136182
 
136410
136183
  // src/storage/core/storageFactory.ts
136411
- init_utils();
136412
136184
  var isServerless3 = typeof process === "undefined" || process.env.IS_SERVERLESS === "true";
136413
136185
  function createStorageProvider(config3, deps = {}) {
136414
136186
  const context = requestContextService.createRequestContext({
@@ -136457,8 +136229,6 @@ function createStorageProvider(config3, deps = {}) {
136457
136229
 
136458
136230
  // src/container/registrations/core.ts
136459
136231
  init_errors3();
136460
- init_utils();
136461
- init_rateLimiter();
136462
136232
  var registerCoreServices = () => {
136463
136233
  const config3 = parseConfig();
136464
136234
  import_tsyringe5.container.register(AppConfig, { useValue: config3 });
@@ -136500,12 +136270,9 @@ var import_tsyringe6 = __toESM(require_cjs2(), 1);
136500
136270
 
136501
136271
  // src/mcp-server/resources/definitions/git-working-directory.resource.ts
136502
136272
  init_zod();
136503
- init_utils();
136504
136273
 
136505
136274
  // src/mcp-server/transports/auth/lib/authUtils.ts
136506
136275
  init_errors3();
136507
- init_utils();
136508
- init_authContext();
136509
136276
  function withRequiredScopes(requiredScopes) {
136510
136277
  const operationName = "withRequiredScopesCheck";
136511
136278
  const initialContext = requestContextService.createRequestContext({
@@ -145125,7 +144892,6 @@ var EMPTY_COMPLETION_RESULT = {
145125
144892
 
145126
144893
  // src/mcp-server/resources/utils/resourceHandlerFactory.ts
145127
144894
  init_errors3();
145128
- init_utils();
145129
144895
  function defaultResponseFormatter(result, meta3) {
145130
144896
  return [
145131
144897
  {
@@ -145211,7 +144977,6 @@ async function registerResource(server, def) {
145211
144977
  }
145212
144978
 
145213
144979
  // src/mcp-server/resources/resource-registration.ts
145214
- init_utils();
145215
144980
  class ResourceRegistry {
145216
144981
  resourceDefs;
145217
144982
  constructor(resourceDefs) {
@@ -145251,12 +145016,10 @@ var import_tsyringe7 = __toESM(require_cjs2(), 1);
145251
145016
  // src/mcp-server/prompts/definitions/git-wrapup.prompt.ts
145252
145017
  init_zod();
145253
145018
  var PROMPT_NAME = "git_wrapup";
145254
- var PROMPT_DESCRIPTION = "Generates a structured workflow prompt for wrapping up git sessions, including reviewing changes, updating documentation, and committing modifications.";
145019
+ var PROMPT_DESCRIPTION = "Orchestrates a full git wrap-up: loads the project-aware acceptance-criteria protocol from git_wrapup_instructions, analyzes changes, satisfies each criterion per project convention, commits atomically, and (optionally) tags the release.";
145255
145020
  var ArgumentsSchema = exports_external.object({
145256
- changelogPath: exports_external.string().optional().describe("Path to the changelog file to update (defaults to CHANGELOG.md)."),
145257
- skipDocumentation: exports_external.string().optional().describe("Whether to skip documentation review ('true' | 'false'). Defaults to 'false'."),
145258
- createTag: exports_external.string().optional().describe("Whether to create a git tag after committing ('true' | 'false'). Defaults to 'false'."),
145259
- updateAgentFiles: exports_external.string().optional().describe("Whether to update agent meta files like CLAUDE.md, AGENTS.md ('true' | 'false'). Defaults to 'false'.")
145021
+ changelogPath: exports_external.string().optional().describe("Path to the changelog file when the project uses a flat one (defaults to CHANGELOG.md). The protocol itself defers to project convention."),
145022
+ createTag: exports_external.string().optional().describe("Whether to include the tag criterion in the protocol ('true' | 'false'). Defaults to 'true' — set to 'false' when tagging is deferred to a separate release step.")
145260
145023
  });
145261
145024
  var gitWrapupPrompt = {
145262
145025
  name: PROMPT_NAME,
@@ -145264,57 +145027,34 @@ var gitWrapupPrompt = {
145264
145027
  argumentsSchema: ArgumentsSchema,
145265
145028
  generate: (args) => {
145266
145029
  const changelogPath = args.changelogPath || "CHANGELOG.md";
145267
- const skipDocumentation = args.skipDocumentation === "true";
145268
- const createTag = args.createTag === "true";
145269
- const updateAgentFiles = args.updateAgentFiles === "true";
145270
- const documentationSection = skipDocumentation ? "" : `
145271
- 4. **Review Documentation**: Read the README.md file and verify it accurately reflects the current codebase state. Update as necessary to maintain currency and accuracy.
145272
- `;
145273
- const agentFilesSection = updateAgentFiles ? `
145274
- 5. **Update Agent Files**: If present, review and update agent-specific meta files (CLAUDE.md, AGENTS.md, .clinerules/) to reflect any architectural or protocol changes.
145275
- ` : "";
145276
- const tagSection = createTag ? `
145277
- After all commits are complete and verified via git_status, create an annotated git tag using the git_tag tool. Use semantic versioning (e.g., v1.2.3) and include a summary of key changes in the annotation message.
145278
- ` : "";
145030
+ const includeTag = args.createTag !== "false";
145279
145031
  return [
145280
145032
  {
145281
145033
  role: "user",
145282
145034
  content: {
145283
145035
  type: "text",
145284
- text: `You are an expert git workflow manager. Execute a systematic wrap-up protocol for the current git session.
145036
+ text: `You are an expert git workflow manager. Run a complete wrap-up for the current git session.
145285
145037
 
145286
- ## Workflow Protocol
145038
+ ## Session Flow
145287
145039
 
145288
- Follow these steps in order. Do not proceed until the prior step is confirmed complete.
145040
+ 1. **Load Protocol**: Call \`git_wrapup_instructions\` with \`acknowledgement: "yes"\`${includeTag ? "" : " and `createTag: false`"}. It returns an acceptance-criteria checklist — every box must be satisfied before the wrap-up is complete — plus the current repository status.
145289
145041
 
145290
- 1. **Initialize Context**: First, call the \`git_wrapup_instructions\` tool with \`acknowledgement: "yes"\`${updateAgentFiles ? ' and `updateAgentMetaFiles: "yes"`' : ""}${createTag ? " and `createTag: true`" : ""}. This will provide the detailed workflow instructions and current repository status.
145042
+ 2. **Set Working Directory**: If not already set, call \`git_set_working_dir\` to establish the session context. Required before any git operations.
145291
145043
 
145292
- 2. **Set Working Directory**: If not already set, use \`git_set_working_dir\` to establish the session context. This is mandatory before any git operations.
145044
+ 3. **Analyze Changes**: Run \`git_diff\` with \`includeUntracked: true\`. Understand the "why" behind every modification end-to-end before grouping anything — the diff drives your commit plan and messages.
145293
145045
 
145294
- 3. **Analyze Changes**: Execute \`git_diff\` with \`includeUntracked: true\` to comprehensively understand all modifications. Analyze the diff output thoroughly to inform your commit strategy and messages.
145046
+ 4. **Satisfy the Acceptance Criteria**: Work each checkbox from step 1. The protocol is strict on outcomes, generic on mechanism — follow this project's own conventions for where versions live, how the changelog is formatted (default path when flat: \`${changelogPath}\`), and what the verification suite looks like. If the root agent-instruction file (\`AGENTS.md\`, \`CLAUDE.md\`, or equivalent) documents a project-specific wrap-up procedure, that takes precedence over the generic checklist.
145295
145047
 
145296
- 4. **Update Changelog**: Read the existing \`${changelogPath}\` file. Append a new version entry at the top that:
145297
- - Uses past tense and concise language
145298
- - Categorizes changes (Added, Changed, Fixed, Deprecated, Removed, Security)
145299
- - Follows the existing changelog format
145300
- - Provides enough detail for users to understand the impact
145301
- ${documentationSection}${agentFilesSection}
145302
- 5. **Commit Changes**: Use \`git_commit\` to create atomic, logical commits. For each commit:
145303
- - Group related changes together using the \`filesToStage\` parameter
145304
- - Write commit messages following Conventional Commits format (e.g., \`feat(auth): add password reset\`, \`fix(parser): handle edge case\`)
145305
- - Ensure commits are self-contained and buildable
145306
- - Do not mix unrelated changes in a single commit
145048
+ 5. **Commit Atomically**: Use \`git_commit\` to create logical, self-contained commits in Conventional Commits form. Group related changes with the \`filesToStage\` parameter. No mixing unrelated changes in one commit.
145307
145049
 
145308
- 6. **Verify Completion**: After all commits, run \`git_status\` to confirm the working directory is clean and all changes are committed.
145309
- ${tagSection}
145310
- ## Important Guidelines
145050
+ 6. **Verify Clean**: Run \`git_status\` to confirm the working tree is clean and every change is committed.${includeTag ? "\n\n7. **Tag the Release**: Create an annotated git tag with `git_tag` using semantic versioning (e.g., `v1.2.3`). The annotation message should summarize the real changes — no filler." : ""}
145311
145051
 
145312
- - **Do NOT push** to the remote repository unless explicitly instructed
145313
- - Create a task list before starting to track your progress
145314
- - Be thorough in your diff analysis - understand the "why" behind changes
145315
- - If you encounter merge conflicts or errors, stop and ask for guidance
145316
- - All commit messages must be clear, descriptive, and follow conventions
145317
- - Preserve existing code style and documentation formatting
145052
+ ## Constraints
145053
+
145054
+ - **Do not push** to the remote unless explicitly instructed.
145055
+ - Create a task list before starting so progress is trackable.
145056
+ - Do not bypass verification failures to land a green commit.
145057
+ - On merge conflicts or unexpected errors: stop and surface the blocker.
145318
145058
 
145319
145059
  Begin by calling \`git_wrapup_instructions\` and creating your task list.`
145320
145060
  }
@@ -145327,11 +145067,10 @@ Begin by calling \`git_wrapup_instructions\` and creating your task list.`
145327
145067
  var allPromptDefinitions = [gitWrapupPrompt];
145328
145068
 
145329
145069
  // src/mcp-server/prompts/prompt-registration.ts
145330
- init_utils();
145331
145070
  class PromptRegistry {
145332
145071
  logger;
145333
- constructor(logger3) {
145334
- this.logger = logger3;
145072
+ constructor(logger2) {
145073
+ this.logger = logger2;
145335
145074
  }
145336
145075
  registerAll(server) {
145337
145076
  const context = requestContextService.createRequestContext({
@@ -145364,7 +145103,6 @@ PromptRegistry = __legacyDecorateClassTS([
145364
145103
 
145365
145104
  // src/mcp-server/tools/tool-registration.ts
145366
145105
  var import_tsyringe9 = __toESM(require_cjs2(), 1);
145367
- init_utils();
145368
145106
 
145369
145107
  // src/mcp-server/tools/definitions/git-changelog-analyze.tool.ts
145370
145108
  init_zod();
@@ -145403,7 +145141,6 @@ var AllSchema = exports_external.boolean().default(false).describe("Include all
145403
145141
  var MergeStrategySchema = exports_external.enum(["ort", "recursive", "octopus", "ours", "subtree"]).optional().describe("Merge strategy to use (ort, recursive, octopus, ours, subtree).");
145404
145142
  var PruneSchema = exports_external.boolean().default(false).describe("Prune remote-tracking references that no longer exist on remote.");
145405
145143
  var DepthSchema = exports_external.number().int().min(1).optional().describe("Create a shallow clone with history truncated to N commits.");
145406
- var SignSchema = exports_external.boolean().optional().describe("Sign the commit/tag with GPG/SSH. Omit to use the server's GIT_SIGN_COMMITS default (recommended). Set true to force signing, or false to skip signing even when the default enables it.");
145407
145144
  var NoVerifySchema = exports_external.boolean().default(false).describe("Bypass pre-commit and commit-msg hooks.");
145408
145145
 
145409
145146
  // src/mcp-server/tools/utils/json-response-formatter.ts
@@ -145527,12 +145264,10 @@ var defaultJsonFormatter = createJsonFormatter();
145527
145264
 
145528
145265
  // src/mcp-server/tools/utils/toolHandlerFactory.ts
145529
145266
  init_tokens();
145530
- init_utils();
145531
145267
  var import_tsyringe8 = __toESM(require_cjs2(), 1);
145532
145268
 
145533
145269
  // src/mcp-server/tools/utils/git-validators.ts
145534
145270
  init_errors3();
145535
- init_utils();
145536
145271
  import path3 from "node:path";
145537
145272
  async function resolveWorkingDirectory(pathInput, appContext, storage) {
145538
145273
  let workingDir;
@@ -145805,6 +145540,7 @@ var InputSchema = exports_external.object({
145805
145540
  path: PathSchema,
145806
145541
  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."),
145807
145542
  maxCommits: exports_external.number().int().min(1).max(1000).default(200).describe("Maximum recent commits to fetch for cross-referencing (1-1000)."),
145543
+ 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."),
145808
145544
  sinceTag: exports_external.string().optional().describe('Only include git history since this tag (e.g., "v1.2.0"). Narrows the analysis window.'),
145809
145545
  branch: CommitRefSchema.optional().describe("Branch to analyze (defaults to current branch).")
145810
145546
  });
@@ -145857,7 +145593,7 @@ async function gitChangelogAnalyzeLogic(input, { provider, targetPath, appContex
145857
145593
  }
145858
145594
  const [logResult, tagResult, statusResult] = await Promise.all([
145859
145595
  provider.log(logOptions, operationContext),
145860
- provider.tag({ mode: "list" }, operationContext),
145596
+ provider.tag({ mode: "list", limit: input.maxTags }, operationContext),
145861
145597
  provider.status({ includeUntracked: false }, operationContext)
145862
145598
  ]);
145863
145599
  const reviewInstructions = buildReviewInstructions(input.reviewTypes);
@@ -145870,8 +145606,8 @@ async function gitChangelogAnalyzeLogic(input, { provider, targetPath, appContex
145870
145606
  commits: logResult.commits.map((c) => ({
145871
145607
  hash: c.shortHash,
145872
145608
  subject: c.subject,
145873
- author: c.author,
145874
- timestamp: c.timestamp,
145609
+ author: c.author ?? "",
145610
+ timestamp: c.timestamp ?? 0,
145875
145611
  ...c.refs && c.refs.length > 0 && { refs: c.refs }
145876
145612
  })),
145877
145613
  tags: (tagResult.tags ?? []).map((t2) => ({
@@ -146300,162 +146036,246 @@ var gitReflogTool = {
146300
146036
 
146301
146037
  // src/mcp-server/tools/definitions/git-set-working-dir.tool.ts
146302
146038
  init_zod();
146039
+ init_errors3();
146040
+
146041
+ // src/mcp-server/tools/utils/repo-snapshot.ts
146042
+ init_zod();
146043
+ var RepoSnapshotStatusSchema = exports_external.object({
146044
+ branch: exports_external.string().nullable().describe("Current branch (null on detached HEAD)."),
146045
+ isClean: exports_external.boolean().describe("True when the working tree has no changes."),
146046
+ staged: exports_external.array(exports_external.string()).describe("Paths staged for the next commit."),
146047
+ unstaged: exports_external.array(exports_external.string()).describe("Paths with unstaged modifications."),
146048
+ untracked: exports_external.array(exports_external.string()).describe("Untracked paths."),
146049
+ conflicts: exports_external.array(exports_external.string()).describe("Paths with merge conflicts."),
146050
+ upstream: exports_external.string().optional().describe("Upstream ref being tracked by the current branch."),
146051
+ ahead: exports_external.number().int().optional().describe("Commits ahead of upstream (if tracking)."),
146052
+ behind: exports_external.number().int().optional().describe("Commits behind upstream (if tracking).")
146053
+ });
146054
+ var RepoSnapshotCommitSchema = exports_external.object({
146055
+ hash: exports_external.string().describe("Short commit hash."),
146056
+ author: exports_external.string().describe("Author name."),
146057
+ date: exports_external.string().describe("Author date (ISO 8601)."),
146058
+ subject: exports_external.string().describe("First line of the commit message.")
146059
+ });
146060
+ var RepoSnapshotTagSchema = exports_external.object({
146061
+ name: exports_external.string().describe("Tag name."),
146062
+ date: exports_external.string().optional().describe("Creator date (ISO 8601); absent for lightweight tags with no metadata."),
146063
+ tagger: exports_external.string().optional().describe("Tagger identity (annotated tags only)."),
146064
+ annotationSubject: exports_external.string().optional().describe("First line of the tag annotation (annotated tags only)."),
146065
+ annotationBody: exports_external.string().optional().describe("Remaining annotation body after the subject (annotated tags only).")
146066
+ });
146067
+ var RepoSnapshotRemoteSchema = exports_external.object({
146068
+ name: exports_external.string().describe("Remote name."),
146069
+ fetchUrl: exports_external.string().describe("Fetch URL."),
146070
+ pushUrl: exports_external.string().describe("Push URL (may differ from fetch URL).")
146071
+ });
146072
+ 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.";
146073
+ function reasonMessage(reason) {
146074
+ if (reason instanceof Error)
146075
+ return reason.message;
146076
+ if (typeof reason === "string")
146077
+ return reason;
146078
+ if (reason === null || reason === undefined)
146079
+ return "unknown error";
146080
+ try {
146081
+ return JSON.stringify(reason);
146082
+ } catch {
146083
+ return "unknown error";
146084
+ }
146085
+ }
146086
+ function isNotARepoError(reason) {
146087
+ if (!reason)
146088
+ return false;
146089
+ return /not a git repository/i.test(reasonMessage(reason));
146090
+ }
146091
+ function isEmptyRepoError(reason) {
146092
+ if (!reason)
146093
+ return false;
146094
+ return /does not have any commits yet/i.test(reasonMessage(reason));
146095
+ }
146096
+ function toIsoDate(unixSeconds) {
146097
+ if (typeof unixSeconds !== "number" || !Number.isFinite(unixSeconds)) {
146098
+ return;
146099
+ }
146100
+ return new Date(unixSeconds * 1000).toISOString();
146101
+ }
146102
+ async function gatherRepoSnapshot(deps, options = {}) {
146103
+ const { provider, appContext, workingDirectory } = deps;
146104
+ const commitLimit = options.commitLimit ?? 2;
146105
+ const tagLimit = options.tagLimit ?? 2;
146106
+ const tenantId = appContext.tenantId || "default-tenant";
146107
+ const context = {
146108
+ workingDirectory,
146109
+ requestContext: appContext,
146110
+ tenantId
146111
+ };
146112
+ const fetchStatus = provider.status({ includeUntracked: true }, context);
146113
+ const fetchLog = provider.log({ maxCount: commitLimit }, context);
146114
+ const fetchTags = provider.tag({ mode: "list", limit: tagLimit }, context);
146115
+ const fetchRemotes = options.includeRemotes ? provider.remote({ mode: "list" }, context) : Promise.resolve(undefined);
146116
+ const [statusRes, logRes, tagsRes, remotesRes] = await Promise.allSettled([
146117
+ fetchStatus,
146118
+ fetchLog,
146119
+ fetchTags,
146120
+ fetchRemotes
146121
+ ]);
146122
+ const settled = [statusRes, logRes, tagsRes, remotesRes];
146123
+ const rejections = settled.filter((s2) => s2.status === "rejected");
146124
+ if (rejections.length > 0 && rejections.every((r2) => isNotARepoError(r2.reason))) {
146125
+ logger.debug("Repository snapshot skipped: path is not a git repository", {
146126
+ ...appContext,
146127
+ workingDirectory
146128
+ });
146129
+ return { warnings: [NOT_A_REPO_HINT] };
146130
+ }
146131
+ const warnings = [];
146132
+ const status = statusRes.status === "fulfilled" ? {
146133
+ branch: statusRes.value.currentBranch,
146134
+ isClean: statusRes.value.isClean,
146135
+ staged: [
146136
+ ...statusRes.value.stagedChanges.added ?? [],
146137
+ ...statusRes.value.stagedChanges.modified ?? [],
146138
+ ...statusRes.value.stagedChanges.deleted ?? [],
146139
+ ...statusRes.value.stagedChanges.renamed ?? [],
146140
+ ...statusRes.value.stagedChanges.copied ?? []
146141
+ ],
146142
+ unstaged: [
146143
+ ...statusRes.value.unstagedChanges.added ?? [],
146144
+ ...statusRes.value.unstagedChanges.modified ?? [],
146145
+ ...statusRes.value.unstagedChanges.deleted ?? []
146146
+ ],
146147
+ untracked: statusRes.value.untrackedFiles,
146148
+ conflicts: statusRes.value.conflictedFiles,
146149
+ ...statusRes.value.upstream ? { upstream: statusRes.value.upstream } : {},
146150
+ ...typeof statusRes.value.ahead === "number" ? { ahead: statusRes.value.ahead } : {},
146151
+ ...typeof statusRes.value.behind === "number" ? { behind: statusRes.value.behind } : {}
146152
+ } : {
146153
+ branch: null,
146154
+ isClean: false,
146155
+ staged: [],
146156
+ unstaged: [],
146157
+ untracked: [],
146158
+ conflicts: []
146159
+ };
146160
+ if (statusRes.status === "rejected") {
146161
+ warnings.push(`status unavailable: ${reasonMessage(statusRes.reason)}`);
146162
+ }
146163
+ const recentCommits = logRes.status === "fulfilled" ? logRes.value.commits.map((commit) => ({
146164
+ hash: commit.shortHash,
146165
+ author: commit.author ?? "",
146166
+ date: typeof commit.timestamp === "number" ? new Date(commit.timestamp * 1000).toISOString() : "",
146167
+ subject: commit.subject
146168
+ })) : [];
146169
+ if (logRes.status === "rejected" && !isEmptyRepoError(logRes.reason)) {
146170
+ warnings.push(`recent commits unavailable: ${reasonMessage(logRes.reason)}`);
146171
+ }
146172
+ const recentTags = tagsRes.status === "fulfilled" && tagsRes.value.mode === "list" ? (tagsRes.value.tags ?? []).map((tag) => {
146173
+ const entry = { name: tag.name };
146174
+ const date6 = toIsoDate(tag.timestamp);
146175
+ if (date6)
146176
+ entry.date = date6;
146177
+ if (tag.tagger)
146178
+ entry.tagger = tag.tagger;
146179
+ if (tag.message)
146180
+ entry.annotationSubject = tag.message;
146181
+ if (tag.annotationBody)
146182
+ entry.annotationBody = tag.annotationBody;
146183
+ return entry;
146184
+ }) : [];
146185
+ if (tagsRes.status === "rejected") {
146186
+ warnings.push(`recent tags unavailable: ${reasonMessage(tagsRes.reason)}`);
146187
+ }
146188
+ let remotes;
146189
+ if (options.includeRemotes) {
146190
+ if (remotesRes.status === "fulfilled" && remotesRes.value && remotesRes.value.mode === "list") {
146191
+ remotes = (remotesRes.value.remotes ?? []).map((r2) => ({
146192
+ name: r2.name,
146193
+ fetchUrl: r2.fetchUrl,
146194
+ pushUrl: r2.pushUrl
146195
+ }));
146196
+ } else if (remotesRes.status === "rejected") {
146197
+ warnings.push(`remotes unavailable: ${reasonMessage(remotesRes.reason)}`);
146198
+ remotes = [];
146199
+ } else {
146200
+ remotes = [];
146201
+ }
146202
+ }
146203
+ const snapshot = {
146204
+ status,
146205
+ recentCommits,
146206
+ recentTags,
146207
+ ...remotes !== undefined ? { remotes } : {}
146208
+ };
146209
+ return { snapshot, warnings };
146210
+ }
146211
+
146212
+ // src/mcp-server/tools/definitions/git-set-working-dir.tool.ts
146303
146213
  var TOOL_NAME8 = "git_set_working_dir";
146304
146214
  var TOOL_TITLE8 = "Git Set Working Directory";
146305
- 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.";
146215
+ 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.";
146306
146216
  var InputSchema8 = exports_external.object({
146307
146217
  path: exports_external.string().min(1).describe("Absolute path to the git repository to use as the working directory."),
146308
146218
  validateGitRepo: exports_external.boolean().default(true).describe("Validate that the path is a Git repository."),
146309
- initializeIfNotPresent: exports_external.boolean().default(false).describe("If not a Git repository, initialize it with 'git init'."),
146310
- 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.")
146219
+ initializeIfNotPresent: exports_external.boolean().default(false).describe("If not a Git repository, initialize it with 'git init'.")
146311
146220
  });
146312
146221
  var OutputSchema9 = exports_external.object({
146313
146222
  success: exports_external.boolean().describe("Indicates if the operation was successful."),
146314
146223
  path: exports_external.string().describe("The working directory that was set."),
146315
146224
  message: exports_external.string().describe("Confirmation message."),
146316
- repositoryContext: exports_external.object({
146317
- status: exports_external.object({
146318
- branch: exports_external.string().nullable().describe("Current branch name (null if detached HEAD)."),
146319
- isClean: exports_external.boolean().describe("True if working directory is clean."),
146320
- stagedCount: exports_external.number().int().describe("Number of staged files ready for commit."),
146321
- unstagedCount: exports_external.number().int().describe("Number of files with unstaged changes."),
146322
- untrackedCount: exports_external.number().int().describe("Number of untracked files."),
146323
- conflictsCount: exports_external.number().int().describe("Number of files with merge conflicts.")
146324
- }).describe("Current repository working tree status."),
146325
- branches: exports_external.object({
146326
- current: exports_external.string().nullable().describe("Current branch name (null if detached HEAD)."),
146327
- totalLocal: exports_external.number().int().describe("Total number of local branches."),
146328
- totalRemote: exports_external.number().int().describe("Total number of remote-tracking branches."),
146329
- upstream: exports_external.string().optional().describe("Upstream branch name if current branch is tracking one."),
146330
- ahead: exports_external.number().int().optional().describe("Commits ahead of upstream (if tracking)."),
146331
- behind: exports_external.number().int().optional().describe("Commits behind upstream (if tracking).")
146332
- }).describe("Branch information and tracking status."),
146333
- remotes: exports_external.array(exports_external.object({
146334
- name: exports_external.string().describe("Remote name."),
146335
- fetchUrl: exports_external.string().describe("Fetch URL."),
146336
- pushUrl: exports_external.string().describe("Push URL (may differ from fetch).")
146337
- })).describe("Configured remote repositories."),
146338
- recentCommits: exports_external.array(exports_external.object({
146339
- hash: exports_external.string().describe("Commit hash (short form)."),
146340
- author: exports_external.string().describe("Commit author name."),
146341
- date: exports_external.string().describe("Commit date (ISO 8601 format)."),
146342
- message: exports_external.string().describe("Commit message (first line).")
146343
- })).describe("Recent commits (up to 5 most recent).")
146344
- }).optional().describe("Rich repository metadata including status, branches, remotes, and recent history. Only included when includeMetadata parameter is true.")
146345
- });
146346
- async function gatherRepositoryContext(targetPath, dependencies) {
146225
+ repository: exports_external.object({
146226
+ status: RepoSnapshotStatusSchema,
146227
+ recentCommits: exports_external.array(RepoSnapshotCommitSchema).describe("Up to 2 most recent commits on the current branch."),
146228
+ recentTags: exports_external.array(RepoSnapshotTagSchema).describe("Up to 2 most recent tags by creator date."),
146229
+ remotes: exports_external.array(RepoSnapshotRemoteSchema).describe("Configured remote repositories.")
146230
+ }).optional().describe("Best-effort repository snapshot. Omitted when the path is not a git repository (see enrichmentWarnings)."),
146231
+ enrichmentWarnings: exports_external.array(exports_external.string()).optional().describe("Actionable notes when snapshot gathering was skipped or partially failed.")
146232
+ });
146233
+ async function ensureRepositoryReady(input, dependencies, tenantId) {
146234
+ if (!input.validateGitRepo)
146235
+ return;
146347
146236
  const { provider, appContext } = dependencies;
146348
- const tenantId = appContext.tenantId || "default-tenant";
146349
- const context = {
146350
- workingDirectory: targetPath,
146237
+ const opContext = {
146238
+ workingDirectory: input.path,
146351
146239
  requestContext: appContext,
146352
146240
  tenantId
146353
146241
  };
146354
146242
  try {
146355
- const [
146356
- statusResult,
146357
- localBranchesResult,
146358
- remoteBranchesResult,
146359
- remotesResult,
146360
- logResult
146361
- ] = await Promise.allSettled([
146362
- provider.status({ includeUntracked: true }, context),
146363
- provider.branch({ mode: "list" }, context),
146364
- provider.branch({ mode: "list", remote: true }, context),
146365
- provider.remote({ mode: "list" }, context),
146366
- provider.log({ maxCount: 5 }, context)
146367
- ]);
146368
- const status = statusResult.status === "fulfilled" ? {
146369
- branch: statusResult.value.currentBranch,
146370
- isClean: statusResult.value.isClean,
146371
- 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),
146372
- unstagedCount: (statusResult.value.unstagedChanges.added?.length || 0) + (statusResult.value.unstagedChanges.modified?.length || 0) + (statusResult.value.unstagedChanges.deleted?.length || 0),
146373
- untrackedCount: statusResult.value.untrackedFiles.length,
146374
- conflictsCount: statusResult.value.conflictedFiles.length
146375
- } : {
146376
- branch: null,
146377
- isClean: false,
146378
- stagedCount: 0,
146379
- unstagedCount: 0,
146380
- untrackedCount: 0,
146381
- conflictsCount: 0
146382
- };
146383
- const localBranches = localBranchesResult.status === "fulfilled" && localBranchesResult.value.mode === "list" ? localBranchesResult.value.branches : [];
146384
- const remoteBranchCount = remoteBranchesResult.status === "fulfilled" && remoteBranchesResult.value.mode === "list" ? remoteBranchesResult.value.branches.length : 0;
146385
- const currentBranch = localBranches.find((b) => b.current);
146386
- const branches = {
146387
- current: currentBranch?.name || null,
146388
- totalLocal: localBranches.length,
146389
- totalRemote: remoteBranchCount,
146390
- upstream: currentBranch?.upstream,
146391
- ahead: currentBranch?.ahead,
146392
- behind: currentBranch?.behind
146393
- };
146394
- const remotes = remotesResult.status === "fulfilled" && remotesResult.value.mode === "list" ? remotesResult.value.remotes || [] : [];
146395
- const recentCommits = logResult.status === "fulfilled" ? logResult.value.commits.map((commit) => ({
146396
- hash: commit.shortHash,
146397
- author: commit.author,
146398
- date: new Date(commit.timestamp * 1000).toISOString(),
146399
- message: commit.subject
146400
- })) : [];
146401
- return {
146402
- status,
146403
- branches,
146404
- remotes,
146405
- recentCommits
146406
- };
146407
- } catch (error48) {
146408
- const { logger: logger3 } = await Promise.resolve().then(() => (init_utils(), exports_utils));
146409
- logger3.debug("Failed to gather repository context", {
146410
- ...appContext,
146411
- error: error48 instanceof Error ? error48.message : String(error48),
146412
- targetPath
146413
- });
146243
+ await provider.validateRepository(input.path, opContext);
146414
146244
  return;
146245
+ } catch (error48) {
146246
+ if (input.initializeIfNotPresent) {
146247
+ await provider.init({ path: input.path, initialBranch: "main", bare: false }, opContext);
146248
+ return;
146249
+ }
146250
+ const original = error48 instanceof Error ? error48.message : String(error48);
146251
+ 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 });
146415
146252
  }
146416
146253
  }
146417
146254
  async function gitSetWorkingDirLogic(input, dependencies) {
146418
146255
  const { provider, storage, appContext } = dependencies;
146419
146256
  const tenantId = appContext.tenantId || "default-tenant";
146420
- if (input.validateGitRepo) {
146421
- try {
146422
- await provider.validateRepository(input.path, {
146423
- workingDirectory: input.path,
146424
- requestContext: appContext,
146425
- tenantId
146426
- });
146427
- } catch (error48) {
146428
- if (input.initializeIfNotPresent) {
146429
- await provider.init({
146430
- path: input.path,
146431
- initialBranch: "main",
146432
- bare: false
146433
- }, {
146434
- workingDirectory: input.path,
146435
- requestContext: appContext,
146436
- tenantId
146437
- });
146438
- } else {
146439
- throw error48;
146440
- }
146441
- }
146442
- }
146257
+ await ensureRepositoryReady(input, dependencies, tenantId);
146443
146258
  const storageKey = `session:workingDir:${tenantId}`;
146444
146259
  await storage.set(storageKey, input.path, appContext);
146445
- const repositoryContext = input.includeMetadata ? await gatherRepositoryContext(input.path, dependencies) : undefined;
146260
+ const { snapshot, warnings } = await gatherRepoSnapshot({ provider, appContext, workingDirectory: input.path }, { commitLimit: 2, tagLimit: 2, includeRemotes: true });
146446
146261
  return {
146447
146262
  success: true,
146448
146263
  path: input.path,
146449
146264
  message: `Working directory set to: ${input.path}`,
146450
- repositoryContext
146265
+ ...snapshot ? {
146266
+ repository: {
146267
+ status: snapshot.status,
146268
+ recentCommits: snapshot.recentCommits,
146269
+ recentTags: snapshot.recentTags,
146270
+ remotes: snapshot.remotes ?? []
146271
+ }
146272
+ } : {},
146273
+ ...warnings.length > 0 ? { enrichmentWarnings: warnings } : {}
146451
146274
  };
146452
146275
  }
146453
146276
  function filterGitSetWorkingDirOutput(result, level) {
146454
146277
  if (level === "minimal") {
146455
- return {
146456
- success: result.success,
146457
- path: result.path
146458
- };
146278
+ return { success: result.success, path: result.path };
146459
146279
  }
146460
146280
  return result;
146461
146281
  }
@@ -146485,6 +146305,9 @@ var InputSchema9 = exports_external.object({
146485
146305
  var OutputSchema10 = exports_external.object({
146486
146306
  success: exports_external.boolean().describe("Indicates if the operation was successful."),
146487
146307
  currentBranch: exports_external.string().nullable().describe("Current branch name."),
146308
+ upstream: exports_external.string().optional().describe("Upstream ref the current branch is tracking (if any)."),
146309
+ ahead: exports_external.number().int().optional().describe("Commits ahead of upstream (if tracking)."),
146310
+ behind: exports_external.number().int().optional().describe("Commits behind upstream (if tracking)."),
146488
146311
  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."),
146489
146312
  stagedChanges: exports_external.object({
146490
146313
  added: exports_external.array(exports_external.string()).optional().describe("Files added to the index (staged)."),
@@ -146512,6 +146335,9 @@ async function gitStatusLogic(input, { provider, targetPath, appContext }) {
146512
146335
  return {
146513
146336
  success: true,
146514
146337
  currentBranch: result.currentBranch,
146338
+ ...result.upstream !== undefined && { upstream: result.upstream },
146339
+ ...result.ahead !== undefined && { ahead: result.ahead },
146340
+ ...result.behind !== undefined && { behind: result.behind },
146515
146341
  isClean: result.isClean,
146516
146342
  stagedChanges: result.stagedChanges,
146517
146343
  unstagedChanges: result.unstagedChanges,
@@ -146545,26 +146371,24 @@ var gitStatusTool = {
146545
146371
 
146546
146372
  // src/mcp-server/tools/definitions/git-wrapup-instructions.tool.ts
146547
146373
  init_zod();
146548
- init_utils();
146549
146374
  import { readFileSync } from "fs";
146550
146375
  import path4 from "path";
146551
146376
  init_config();
146552
146377
  var TOOL_NAME10 = "git_wrapup_instructions";
146553
146378
  var TOOL_TITLE10 = "Git Wrap-up Instructions";
146554
- 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.";
146379
+ 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.";
146555
146380
  var InputSchema10 = exports_external.object({
146556
146381
  acknowledgement: exports_external.enum(["Y", "y", "Yes", "yes"]).describe("Acknowledgement to initiate the wrap-up workflow."),
146557
146382
  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.")
146558
146383
  });
146559
146384
  var OutputSchema11 = exports_external.object({
146560
- instructions: exports_external.string().describe("The set of instructions for the wrap-up workflow."),
146561
- gitStatus: exports_external.object({
146562
- branch: exports_external.string().describe("Current branch name."),
146563
- staged: exports_external.array(exports_external.string()).describe("Files staged for commit."),
146564
- unstaged: exports_external.array(exports_external.string()).describe("Files with unstaged changes."),
146565
- untracked: exports_external.array(exports_external.string()).describe("Untracked files.")
146566
- }).optional().describe("The current structured git status."),
146567
- gitStatusError: exports_external.string().optional().describe("Any error message if getting git status failed.")
146385
+ instructions: exports_external.string().describe("The wrap-up protocol to satisfy before the session ships."),
146386
+ repository: exports_external.object({
146387
+ status: RepoSnapshotStatusSchema,
146388
+ recentCommits: exports_external.array(RepoSnapshotCommitSchema).describe("Up to 2 most recent commits on the current branch."),
146389
+ recentTags: exports_external.array(RepoSnapshotTagSchema).describe("Up to 2 most recent tags by creator date.")
146390
+ }).optional().describe("Best-effort repository snapshot. Omitted when no working directory is set or when the path is not a git repository."),
146391
+ enrichmentWarnings: exports_external.array(exports_external.string()).optional().describe("Actionable notes when snapshot gathering was skipped or partially failed.")
146568
146392
  });
146569
146393
  function buildDefaultInstructions(input) {
146570
146394
  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.";
@@ -146633,49 +146457,32 @@ var customInstructions = loadCustomInstructions(config2?.git?.wrapupInstructions
146633
146457
  async function gitWrapupInstructionsLogic(input, { provider, storage, appContext }) {
146634
146458
  const tenantId = appContext.tenantId || "default-tenant";
146635
146459
  const finalInstructions = customInstructions ?? buildDefaultInstructions(input);
146636
- let gitStatus;
146637
- let gitStatusError;
146638
- try {
146639
- const storageKey = `session:workingDir:${tenantId}`;
146640
- const workingDir = await storage.get(storageKey, appContext);
146641
- if (workingDir) {
146642
- const result = await provider.status({ includeUntracked: true }, {
146643
- workingDirectory: workingDir,
146644
- requestContext: appContext,
146645
- tenantId
146646
- });
146647
- gitStatus = {
146648
- branch: result.currentBranch || "detached HEAD",
146649
- staged: [
146650
- ...result.stagedChanges.added || [],
146651
- ...result.stagedChanges.modified || [],
146652
- ...result.stagedChanges.deleted || []
146653
- ],
146654
- unstaged: [
146655
- ...result.unstagedChanges.modified || [],
146656
- ...result.unstagedChanges.deleted || []
146657
- ],
146658
- untracked: result.untrackedFiles
146659
- };
146660
- } else {
146661
- gitStatusError = "No working directory set for session, git status skipped.";
146662
- }
146663
- } catch (error48) {
146664
- const errorMessage = error48 instanceof Error ? error48.message : "Unknown error";
146665
- gitStatusError = `Failed to get git status: ${errorMessage}`;
146666
- logger.warning(gitStatusError, { ...appContext, error: error48 });
146460
+ const storageKey = `session:workingDir:${tenantId}`;
146461
+ const workingDir = await storage.get(storageKey, appContext);
146462
+ if (!workingDir) {
146463
+ return {
146464
+ instructions: finalInstructions,
146465
+ enrichmentWarnings: [
146466
+ "No session working directory set. Call git_set_working_dir first to include a repository snapshot (status, recent commits, recent tags) in this response."
146467
+ ]
146468
+ };
146667
146469
  }
146470
+ const { snapshot, warnings } = await gatherRepoSnapshot({ provider, appContext, workingDirectory: workingDir }, { commitLimit: 2, tagLimit: 2 });
146668
146471
  return {
146669
146472
  instructions: finalInstructions,
146670
- gitStatus,
146671
- gitStatusError
146473
+ ...snapshot ? {
146474
+ repository: {
146475
+ status: snapshot.status,
146476
+ recentCommits: snapshot.recentCommits,
146477
+ recentTags: snapshot.recentTags
146478
+ }
146479
+ } : {},
146480
+ ...warnings.length > 0 ? { enrichmentWarnings: warnings } : {}
146672
146481
  };
146673
146482
  }
146674
146483
  function filterGitWrapupInstructionsOutput(result, level) {
146675
146484
  if (level === "minimal") {
146676
- return {
146677
- instructions: result.instructions
146678
- };
146485
+ return { instructions: result.instructions };
146679
146486
  }
146680
146487
  return result;
146681
146488
  }
@@ -146841,10 +146648,8 @@ var InputSchema12 = exports_external.object({
146841
146648
  }).optional().describe("Override commit author (defaults to git config)."),
146842
146649
  amend: exports_external.boolean().default(false).describe("Amend the previous commit instead of creating a new one. Use with caution."),
146843
146650
  allowEmpty: exports_external.boolean().default(false).describe("Allow creating a commit with no changes."),
146844
- sign: SignSchema,
146845
146651
  noVerify: NoVerifySchema,
146846
- filesToStage: exports_external.array(exports_external.string()).optional().describe("File paths to stage before committing (atomic stage+commit operation)."),
146847
- forceUnsignedOnFailure: exports_external.boolean().default(false).describe("If GPG/SSH signing fails, retry the commit without signing instead of failing.")
146652
+ filesToStage: exports_external.array(exports_external.string()).optional().describe("File paths to stage before committing (atomic stage+commit operation).")
146848
146653
  });
146849
146654
  var OutputSchema13 = exports_external.object({
146850
146655
  success: exports_external.boolean().describe("Indicates if the operation was successful."),
@@ -146856,6 +146661,8 @@ var OutputSchema13 = exports_external.object({
146856
146661
  committedFiles: exports_external.array(exports_external.string()).describe("List of files that were committed."),
146857
146662
  insertions: exports_external.number().int().optional().describe("Number of line insertions."),
146858
146663
  deletions: exports_external.number().int().optional().describe("Number of line deletions."),
146664
+ signed: exports_external.boolean().describe("Whether the commit was signed. False when GIT_SIGN_COMMITS=false or when signing was attempted and fell back to unsigned on failure."),
146665
+ signingWarning: exports_external.string().optional().describe("Populated only when signing was requested but failed, and the commit was created unsigned as a fallback."),
146859
146666
  status: exports_external.object({
146860
146667
  current_branch: exports_external.string().nullable().describe("Current branch name after commit."),
146861
146668
  staged_changes: exports_external.record(exports_external.string(), exports_external.any()).describe("Remaining staged changes after commit."),
@@ -146877,15 +146684,11 @@ async function gitCommitLogic(input, { provider, targetPath, appContext }) {
146877
146684
  message: input.message,
146878
146685
  amend: input.amend,
146879
146686
  allowEmpty: input.allowEmpty,
146880
- noVerify: input.noVerify,
146881
- forceUnsignedOnFailure: input.forceUnsignedOnFailure
146687
+ noVerify: input.noVerify
146882
146688
  };
146883
146689
  if (input.author !== undefined) {
146884
146690
  commitOptions.author = input.author;
146885
146691
  }
146886
- if (input.sign !== undefined) {
146887
- commitOptions.sign = input.sign;
146888
- }
146889
146692
  const result = await provider.commit(commitOptions, {
146890
146693
  workingDirectory: targetPath,
146891
146694
  requestContext: appContext,
@@ -146896,7 +146699,7 @@ async function gitCommitLogic(input, { provider, targetPath, appContext }) {
146896
146699
  requestContext: appContext,
146897
146700
  tenantId: appContext.tenantId || "default-tenant"
146898
146701
  });
146899
- return {
146702
+ const output = {
146900
146703
  success: result.success,
146901
146704
  commitHash: result.commitHash,
146902
146705
  message: result.message,
@@ -146904,6 +146707,7 @@ async function gitCommitLogic(input, { provider, targetPath, appContext }) {
146904
146707
  timestamp: result.timestamp,
146905
146708
  filesChanged: result.filesChanged.length,
146906
146709
  committedFiles: result.filesChanged,
146710
+ signed: result.signed,
146907
146711
  status: {
146908
146712
  current_branch: statusResult.currentBranch,
146909
146713
  staged_changes: flattenChanges(statusResult.stagedChanges),
@@ -146913,6 +146717,10 @@ async function gitCommitLogic(input, { provider, targetPath, appContext }) {
146913
146717
  is_clean: statusResult.isClean
146914
146718
  }
146915
146719
  };
146720
+ if (result.signingWarning) {
146721
+ output.signingWarning = result.signingWarning;
146722
+ }
146723
+ return output;
146916
146724
  }
146917
146725
  function filterGitCommitOutput(result, level) {
146918
146726
  if (level === "minimal") {
@@ -146920,6 +146728,8 @@ function filterGitCommitOutput(result, level) {
146920
146728
  success: result.success,
146921
146729
  commitHash: result.commitHash,
146922
146730
  message: result.message,
146731
+ signed: result.signed,
146732
+ ...result.signingWarning && { signingWarning: result.signingWarning },
146923
146733
  status: {
146924
146734
  current_branch: result.status.current_branch,
146925
146735
  is_clean: result.status.is_clean,
@@ -146941,6 +146751,8 @@ function filterGitCommitOutput(result, level) {
146941
146751
  insertions: result.insertions,
146942
146752
  deletions: result.deletions,
146943
146753
  committedFiles: result.committedFiles,
146754
+ signed: result.signed,
146755
+ ...result.signingWarning && { signingWarning: result.signingWarning },
146944
146756
  status: {
146945
146757
  current_branch: result.status.current_branch,
146946
146758
  is_clean: result.status.is_clean,
@@ -147102,7 +146914,8 @@ var CommitSchema = exports_external.object({
147102
146914
  var OutputSchema15 = exports_external.object({
147103
146915
  success: exports_external.boolean().describe("Indicates if the operation was successful."),
147104
146916
  commits: exports_external.array(CommitSchema).describe("Array of commit objects."),
147105
- totalCount: exports_external.number().int().describe("Total number of commits returned (may be limited by maxCount).")
146917
+ totalCount: exports_external.number().int().describe("Total number of commits returned (may be limited by maxCount)."),
146918
+ 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.")
147106
146919
  });
147107
146920
  async function gitLogLogic(input, { provider, targetPath, appContext }) {
147108
146921
  const result = await provider.log({
@@ -147123,15 +146936,25 @@ async function gitLogLogic(input, { provider, targetPath, appContext }) {
147123
146936
  requestContext: appContext,
147124
146937
  tenantId: appContext.tenantId || "default-tenant"
147125
146938
  });
147126
- const commits = input.oneline ? result.commits.map(({ hash: hash2, shortHash, subject }) => ({
147127
- hash: hash2,
147128
- shortHash,
147129
- subject
147130
- })) : result.commits;
146939
+ const appliedFilters = [];
146940
+ if (input.author)
146941
+ appliedFilters.push(`author=${input.author}`);
146942
+ if (input.grep)
146943
+ appliedFilters.push(`grep=${input.grep}`);
146944
+ if (input.since)
146945
+ appliedFilters.push(`since=${input.since}`);
146946
+ if (input.until)
146947
+ appliedFilters.push(`until=${input.until}`);
146948
+ if (input.filePath)
146949
+ appliedFilters.push(`filePath=${input.filePath}`);
146950
+ if (input.branch)
146951
+ appliedFilters.push(`branch=${input.branch}`);
146952
+ 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;
147131
146953
  return {
147132
146954
  success: true,
147133
- commits,
147134
- totalCount: result.totalCount
146955
+ commits: result.commits,
146956
+ totalCount: result.totalCount,
146957
+ ...note && { note }
147135
146958
  };
147136
146959
  }
147137
146960
  function filterGitLogOutput(result, level) {
@@ -147250,7 +147073,8 @@ var InputSchema16 = exports_external.object({
147250
147073
  all: AllSchema.describe("For list operation: show both local and remote branches."),
147251
147074
  remote: exports_external.boolean().default(false).describe("For list operation: show only remote branches."),
147252
147075
  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)."),
147253
- 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).")
147076
+ 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)."),
147077
+ limit: LimitSchema.describe("For list operation: cap the number of branches returned (applied at the git command). Use on repos with many branches.")
147254
147078
  });
147255
147079
  var BranchInfoSchema = exports_external.object({
147256
147080
  name: exports_external.string().describe("Branch name."),
@@ -147269,18 +147093,18 @@ var OutputSchema17 = exports_external.object({
147269
147093
  });
147270
147094
  async function gitBranchLogic(input, { provider, targetPath, appContext }) {
147271
147095
  if (input.operation === "show-current") {
147272
- const result2 = await provider.branch({ mode: "list" }, {
147096
+ const result2 = await provider.branch({ mode: "show-current" }, {
147273
147097
  workingDirectory: targetPath,
147274
147098
  requestContext: appContext,
147275
147099
  tenantId: appContext.tenantId || "default-tenant"
147276
147100
  });
147277
- const current = result2.mode === "list" ? result2.branches.find((b) => b.current) : undefined;
147101
+ const current = result2.mode === "show-current" ? result2.current : null;
147278
147102
  return {
147279
147103
  success: true,
147280
147104
  operation: "show-current",
147281
147105
  branches: undefined,
147282
- currentBranch: current?.name,
147283
- message: current ? `Current branch: ${current.name}` : "Not on any branch (detached HEAD)"
147106
+ currentBranch: current ?? undefined,
147107
+ message: current ? `Current branch: ${current}` : "Not on any branch (detached HEAD)"
147284
147108
  };
147285
147109
  }
147286
147110
  const { path: _path, operation, name, newName, ...rest } = input;
@@ -147310,6 +147134,9 @@ async function gitBranchLogic(input, { provider, targetPath, appContext }) {
147310
147134
  if (rest.noMerged !== undefined) {
147311
147135
  branchOptions.noMerged = rest.noMerged;
147312
147136
  }
147137
+ if (rest.limit !== undefined) {
147138
+ branchOptions.limit = rest.limit;
147139
+ }
147313
147140
  const result = await provider.branch(branchOptions, {
147314
147141
  workingDirectory: targetPath,
147315
147142
  requestContext: appContext,
@@ -147339,7 +147166,7 @@ async function gitBranchLogic(input, { provider, targetPath, appContext }) {
147339
147166
  currentBranch: undefined,
147340
147167
  message: `Branch '${result.deleted}' deleted successfully.`
147341
147168
  };
147342
- } else {
147169
+ } else if (result.mode === "rename") {
147343
147170
  return {
147344
147171
  success: true,
147345
147172
  operation: "rename",
@@ -147348,6 +147175,7 @@ async function gitBranchLogic(input, { provider, targetPath, appContext }) {
147348
147175
  message: `Branch '${result.renamed.from}' renamed to '${result.renamed.to}'.`
147349
147176
  };
147350
147177
  }
147178
+ throw new Error(`Unexpected branch result mode: ${result.mode}`);
147351
147179
  }
147352
147180
  function filterGitBranchOutput(result, level) {
147353
147181
  if (level === "minimal") {
@@ -148105,7 +147933,8 @@ var InputSchema26 = exports_external.object({
148105
147933
  message: exports_external.string().optional().describe("Stash message description (for push operation)."),
148106
147934
  stashRef: exports_external.string().optional().describe("Stash reference like stash@{0} (for pop/apply/drop operations)."),
148107
147935
  includeUntracked: exports_external.boolean().default(false).describe("Include untracked files in the stash (for push operation)."),
148108
- keepIndex: exports_external.boolean().default(false).describe("Don't revert staged changes (for push operation).")
147936
+ keepIndex: exports_external.boolean().default(false).describe("Don't revert staged changes (for push operation)."),
147937
+ limit: LimitSchema.describe("For list mode: cap the number of stash entries returned (applied at the git command).")
148109
147938
  });
148110
147939
  var StashInfoSchema = exports_external.object({
148111
147940
  ref: exports_external.string().describe("Stash reference (e.g., stash@{0})."),
@@ -148139,6 +147968,9 @@ async function gitStashLogic(input, { provider, targetPath, appContext }) {
148139
147968
  if (input.keepIndex !== undefined) {
148140
147969
  stashOptions.keepIndex = input.keepIndex;
148141
147970
  }
147971
+ if (input.limit !== undefined) {
147972
+ stashOptions.limit = input.limit;
147973
+ }
148142
147974
  const result = await provider.stash(stashOptions, {
148143
147975
  workingDirectory: targetPath,
148144
147976
  requestContext: appContext,
@@ -148189,9 +148021,7 @@ var InputSchema27 = exports_external.object({
148189
148021
  tagName: TagNameSchema.optional().describe("Tag name for create/delete operations."),
148190
148022
  commit: CommitRefSchema.optional().describe("Commit to tag (default: HEAD for create operation)."),
148191
148023
  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."),
148192
- annotated: exports_external.boolean().default(false).describe('Create an annotated tag with a default "Tag <name>" message. Only effective when both message and sign are absent — otherwise the tag is always annotated.'),
148193
- sign: SignSchema,
148194
- forceUnsignedOnFailure: exports_external.boolean().default(false).describe("If GPG/SSH signing fails, retry the tag creation without signing instead of failing."),
148024
+ 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.'),
148195
148025
  force: ForceSchema.describe("Overwrite an existing tag (create mode only; has no effect on list or delete).")
148196
148026
  });
148197
148027
  var TagInfoSchema = exports_external.object({
@@ -148206,7 +148036,9 @@ var OutputSchema28 = exports_external.object({
148206
148036
  mode: exports_external.string().describe("Operation mode that was performed."),
148207
148037
  tags: exports_external.array(TagInfoSchema).optional().describe("List of tags (for list mode)."),
148208
148038
  created: exports_external.string().optional().describe("Created tag name (for create mode)."),
148209
- deleted: exports_external.string().optional().describe("Deleted tag name (for delete mode).")
148039
+ deleted: exports_external.string().optional().describe("Deleted tag name (for delete mode)."),
148040
+ 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."),
148041
+ signingWarning: exports_external.string().optional().describe("Populated only when signing was requested but failed, and the tag was created unsigned as a fallback.")
148210
148042
  });
148211
148043
  async function gitTagLogic(input, { provider, targetPath, appContext }) {
148212
148044
  if ((input.mode === "create" || input.mode === "delete") && !input.tagName) {
@@ -148215,8 +148047,7 @@ async function gitTagLogic(input, { provider, targetPath, appContext }) {
148215
148047
  const tagOptions = {
148216
148048
  mode: input.mode,
148217
148049
  annotated: input.annotated,
148218
- force: input.force,
148219
- forceUnsignedOnFailure: input.forceUnsignedOnFailure
148050
+ force: input.force
148220
148051
  };
148221
148052
  if (input.tagName !== undefined) {
148222
148053
  tagOptions.tagName = input.tagName;
@@ -148227,27 +148058,33 @@ async function gitTagLogic(input, { provider, targetPath, appContext }) {
148227
148058
  if (input.message !== undefined) {
148228
148059
  tagOptions.message = normalizeMessage(input.message);
148229
148060
  }
148230
- if (input.sign !== undefined) {
148231
- tagOptions.sign = input.sign;
148232
- }
148233
148061
  const result = await provider.tag(tagOptions, {
148234
148062
  workingDirectory: targetPath,
148235
148063
  requestContext: appContext,
148236
148064
  tenantId: appContext.tenantId || "default-tenant"
148237
148065
  });
148238
- return {
148066
+ const output = {
148239
148067
  success: true,
148240
148068
  mode: result.mode,
148241
148069
  tags: result.tags,
148242
148070
  created: result.created,
148243
148071
  deleted: result.deleted
148244
148072
  };
148073
+ if (result.signed !== undefined) {
148074
+ output.signed = result.signed;
148075
+ }
148076
+ if (result.signingWarning) {
148077
+ output.signingWarning = result.signingWarning;
148078
+ }
148079
+ return output;
148245
148080
  }
148246
148081
  function filterGitTagOutput(result, level) {
148247
148082
  if (level === "minimal") {
148248
148083
  return {
148249
148084
  success: result.success,
148250
- mode: result.mode
148085
+ mode: result.mode,
148086
+ ...result.signed !== undefined && { signed: result.signed },
148087
+ ...result.signingWarning && { signingWarning: result.signingWarning }
148251
148088
  };
148252
148089
  }
148253
148090
  return result;
@@ -148466,7 +148303,6 @@ var registerTools = (container4) => {
148466
148303
  };
148467
148304
 
148468
148305
  // src/mcp-server/server.ts
148469
- init_utils();
148470
148306
  async function createMcpServerInstance() {
148471
148307
  const context = requestContextService.createRequestContext({
148472
148308
  operation: "createMcpServerInstance"
@@ -148510,7 +148346,6 @@ async function createMcpServerInstance() {
148510
148346
 
148511
148347
  // src/mcp-server/transports/manager.ts
148512
148348
  init_tokens();
148513
- init_utils();
148514
148349
  var import_tsyringe14 = __toESM(require_cjs2(), 1);
148515
148350
 
148516
148351
  // node_modules/@modelcontextprotocol/sdk/dist/esm/server/auth/errors.js
@@ -151018,11 +150853,11 @@ var MemoryEventStore = class {
151018
150853
  #eventIdToStreamIdMap;
151019
150854
  #idGenerator;
151020
150855
  constructor(options = {}) {
151021
- const { streamBufferSize = 100, eventsPerStreamBufferSize = 100, idGenerator: idGenerator3 = () => crypto.randomUUID() } = options;
150856
+ const { streamBufferSize = 100, eventsPerStreamBufferSize = 100, idGenerator: idGenerator2 = () => crypto.randomUUID() } = options;
151022
150857
  this.#idToIndexMap = /* @__PURE__ */ new Map;
151023
150858
  this.#eventIdToStreamIdMap = /* @__PURE__ */ new Map;
151024
150859
  this.#eventsPerStreamBufferSize = eventsPerStreamBufferSize;
151025
- this.#idGenerator = idGenerator3;
150860
+ this.#idGenerator = idGenerator2;
151026
150861
  this.#items = new RingBuffer(streamBufferSize, ({ streamId, events }) => {
151027
150862
  this.#idToIndexMap.delete(streamId);
151028
150863
  events.reset();
@@ -152266,13 +152101,8 @@ var serve = (options, listeningListener) => {
152266
152101
  init_config();
152267
152102
  import http3 from "http";
152268
152103
  import { randomUUID } from "node:crypto";
152269
-
152270
- // src/mcp-server/transports/auth/index.ts
152271
- init_authContext();
152272
-
152273
152104
  // src/mcp-server/transports/auth/authFactory.ts
152274
152105
  init_config();
152275
- init_utils();
152276
152106
  var import_tsyringe13 = __toESM(require_cjs2(), 1);
152277
152107
 
152278
152108
  // node_modules/jose/dist/webapi/lib/buffer_utils.js
@@ -153760,7 +153590,6 @@ function createRemoteJWKSet(url2, options) {
153760
153590
  // src/mcp-server/transports/auth/strategies/jwtStrategy.ts
153761
153591
  init_tokens();
153762
153592
  init_errors3();
153763
- init_utils();
153764
153593
  var import_tsyringe11 = __toESM(require_cjs2(), 1);
153765
153594
  class JwtStrategy {
153766
153595
  config;
@@ -153769,9 +153598,9 @@ class JwtStrategy {
153769
153598
  env;
153770
153599
  devMcpClientId;
153771
153600
  devMcpScopes;
153772
- constructor(config3, logger3) {
153601
+ constructor(config3, logger2) {
153773
153602
  this.config = config3;
153774
- this.logger = logger3;
153603
+ this.logger = logger2;
153775
153604
  const context = requestContextService.createRequestContext({
153776
153605
  operation: "JwtStrategy.constructor"
153777
153606
  });
@@ -153876,15 +153705,14 @@ JwtStrategy = __legacyDecorateClassTS([
153876
153705
  // src/mcp-server/transports/auth/strategies/oauthStrategy.ts
153877
153706
  init_tokens();
153878
153707
  init_errors3();
153879
- init_utils();
153880
153708
  var import_tsyringe12 = __toESM(require_cjs2(), 1);
153881
153709
  class OauthStrategy {
153882
153710
  config;
153883
153711
  logger;
153884
153712
  jwks;
153885
- constructor(config3, logger3) {
153713
+ constructor(config3, logger2) {
153886
153714
  this.config = config3;
153887
- this.logger = logger3;
153715
+ this.logger = logger2;
153888
153716
  const context = requestContextService.createRequestContext({
153889
153717
  operation: "OauthStrategy.constructor"
153890
153718
  });
@@ -154029,8 +153857,6 @@ function createAuthStrategy() {
154029
153857
  }
154030
153858
  // src/mcp-server/transports/auth/authMiddleware.ts
154031
153859
  init_errors3();
154032
- init_utils();
154033
- init_authContext();
154034
153860
  function createAuthMiddleware(strategy) {
154035
153861
  return async function authMiddleware(c, next) {
154036
153862
  const context = requestContextService.createRequestContext({
@@ -154079,7 +153905,6 @@ function createAuthMiddleware(strategy) {
154079
153905
  }
154080
153906
  // src/mcp-server/transports/http/httpErrorHandler.ts
154081
153907
  init_errors3();
154082
- init_utils();
154083
153908
  var httpErrorHandler = async (err, c) => {
154084
153909
  const context = requestContextService.createRequestContext({
154085
153910
  operation: "httpErrorHandler",
@@ -154164,8 +153989,6 @@ var httpErrorHandler = async (err, c) => {
154164
153989
  };
154165
153990
 
154166
153991
  // src/mcp-server/transports/http/sessionManager.ts
154167
- init_utils();
154168
-
154169
153992
  class SessionManager {
154170
153993
  static instance = null;
154171
153994
  sessions = new Map;
@@ -154324,7 +154147,6 @@ class SessionManager {
154324
154147
  }
154325
154148
 
154326
154149
  // src/mcp-server/transports/http/httpTransport.ts
154327
- init_utils();
154328
154150
  function createHttpApp(createMcpServer, parentContext) {
154329
154151
  const app = new Hono2;
154330
154152
  const transportContext = {
@@ -154700,7 +154522,6 @@ class StdioServerTransport {
154700
154522
  }
154701
154523
 
154702
154524
  // src/mcp-server/transports/stdio/stdioTransport.ts
154703
- init_utils();
154704
154525
  async function startStdioTransport(server, parentContext) {
154705
154526
  const operationContext = {
154706
154527
  ...parentContext,
@@ -154747,9 +154568,9 @@ class TransportManager {
154747
154568
  logger;
154748
154569
  createMcpServer;
154749
154570
  serverInstance = null;
154750
- constructor(config3, logger3, createMcpServer) {
154571
+ constructor(config3, logger2, createMcpServer) {
154751
154572
  this.config = config3;
154752
- this.logger = logger3;
154573
+ this.logger = logger2;
154753
154574
  this.createMcpServer = createMcpServer;
154754
154575
  }
154755
154576
  async start() {
@@ -154802,7 +154623,6 @@ TransportManager = __legacyDecorateClassTS([
154802
154623
  ], TransportManager);
154803
154624
 
154804
154625
  // src/container/registrations/mcp.ts
154805
- init_utils();
154806
154626
  var registerMcpServices = () => {
154807
154627
  import_tsyringe15.container.registerSingleton(ToolRegistry);
154808
154628
  import_tsyringe15.container.registerSingleton(ResourceRegistry);
@@ -154898,11 +154718,11 @@ var start = async () => {
154898
154718
  }
154899
154719
  await logger.initialize(validatedMcpLogLevel, config3.mcpTransportType);
154900
154720
  logger.info(`Logger initialized. Effective MCP logging level: ${validatedMcpLogLevel}.`, requestContextService.createRequestContext({ operation: "LoggerInit" }));
154901
- const runtime2 = detectRuntime();
154721
+ const runtime = detectRuntime();
154902
154722
  const runtimeDesc = getRuntimeDescription();
154903
154723
  logger.info(`Runtime detected: ${runtimeDesc}`, requestContextService.createRequestContext({
154904
154724
  operation: "RuntimeDetection",
154905
- runtime: runtime2,
154725
+ runtime,
154906
154726
  runtimeVersion: runtimeDesc
154907
154727
  }));
154908
154728
  logger.info(`Storage service initialized with provider: ${config3.storage.providerType}`, requestContextService.createRequestContext({ operation: "StorageInit" }));