mcp-ts-template 2.4.1 → 2.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +441 -116
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -29010,7 +29010,7 @@ var require_gaxios = __commonJS((exports) => {
29010
29010
  function hasFetch() {
29011
29011
  return hasWindow() && !!window.fetch;
29012
29012
  }
29013
- function hasBuffer() {
29013
+ function hasBuffer2() {
29014
29014
  return typeof Buffer !== "undefined";
29015
29015
  }
29016
29016
  function hasHeader(options, header) {
@@ -29236,7 +29236,7 @@ Content-Type: ${partContentType}\r
29236
29236
  const isFormData = typeof FormData === "undefined" ? false : (opts === null || opts === undefined ? undefined : opts.data) instanceof FormData;
29237
29237
  if (is_stream_1.default.readable(opts.data)) {
29238
29238
  opts.body = opts.data;
29239
- } else if (hasBuffer() && Buffer.isBuffer(opts.data)) {
29239
+ } else if (hasBuffer2() && Buffer.isBuffer(opts.data)) {
29240
29240
  opts.body = opts.data;
29241
29241
  if (!hasHeader(opts, "Content-Type")) {
29242
29242
  opts.headers["Content-Type"] = "application/json";
@@ -117645,81 +117645,175 @@ var config = parseConfig();
117645
117645
 
117646
117646
  // src/utils/telemetry/instrumentation.ts
117647
117647
  var import_api = __toESM(require_src(), 1);
117648
- var import_auto_instrumentations_node = __toESM(require_src58(), 1);
117649
- var import_exporter_metrics_otlp_http = __toESM(require_src62(), 1);
117650
- var import_exporter_trace_otlp_http = __toESM(require_src63(), 1);
117651
- var import_instrumentation_pino = __toESM(require_src40(), 1);
117652
- var import_resources = __toESM(require_src52(), 1);
117653
- var import_sdk_metrics = __toESM(require_src59(), 1);
117654
- var import_sdk_node = __toESM(require_src83(), 1);
117655
- var import_sdk_trace_node = __toESM(require_src67(), 1);
117656
- var import_incubating = __toESM(require_index_incubating(), 1);
117648
+
117649
+ // src/utils/internal/runtime.ts
117650
+ var safeHas = (key) => {
117651
+ try {
117652
+ return typeof globalThis[key] !== "undefined";
117653
+ } catch {
117654
+ return false;
117655
+ }
117656
+ };
117657
+ var isNode = typeof process !== "undefined" && typeof process.versions?.node === "string";
117658
+ var hasProcess = typeof process !== "undefined";
117659
+ var hasBuffer = typeof Buffer !== "undefined";
117660
+ var hasTextEncoder = safeHas("TextEncoder");
117661
+ var hasPerformanceNow = typeof globalThis.performance?.now === "function";
117662
+ var isWorkerLike = !isNode && typeof globalThis.WorkerGlobalScope !== "undefined";
117663
+ var isBrowserLike = !isNode && !isWorkerLike && safeHas("window");
117664
+ var runtimeCaps = {
117665
+ isNode,
117666
+ isWorkerLike,
117667
+ isBrowserLike,
117668
+ hasProcess,
117669
+ hasBuffer,
117670
+ hasTextEncoder,
117671
+ hasPerformanceNow
117672
+ };
117673
+
117674
+ // src/utils/telemetry/instrumentation.ts
117657
117675
  var sdk = null;
117658
117676
  var isOtelInitialized = false;
117659
- if (config.openTelemetry.enabled && !isOtelInitialized) {
117660
- isOtelInitialized = true;
117661
- try {
117662
- const otelLogLevelString = config.openTelemetry.logLevel.toUpperCase();
117663
- const otelLogLevel = import_api.DiagLogLevel[otelLogLevelString] ?? import_api.DiagLogLevel.INFO;
117664
- import_api.diag.setLogger(new import_api.DiagConsoleLogger, otelLogLevel);
117665
- const tracesEndpoint = config.openTelemetry.tracesEndpoint;
117666
- const metricsEndpoint = config.openTelemetry.metricsEndpoint;
117667
- if (!tracesEndpoint && !metricsEndpoint) {
117668
- import_api.diag.warn("OTEL_ENABLED is true, but no OTLP endpoint for traces or metrics is configured. OpenTelemetry will not export any telemetry.");
117669
- }
117670
- const resource = import_resources.resourceFromAttributes({
117671
- [import_incubating.ATTR_SERVICE_NAME]: config.openTelemetry.serviceName,
117672
- [import_incubating.ATTR_SERVICE_VERSION]: config.openTelemetry.serviceVersion,
117673
- "deployment.environment.name": config.environment
117674
- });
117675
- const spanProcessors = [];
117676
- if (tracesEndpoint) {
117677
- import_api.diag.info(`Using OTLP exporter for traces, endpoint: ${tracesEndpoint}`);
117678
- const traceExporter = new import_exporter_trace_otlp_http.OTLPTraceExporter({ url: tracesEndpoint });
117679
- spanProcessors.push(new import_sdk_trace_node.BatchSpanProcessor(traceExporter));
117680
- } else {
117681
- import_api.diag.info("No OTLP traces endpoint configured. Traces will not be exported.");
117682
- }
117683
- const metricReader = metricsEndpoint ? new import_sdk_metrics.PeriodicExportingMetricReader({
117684
- exporter: new import_exporter_metrics_otlp_http.OTLPMetricExporter({ url: metricsEndpoint }),
117685
- exportIntervalMillis: 15000
117686
- }) : undefined;
117687
- sdk = new import_sdk_node.NodeSDK({
117688
- resource,
117689
- spanProcessors,
117690
- ...metricReader && { metricReader },
117691
- sampler: new import_sdk_trace_node.TraceIdRatioBasedSampler(config.openTelemetry.samplingRatio),
117692
- instrumentations: [
117693
- import_auto_instrumentations_node.getNodeAutoInstrumentations({
117694
- "@opentelemetry/instrumentation-http": {
117695
- enabled: true,
117696
- ignoreIncomingRequestHook: (req) => req.url === "/healthz"
117697
- },
117698
- "@opentelemetry/instrumentation-fs": { enabled: false }
117699
- }),
117700
- new import_instrumentation_pino.PinoInstrumentation({
117701
- logHook: (_span, record) => {
117702
- record["trace_id"] = _span.spanContext().traceId;
117703
- record["span_id"] = _span.spanContext().spanId;
117704
- }
117705
- })
117706
- ]
117707
- });
117708
- sdk.start();
117709
- import_api.diag.info(`OpenTelemetry initialized for ${config.openTelemetry.serviceName} v${config.openTelemetry.serviceVersion}`);
117710
- } catch (error) {
117711
- import_api.diag.error("Error initializing OpenTelemetry", error);
117712
- sdk = null;
117677
+ var initializationPromise = null;
117678
+ function canUseNodeSDK() {
117679
+ return runtimeCaps.isNode && typeof process?.versions?.node === "string" && typeof process.env === "object";
117680
+ }
117681
+ function detectCloudResource() {
117682
+ const attrs = {};
117683
+ if (runtimeCaps.isWorkerLike) {
117684
+ attrs["cloud.provider"] = "cloudflare";
117685
+ attrs["cloud.platform"] = "cloudflare_workers";
117686
+ }
117687
+ if (typeof process !== "undefined" && process.env?.AWS_LAMBDA_FUNCTION_NAME) {
117688
+ attrs["cloud.provider"] = "aws";
117689
+ attrs["cloud.platform"] = "aws_lambda";
117690
+ if (process.env.AWS_REGION) {
117691
+ attrs["cloud.region"] = process.env.AWS_REGION;
117692
+ }
117693
+ }
117694
+ if (typeof process !== "undefined" && (process.env?.FUNCTION_TARGET || process.env?.K_SERVICE)) {
117695
+ attrs["cloud.provider"] = "gcp";
117696
+ attrs["cloud.platform"] = process.env.FUNCTION_TARGET ? "gcp_cloud_functions" : "gcp_cloud_run";
117697
+ if (process.env.GCP_REGION) {
117698
+ attrs["cloud.region"] = process.env.GCP_REGION;
117699
+ }
117713
117700
  }
117701
+ attrs["deployment.environment.name"] = config.environment;
117702
+ return attrs;
117714
117703
  }
117715
- async function shutdownOpenTelemetry() {
117716
- if (sdk) {
117704
+ async function initializeOpenTelemetry() {
117705
+ if (initializationPromise) {
117706
+ return initializationPromise;
117707
+ }
117708
+ if (isOtelInitialized) {
117709
+ return;
117710
+ }
117711
+ initializationPromise = (async () => {
117712
+ if (!config.openTelemetry.enabled) {
117713
+ import_api.diag.info("OpenTelemetry disabled via configuration.");
117714
+ isOtelInitialized = true;
117715
+ return;
117716
+ }
117717
+ if (!canUseNodeSDK()) {
117718
+ import_api.diag.info("NodeSDK unavailable in this runtime. Using lightweight telemetry mode.");
117719
+ isOtelInitialized = true;
117720
+ return;
117721
+ }
117722
+ isOtelInitialized = true;
117717
117723
  try {
117718
- await sdk.shutdown();
117719
- import_api.diag.info("OpenTelemetry terminated successfully.");
117724
+ const [
117725
+ { getNodeAutoInstrumentations },
117726
+ { OTLPMetricExporter },
117727
+ { OTLPTraceExporter },
117728
+ { PinoInstrumentation },
117729
+ { resourceFromAttributes },
117730
+ { PeriodicExportingMetricReader },
117731
+ { NodeSDK },
117732
+ { BatchSpanProcessor, TraceIdRatioBasedSampler },
117733
+ { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION }
117734
+ ] = await Promise.all([
117735
+ Promise.resolve().then(() => __toESM(require_src58(), 1)),
117736
+ Promise.resolve().then(() => __toESM(require_src62(), 1)),
117737
+ Promise.resolve().then(() => __toESM(require_src63(), 1)),
117738
+ Promise.resolve().then(() => __toESM(require_src40(), 1)),
117739
+ Promise.resolve().then(() => __toESM(require_src52(), 1)),
117740
+ Promise.resolve().then(() => __toESM(require_src59(), 1)),
117741
+ Promise.resolve().then(() => __toESM(require_src83(), 1)),
117742
+ Promise.resolve().then(() => __toESM(require_src67(), 1)),
117743
+ Promise.resolve().then(() => __toESM(require_index_incubating(), 1))
117744
+ ]);
117745
+ const otelLogLevelString = config.openTelemetry.logLevel.toUpperCase();
117746
+ const otelLogLevel = import_api.DiagLogLevel[otelLogLevelString] ?? import_api.DiagLogLevel.INFO;
117747
+ import_api.diag.setLogger(new import_api.DiagConsoleLogger, otelLogLevel);
117748
+ const tracesEndpoint = config.openTelemetry.tracesEndpoint;
117749
+ const metricsEndpoint = config.openTelemetry.metricsEndpoint;
117750
+ if (!tracesEndpoint && !metricsEndpoint) {
117751
+ import_api.diag.warn("OTEL_ENABLED is true, but no OTLP endpoint for traces or metrics is configured. OpenTelemetry will not export any telemetry.");
117752
+ }
117753
+ const resource = resourceFromAttributes({
117754
+ [ATTR_SERVICE_NAME]: config.openTelemetry.serviceName,
117755
+ [ATTR_SERVICE_VERSION]: config.openTelemetry.serviceVersion,
117756
+ ...detectCloudResource()
117757
+ });
117758
+ const spanProcessors = [];
117759
+ if (tracesEndpoint) {
117760
+ import_api.diag.info(`Using OTLP exporter for traces, endpoint: ${tracesEndpoint}`);
117761
+ const traceExporter = new OTLPTraceExporter({ url: tracesEndpoint });
117762
+ spanProcessors.push(new BatchSpanProcessor(traceExporter));
117763
+ } else {
117764
+ import_api.diag.info("No OTLP traces endpoint configured. Traces will not be exported.");
117765
+ }
117766
+ const metricReader = metricsEndpoint ? new PeriodicExportingMetricReader({
117767
+ exporter: new OTLPMetricExporter({ url: metricsEndpoint }),
117768
+ exportIntervalMillis: 15000
117769
+ }) : undefined;
117770
+ sdk = new NodeSDK({
117771
+ resource,
117772
+ spanProcessors,
117773
+ ...metricReader && { metricReader },
117774
+ sampler: new TraceIdRatioBasedSampler(config.openTelemetry.samplingRatio),
117775
+ instrumentations: [
117776
+ getNodeAutoInstrumentations({
117777
+ "@opentelemetry/instrumentation-http": {
117778
+ enabled: true,
117779
+ ignoreIncomingRequestHook: (req) => req.url === "/healthz"
117780
+ },
117781
+ "@opentelemetry/instrumentation-fs": { enabled: false }
117782
+ }),
117783
+ new PinoInstrumentation({
117784
+ logHook: (_span, record) => {
117785
+ record["trace_id"] = _span.spanContext().traceId;
117786
+ record["span_id"] = _span.spanContext().spanId;
117787
+ }
117788
+ })
117789
+ ]
117790
+ });
117791
+ sdk.start();
117792
+ import_api.diag.info(`OpenTelemetry NodeSDK initialized for ${config.openTelemetry.serviceName} v${config.openTelemetry.serviceVersion}`);
117720
117793
  } catch (error) {
117721
- import_api.diag.error("Error terminating OpenTelemetry", error);
117794
+ import_api.diag.error("Error initializing OpenTelemetry", error);
117795
+ sdk = null;
117796
+ throw error;
117722
117797
  }
117798
+ })();
117799
+ return initializationPromise;
117800
+ }
117801
+ async function shutdownOpenTelemetry(timeoutMs = 5000) {
117802
+ if (!sdk) {
117803
+ return;
117804
+ }
117805
+ try {
117806
+ const shutdownPromise = sdk.shutdown();
117807
+ const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error("OpenTelemetry SDK shutdown timeout")), timeoutMs));
117808
+ await Promise.race([shutdownPromise, timeoutPromise]);
117809
+ import_api.diag.info("OpenTelemetry SDK terminated successfully.");
117810
+ } catch (error) {
117811
+ import_api.diag.error("Error terminating OpenTelemetry SDK", error);
117812
+ throw error;
117813
+ } finally {
117814
+ sdk = null;
117815
+ isOtelInitialized = false;
117816
+ initializationPromise = null;
117723
117817
  }
117724
117818
  }
117725
117819
 
@@ -118457,6 +118551,25 @@ class Logger {
118457
118551
  var logger = Logger.getInstance();
118458
118552
 
118459
118553
  // src/utils/internal/error-handler/mappings.ts
118554
+ var COMPILED_PATTERN_CACHE = new Map;
118555
+ function getCompiledPattern(pattern) {
118556
+ const cacheKey = pattern instanceof RegExp ? pattern.source + pattern.flags : pattern;
118557
+ if (COMPILED_PATTERN_CACHE.has(cacheKey)) {
118558
+ return COMPILED_PATTERN_CACHE.get(cacheKey);
118559
+ }
118560
+ let compiled;
118561
+ if (pattern instanceof RegExp) {
118562
+ let flags = pattern.flags.replace("g", "");
118563
+ if (!flags.includes("i")) {
118564
+ flags += "i";
118565
+ }
118566
+ compiled = new RegExp(pattern.source, flags);
118567
+ } else {
118568
+ compiled = new RegExp(pattern, "i");
118569
+ }
118570
+ COMPILED_PATTERN_CACHE.set(cacheKey, compiled);
118571
+ return compiled;
118572
+ }
118460
118573
  var ERROR_TYPE_MAPPINGS = {
118461
118574
  SyntaxError: -32007 /* ValidationError */,
118462
118575
  TypeError: -32007 /* ValidationError */,
@@ -118508,17 +118621,76 @@ var COMMON_ERROR_PATTERNS = [
118508
118621
  errorCode: -32007 /* ValidationError */
118509
118622
  }
118510
118623
  ];
118624
+ var COMPILED_ERROR_PATTERNS = COMMON_ERROR_PATTERNS.map((mapping) => ({
118625
+ ...mapping,
118626
+ compiledPattern: getCompiledPattern(mapping.pattern)
118627
+ }));
118628
+ var PROVIDER_ERROR_PATTERNS = [
118629
+ {
118630
+ pattern: /ThrottlingException|TooManyRequestsException/i,
118631
+ errorCode: -32003 /* RateLimited */
118632
+ },
118633
+ {
118634
+ pattern: /AccessDenied|UnauthorizedOperation/i,
118635
+ errorCode: -32005 /* Forbidden */
118636
+ },
118637
+ {
118638
+ pattern: /ResourceNotFoundException/i,
118639
+ errorCode: -32001 /* NotFound */
118640
+ },
118641
+ { pattern: /status code 401/i, errorCode: -32006 /* Unauthorized */ },
118642
+ { pattern: /status code 403/i, errorCode: -32005 /* Forbidden */ },
118643
+ { pattern: /status code 404/i, errorCode: -32001 /* NotFound */ },
118644
+ { pattern: /status code 409/i, errorCode: -32002 /* Conflict */ },
118645
+ { pattern: /status code 429/i, errorCode: -32003 /* RateLimited */ },
118646
+ {
118647
+ pattern: /status code 5\d\d/i,
118648
+ errorCode: -32000 /* ServiceUnavailable */
118649
+ },
118650
+ {
118651
+ pattern: /ECONNREFUSED|connection refused/i,
118652
+ errorCode: -32000 /* ServiceUnavailable */
118653
+ },
118654
+ {
118655
+ pattern: /ETIMEDOUT|connection timeout/i,
118656
+ errorCode: -32004 /* Timeout */
118657
+ },
118658
+ {
118659
+ pattern: /unique constraint|duplicate key/i,
118660
+ errorCode: -32002 /* Conflict */
118661
+ },
118662
+ {
118663
+ pattern: /foreign key constraint/i,
118664
+ errorCode: -32007 /* ValidationError */
118665
+ },
118666
+ { pattern: /JWT expired/i, errorCode: -32006 /* Unauthorized */ },
118667
+ {
118668
+ pattern: /row level security/i,
118669
+ errorCode: -32005 /* Forbidden */
118670
+ },
118671
+ {
118672
+ pattern: /insufficient_quota|quota exceeded/i,
118673
+ errorCode: -32003 /* RateLimited */
118674
+ },
118675
+ { pattern: /model_not_found/i, errorCode: -32001 /* NotFound */ },
118676
+ {
118677
+ pattern: /context_length_exceeded/i,
118678
+ errorCode: -32007 /* ValidationError */
118679
+ },
118680
+ { pattern: /ENOTFOUND|DNS/i, errorCode: -32000 /* ServiceUnavailable */ },
118681
+ {
118682
+ pattern: /ECONNRESET|connection reset/i,
118683
+ errorCode: -32000 /* ServiceUnavailable */
118684
+ }
118685
+ ];
118686
+ var COMPILED_PROVIDER_PATTERNS = PROVIDER_ERROR_PATTERNS.map((mapping) => ({
118687
+ ...mapping,
118688
+ compiledPattern: getCompiledPattern(mapping.pattern)
118689
+ }));
118511
118690
 
118512
118691
  // src/utils/internal/error-handler/helpers.ts
118513
118692
  function createSafeRegex(pattern) {
118514
- if (pattern instanceof RegExp) {
118515
- let flags = pattern.flags.replace("g", "");
118516
- if (!flags.includes("i")) {
118517
- flags += "i";
118518
- }
118519
- return new RegExp(pattern.source, flags);
118520
- }
118521
- return new RegExp(pattern, "i");
118693
+ return getCompiledPattern(pattern);
118522
118694
  }
118523
118695
  function getErrorName(error) {
118524
118696
  if (error instanceof Error) {
@@ -118579,6 +118751,61 @@ function getErrorMessage(error) {
118579
118751
  return `Error converting error to string: ${conversionError instanceof Error ? conversionError.message : "Unknown conversion error"}`;
118580
118752
  }
118581
118753
  }
118754
+ function extractErrorCauseChain(error, maxDepth = 20) {
118755
+ const chain = [];
118756
+ const seen = new WeakSet;
118757
+ let current = error;
118758
+ let depth = 0;
118759
+ while (current && depth < maxDepth) {
118760
+ if (typeof current === "object" && current !== null) {
118761
+ if (seen.has(current)) {
118762
+ chain.push({
118763
+ name: "CircularReference",
118764
+ message: "Circular reference detected in error cause chain",
118765
+ depth
118766
+ });
118767
+ break;
118768
+ }
118769
+ seen.add(current);
118770
+ }
118771
+ if (current instanceof Error) {
118772
+ const node = {
118773
+ name: current.name,
118774
+ message: current.message,
118775
+ depth,
118776
+ ...current.stack !== undefined ? { stack: current.stack } : {}
118777
+ };
118778
+ if (current instanceof McpError && current.data) {
118779
+ node.data = current.data;
118780
+ }
118781
+ chain.push(node);
118782
+ current = current.cause;
118783
+ } else if (typeof current === "string") {
118784
+ chain.push({
118785
+ name: "StringError",
118786
+ message: current,
118787
+ depth
118788
+ });
118789
+ break;
118790
+ } else {
118791
+ chain.push({
118792
+ name: getErrorName(current),
118793
+ message: getErrorMessage(current),
118794
+ depth
118795
+ });
118796
+ break;
118797
+ }
118798
+ depth++;
118799
+ }
118800
+ if (depth >= maxDepth) {
118801
+ chain.push({
118802
+ name: "MaxDepthExceeded",
118803
+ message: `Error cause chain exceeded maximum depth of ${maxDepth}`,
118804
+ depth
118805
+ });
118806
+ }
118807
+ return chain;
118808
+ }
118582
118809
 
118583
118810
  // src/utils/internal/error-handler/errorHandler.ts
118584
118811
  class ErrorHandler {
@@ -118592,9 +118819,13 @@ class ErrorHandler {
118592
118819
  if (mappedFromType) {
118593
118820
  return mappedFromType;
118594
118821
  }
118595
- for (const mapping of COMMON_ERROR_PATTERNS) {
118596
- const regex = createSafeRegex(mapping.pattern);
118597
- if (regex.test(errorMessage) || regex.test(errorName)) {
118822
+ for (const mapping of COMPILED_PROVIDER_PATTERNS) {
118823
+ if (mapping.compiledPattern.test(errorMessage) || mapping.compiledPattern.test(errorName)) {
118824
+ return mapping.errorCode;
118825
+ }
118826
+ }
118827
+ for (const mapping of COMPILED_ERROR_PATTERNS) {
118828
+ if (mapping.compiledPattern.test(errorMessage) || mapping.compiledPattern.test(errorName)) {
118598
118829
  return mapping.errorCode;
118599
118830
  }
118600
118831
  }
@@ -118641,17 +118872,19 @@ class ErrorHandler {
118641
118872
  consolidatedData.originalStack = originalStack;
118642
118873
  }
118643
118874
  const cause = error instanceof Error ? error : undefined;
118644
- const rootCause = (() => {
118645
- let current = cause;
118646
- let depth = 0;
118647
- while (current && current instanceof Error && current.cause && depth < 5) {
118648
- current = current.cause;
118649
- depth += 1;
118875
+ const causeChain = extractErrorCauseChain(error);
118876
+ if (causeChain.length > 0) {
118877
+ const rootCause = causeChain[causeChain.length - 1];
118878
+ if (rootCause) {
118879
+ consolidatedData["rootCause"] = {
118880
+ name: rootCause.name,
118881
+ message: rootCause.message
118882
+ };
118650
118883
  }
118651
- return current instanceof Error ? { name: current.name, message: current.message } : undefined;
118652
- })();
118653
- if (rootCause) {
118654
- consolidatedData["rootCause"] = rootCause;
118884
+ consolidatedData["causeChain"] = causeChain;
118885
+ }
118886
+ if (context && "metadata" in context && context.metadata && typeof context.metadata === "object" && "breadcrumbs" in context.metadata) {
118887
+ consolidatedData["breadcrumbs"] = context.metadata.breadcrumbs;
118655
118888
  }
118656
118889
  if (error instanceof McpError) {
118657
118890
  loggedErrorCode = error.code;
@@ -118735,32 +118968,119 @@ class ErrorHandler {
118735
118968
  });
118736
118969
  }
118737
118970
  }
118738
- }
118739
- // src/utils/internal/runtime.ts
118740
- var safeHas = (key) => {
118741
- try {
118742
- return typeof globalThis[key] !== "undefined";
118743
- } catch {
118744
- return false;
118971
+ static async tryAsResult(fn, options) {
118972
+ try {
118973
+ const value = await Promise.resolve(fn());
118974
+ return { ok: true, value };
118975
+ } catch (caughtError) {
118976
+ const error = ErrorHandler.handleError(caughtError, {
118977
+ ...options,
118978
+ rethrow: false
118979
+ });
118980
+ return { ok: false, error };
118981
+ }
118745
118982
  }
118746
- };
118747
- var isNode = typeof process !== "undefined" && typeof process.versions?.node === "string";
118748
- var hasProcess = typeof process !== "undefined";
118749
- var hasBuffer = typeof Buffer !== "undefined";
118750
- var hasTextEncoder = safeHas("TextEncoder");
118751
- var hasPerformanceNow = typeof globalThis.performance?.now === "function";
118752
- var isWorkerLike = !isNode && typeof globalThis.WorkerGlobalScope !== "undefined";
118753
- var isBrowserLike = !isNode && !isWorkerLike && safeHas("window");
118754
- var runtimeCaps = {
118755
- isNode,
118756
- isWorkerLike,
118757
- isBrowserLike,
118758
- hasProcess,
118759
- hasBuffer,
118760
- hasTextEncoder,
118761
- hasPerformanceNow
118762
- };
118763
-
118983
+ static mapResult(result, fn) {
118984
+ if (result.ok) {
118985
+ try {
118986
+ return { ok: true, value: fn(result.value) };
118987
+ } catch (error) {
118988
+ return {
118989
+ ok: false,
118990
+ error: new McpError(-32603 /* InternalError */, `Error mapping result: ${getErrorMessage(error)}`)
118991
+ };
118992
+ }
118993
+ }
118994
+ return result;
118995
+ }
118996
+ static flatMapResult(result, fn) {
118997
+ if (result.ok) {
118998
+ return fn(result.value);
118999
+ }
119000
+ return result;
119001
+ }
119002
+ static recoverResult(result, fallback) {
119003
+ if (result.ok) {
119004
+ return result.value;
119005
+ }
119006
+ return typeof fallback === "function" ? fallback(result.error) : fallback;
119007
+ }
119008
+ static addBreadcrumb(context, operation, additionalData) {
119009
+ const breadcrumbs = context.metadata?.breadcrumbs || [];
119010
+ breadcrumbs.push({
119011
+ timestamp: new Date().toISOString(),
119012
+ operation,
119013
+ ...additionalData !== undefined ? { context: additionalData } : {}
119014
+ });
119015
+ return {
119016
+ ...context,
119017
+ metadata: {
119018
+ ...context.metadata,
119019
+ breadcrumbs
119020
+ }
119021
+ };
119022
+ }
119023
+ static async tryCatchWithRetry(fn, options, strategy) {
119024
+ let lastError;
119025
+ for (let attempt = 1;attempt <= strategy.maxAttempts; attempt++) {
119026
+ try {
119027
+ return await Promise.resolve(fn());
119028
+ } catch (caughtError) {
119029
+ lastError = caughtError instanceof Error ? caughtError : new Error(String(caughtError));
119030
+ if (attempt < strategy.maxAttempts && strategy.shouldRetry(lastError, attempt)) {
119031
+ const delay = strategy.getRetryDelay(attempt);
119032
+ const retryContext = {
119033
+ ...options.context,
119034
+ requestId: options.context?.requestId || generateUUID(),
119035
+ timestamp: new Date().toISOString(),
119036
+ operation: options.operation,
119037
+ error: lastError.message,
119038
+ attempt
119039
+ };
119040
+ logger.warning(`Retry attempt ${attempt}/${strategy.maxAttempts} after ${delay}ms`, retryContext);
119041
+ strategy.onRetry?.(lastError, attempt);
119042
+ await new Promise((resolve) => setTimeout(resolve, delay));
119043
+ } else {
119044
+ throw ErrorHandler.handleError(lastError, {
119045
+ ...options,
119046
+ rethrow: true,
119047
+ context: {
119048
+ ...options.context,
119049
+ retryAttempts: attempt,
119050
+ finalAttempt: true
119051
+ }
119052
+ });
119053
+ }
119054
+ }
119055
+ }
119056
+ throw ErrorHandler.handleError(lastError, {
119057
+ ...options,
119058
+ rethrow: true
119059
+ });
119060
+ }
119061
+ static createExponentialBackoffStrategy(maxAttempts = 3, baseDelay = 1000, maxDelay = 30000) {
119062
+ return {
119063
+ maxAttempts,
119064
+ shouldRetry: (error) => {
119065
+ if (error instanceof McpError) {
119066
+ const nonRetryableCodes = [
119067
+ -32007 /* ValidationError */,
119068
+ -32006 /* Unauthorized */,
119069
+ -32005 /* Forbidden */,
119070
+ -32001 /* NotFound */
119071
+ ];
119072
+ return !nonRetryableCodes.includes(error.code);
119073
+ }
119074
+ return true;
119075
+ },
119076
+ getRetryDelay: (attemptNumber) => {
119077
+ const exponentialDelay = baseDelay * Math.pow(2, attemptNumber - 1);
119078
+ const jitter = Math.random() * 0.3 * exponentialDelay;
119079
+ return Math.min(exponentialDelay + jitter, maxDelay);
119080
+ }
119081
+ };
119082
+ }
119083
+ }
118764
119084
  // src/utils/internal/performance.ts
118765
119085
  var import_api4 = __toESM(require_src(), 1);
118766
119086
 
@@ -136482,6 +136802,11 @@ var start = async () => {
136482
136802
  await shutdownOpenTelemetry();
136483
136803
  process.exit(1);
136484
136804
  }
136805
+ try {
136806
+ await initializeOpenTelemetry();
136807
+ } catch (error2) {
136808
+ console.error("[Startup] Failed to initialize OpenTelemetry:", error2);
136809
+ }
136485
136810
  await initializePerformance_Hrt();
136486
136811
  const validMcpLogLevels = [
136487
136812
  "debug",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-ts-template",
3
- "version": "2.4.1",
3
+ "version": "2.4.2",
4
4
  "mcpName": "io.github.cyanheads/mcp-ts-template",
5
5
  "description": "The definitive, production-grade template for building powerful and scalable Model Context Protocol (MCP) servers with TypeScript, featuring built-in observability (OpenTelemetry), declarative tooling, robust error handling, and a modular, DI-driven architecture.",
6
6
  "main": "dist/index.js",