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