hevy-mcp 5.0.4 → 5.0.5

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/dist/cli.mjs CHANGED
@@ -4,12 +4,12 @@
4
4
  (function() {
5
5
  try {
6
6
  var e = "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof globalThis ? globalThis : "undefined" != typeof self ? self : {};
7
- e.SENTRY_RELEASE = { id: "hevy-mcp@5.0.4" };
7
+ e.SENTRY_RELEASE = { id: "hevy-mcp@5.0.5" };
8
8
  var n = new e.Error().stack;
9
9
  n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "625c4c9c-e20d-40b3-96b1-4e799ef130f3", e._sentryDebugIdIdentifier = "sentry-dbid-625c4c9c-e20d-40b3-96b1-4e799ef130f3");
10
10
  } catch (e) {}
11
11
  })();
12
- import { a as createSafeErrorDiagnostic, i as MissingHevyApiKeyError, n as runServer, o as flushTelemetry } from "./src-CJRjsomO.mjs";
12
+ import { a as createSafeErrorDiagnostic, i as MissingHevyApiKeyError, n as runServer, o as flushTelemetry } from "./src-TBD9ENR3.mjs";
13
13
  //#region src/cli.ts
14
14
  runServer().catch(async (error) => {
15
15
  if (error instanceof MissingHevyApiKeyError) console.error(error.message);
package/dist/index.mjs CHANGED
@@ -4,10 +4,10 @@
4
4
  (function() {
5
5
  try {
6
6
  var e = "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof globalThis ? globalThis : "undefined" != typeof self ? self : {};
7
- e.SENTRY_RELEASE = { id: "hevy-mcp@5.0.4" };
7
+ e.SENTRY_RELEASE = { id: "hevy-mcp@5.0.5" };
8
8
  var n = new e.Error().stack;
9
9
  n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "e9496b31-626b-4ad1-9416-47ba4ffd2995", e._sentryDebugIdIdentifier = "sentry-dbid-e9496b31-626b-4ad1-9416-47ba4ffd2995");
10
10
  } catch (e) {}
11
11
  })();
12
- import { n as runServer, r as runStdioServer, t as createNodeMcpServer } from "./src-CJRjsomO.mjs";
12
+ import { n as runServer, r as runStdioServer, t as createNodeMcpServer } from "./src-TBD9ENR3.mjs";
13
13
  export { createNodeMcpServer, runServer, runStdioServer };
@@ -4,9 +4,9 @@
4
4
  (function() {
5
5
  try {
6
6
  var e = "undefined" != typeof window ? window : "undefined" != typeof global ? global : "undefined" != typeof globalThis ? globalThis : "undefined" != typeof self ? self : {};
7
- e.SENTRY_RELEASE = { id: "hevy-mcp@5.0.4" };
7
+ e.SENTRY_RELEASE = { id: "hevy-mcp@5.0.5" };
8
8
  var n = new e.Error().stack;
9
- n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "72e7b08a-987c-4dba-aabd-6437da54ce2f", e._sentryDebugIdIdentifier = "sentry-dbid-72e7b08a-987c-4dba-aabd-6437da54ce2f");
9
+ n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "f5270278-73ea-40fd-92e2-2ae5127e6780", e._sentryDebugIdIdentifier = "sentry-dbid-f5270278-73ea-40fd-92e2-2ae5127e6780");
10
10
  } catch (e) {}
11
11
  })();
12
12
  import { createHmac, randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
@@ -20,13 +20,13 @@ import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
20
20
  import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
21
21
  import { MeterProvider, PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
22
22
  import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
23
- import { AsyncLocalStorage } from "node:async_hooks";
24
23
  import { ZodError, z } from "zod";
25
24
  import { McpServer, deserializeMessage } from "@modelcontextprotocol/server";
26
25
  import { z as z$1 } from "zod/v4";
27
26
  import { isIP } from "node:net";
28
27
  import { createServer } from "node:http";
29
28
  import { NodeStreamableHTTPServerTransport } from "@modelcontextprotocol/node";
29
+ import { AsyncLocalStorage } from "node:async_hooks";
30
30
  import { mkdir, readFile, rename, unlink, writeFile } from "node:fs/promises";
31
31
  import { homedir } from "node:os";
32
32
  import { dirname, join } from "node:path";
@@ -79,6 +79,10 @@ function sanitizeSentryMcpSpan(span) {
79
79
  * Sentry SDK: error events, performance traces, release tracking
80
80
  * OTel Collector → Honeycomb: performance traces, metrics
81
81
  */
82
+ const PROCESS_FAILURE_TAXONOMY = {
83
+ uncaughtException: "uncaught_exception",
84
+ unhandledRejection: "unhandled_rejection"
85
+ };
82
86
  const SAFE_EXCEPTION_TYPES = /* @__PURE__ */ new Set([
83
87
  "AggregateError",
84
88
  "DOMException",
@@ -109,10 +113,7 @@ const SAFE_EXCEPTION_CODES = /* @__PURE__ */ new Set([
109
113
  ]);
110
114
  function normalizeTelemetryError(error) {
111
115
  const candidate = error instanceof Error && typeof error.name === "string" ? error.name : void 0;
112
- return {
113
- name: candidate && SAFE_EXCEPTION_TYPES.has(candidate) ? candidate : "UnknownError",
114
- ...error instanceof Error && error.stack ? { stack: error.stack } : {}
115
- };
116
+ return { name: candidate && SAFE_EXCEPTION_TYPES.has(candidate) ? candidate : "UnknownError" };
116
117
  }
117
118
  function getSafeExceptionCode(error) {
118
119
  if (!error || typeof error !== "object" || !("code" in error)) return void 0;
@@ -125,7 +126,10 @@ function recordTelemetryException(error, attributes, span) {
125
126
  const target = span ?? trace.getActiveSpan();
126
127
  if (!target) return;
127
128
  const normalized = normalizeTelemetryError(error);
128
- target.recordException(normalized);
129
+ target.addEvent("exception", {
130
+ ...attributes,
131
+ "exception.type": normalized.name
132
+ });
129
133
  target.setAttribute("exception.type", normalized.name);
130
134
  target.setAttribute("error.category", normalized.name);
131
135
  if (attributes) target.setAttributes(attributes);
@@ -138,11 +142,12 @@ function installProcessExceptionTracking(processLike = process) {
138
142
  try {
139
143
  tracer.startActiveSpan(`mcp.process.${source}`, { attributes: { "mcp.span.category": "process" } }, (span) => {
140
144
  try {
141
- const normalized = normalizeTelemetryError(error);
142
145
  const code = getSafeExceptionCode(error);
143
146
  recordTelemetryException(error, {
144
147
  "exception.source": source,
145
- "error.category": normalized.name,
148
+ "mcp.failure.phase": PROCESS_FAILURE_TAXONOMY[source],
149
+ "error.type": "MCP_PROCESS_EXCEPTION",
150
+ "error.category": "McpProcessFailure",
146
151
  ...code ? { "error.code": code } : {}
147
152
  }, span);
148
153
  } finally {
@@ -164,7 +169,7 @@ function installProcessExceptionTracking(processLike = process) {
164
169
  };
165
170
  }
166
171
  const name$1 = "hevy-mcp";
167
- const version$1 = "5.0.4";
172
+ const version$1 = "5.0.5";
168
173
  const telemetryEnabled = process.env.HEVY_MCP_TELEMETRY !== "0";
169
174
  const collectorToken = "NH9vOela-HYreQxAbJa68cjEmORoEKM57EvneUDVcOo";
170
175
  const COLLECTOR_ENDPOINT = "https://otel.chrisdoc.dev/v1";
@@ -2839,7 +2844,7 @@ function registerHevyResources(server, runtime) {
2839
2844
  //#endregion
2840
2845
  //#region ../core/src/server-metadata.ts
2841
2846
  const SERVER_NAME = "hevy-mcp";
2842
- const SERVER_VERSION = "5.0.4";
2847
+ const SERVER_VERSION = "5.0.5";
2843
2848
  const SERVER_INSTRUCTIONS = [
2844
2849
  "Hevy MCP connects clients to the authenticated user's Hevy workout-tracking data, including workouts, routines, exercise templates, routine folders, body measurements, and profile information. HEVY_API_KEY must contain a valid Hevy API key for local stdio use.",
2845
2850
  "Safety: all get-* and search-* tools are read-only. create-* and update-* tools mutate Hevy data. Creates are additive and non-idempotent, so repeating one can create duplicates. Updates can overwrite existing data. Delete operations are not available.",
@@ -5728,6 +5733,177 @@ function createInstrumentedStdioTransport(transport) {
5728
5733
  return transport;
5729
5734
  }
5730
5735
  //#endregion
5736
+ //#region src/utils/sdk-observability.ts
5737
+ const sdkToolNameStorage = new AsyncLocalStorage();
5738
+ const SAFE_TOOL_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/u;
5739
+ const SDK_FAILURE_TAXONOMY = {
5740
+ protocol: {
5741
+ errorType: "UNKNOWN_ERROR",
5742
+ errorCategory: "McpSdkProtocolFailure"
5743
+ },
5744
+ tool_call: {
5745
+ errorType: "UNKNOWN_ERROR",
5746
+ errorCategory: "McpSdkToolCallFailure"
5747
+ },
5748
+ validation: {
5749
+ errorType: "VALIDATION_ERROR",
5750
+ errorCategory: "McpSdkValidationFailure"
5751
+ }
5752
+ };
5753
+ function createFailureAttributes(error, phase, errorType, errorCategory) {
5754
+ const diagnostic = createSafeErrorDiagnostic(error);
5755
+ return {
5756
+ "mcp.failure.phase": phase,
5757
+ "error.type": errorType,
5758
+ "error.category": errorCategory,
5759
+ ...diagnostic.code ? { "error.code": diagnostic.code } : {},
5760
+ ...diagnostic.status !== void 0 ? { "http.response.status_code": diagnostic.status } : {},
5761
+ ...diagnostic.method ? { "http.request.method": diagnostic.method } : {},
5762
+ ...diagnostic.endpoint ? { "hevy.api.endpoint": diagnostic.endpoint } : {}
5763
+ };
5764
+ }
5765
+ function enrichActiveSdkSpan(attributes) {
5766
+ try {
5767
+ trace.getActiveSpan()?.setAttributes(attributes);
5768
+ } catch {}
5769
+ }
5770
+ function getSdkToolName(request) {
5771
+ if (!request || typeof request !== "object") return "unknown";
5772
+ const candidate = request.params?.name;
5773
+ return typeof candidate === "string" && SAFE_TOOL_NAME_PATTERN.test(candidate) ? candidate : "unknown";
5774
+ }
5775
+ function markSdkToolFailure(span, error, toolName = sdkToolNameStorage.getStore() ?? "unknown", kind = "tool_call") {
5776
+ const taxonomy = SDK_FAILURE_TAXONOMY[kind];
5777
+ const attributes = createFailureAttributes(error, "sdk", taxonomy.errorType, taxonomy.errorCategory);
5778
+ span.addEvent("mcp.tool.failure", {
5779
+ "mcp.tool.name": toolName,
5780
+ ...attributes
5781
+ });
5782
+ span.setAttribute("error.type", taxonomy.errorType);
5783
+ recordTelemetryException(error, attributes, span);
5784
+ span.setStatus({ code: SpanStatusCode.ERROR });
5785
+ }
5786
+ function installProtocolErrorTracking(server, transport) {
5787
+ const protocol = server.server;
5788
+ if (!protocol) return;
5789
+ const previous = protocol.onerror;
5790
+ protocol.onerror = (error) => {
5791
+ const taxonomy = SDK_FAILURE_TAXONOMY.protocol;
5792
+ const attributes = createFailureAttributes(error, "sdk", taxonomy.errorType, taxonomy.errorCategory);
5793
+ const activeSpan = trace.getActiveSpan();
5794
+ const sessionId = getCurrentMcpSessionId();
5795
+ if (activeSpan) {
5796
+ activeSpan.addEvent("mcp.tool.failure", {
5797
+ "mcp.tool.name": sdkToolNameStorage.getStore() ?? "unknown",
5798
+ ...attributes
5799
+ });
5800
+ recordTelemetryException(error, attributes, activeSpan);
5801
+ } else tracer.startActiveSpan("mcp.sdk.failure", { attributes: {
5802
+ "mcp.span.category": "protocol",
5803
+ "mcp.transport": transport,
5804
+ ...sessionId ? { "mcp.session.id": sessionId } : {}
5805
+ } }, (span) => {
5806
+ span.addEvent("mcp.tool.failure", {
5807
+ "mcp.tool.name": "unknown",
5808
+ ...attributes
5809
+ });
5810
+ recordTelemetryException(error, attributes, span);
5811
+ span.end();
5812
+ });
5813
+ try {
5814
+ previous?.(error);
5815
+ } catch {}
5816
+ };
5817
+ }
5818
+ function installValidationErrorTracking(server) {
5819
+ const toolErrorHost = server;
5820
+ const previousCreateToolError = toolErrorHost.createToolError;
5821
+ if (!previousCreateToolError) return;
5822
+ const createToolError = previousCreateToolError.bind(server);
5823
+ toolErrorHost.createToolError = (message) => {
5824
+ const result = createToolError(message);
5825
+ const activeSpan = trace.getActiveSpan();
5826
+ if (activeSpan) markSdkToolFailure(activeSpan, /* @__PURE__ */ new Error("MCP tool validation failed"), void 0, "validation");
5827
+ return result;
5828
+ };
5829
+ }
5830
+ function installInitializeEnrichment(handlers, transport) {
5831
+ const initializeHandler = handlers.get("initialize");
5832
+ if (!initializeHandler) return;
5833
+ handlers.set("initialize", (request, extra) => {
5834
+ enrichActiveSdkSpan({
5835
+ "mcp.span.category": "protocol",
5836
+ "mcp.transport": transport
5837
+ });
5838
+ return initializeHandler(request, extra);
5839
+ });
5840
+ }
5841
+ function installToolCallTracking(handlers, transport) {
5842
+ const toolHandler = handlers.get("tools/call");
5843
+ if (!toolHandler) return;
5844
+ handlers.set("tools/call", (request, extra) => {
5845
+ const sessionId = getCurrentMcpSessionId();
5846
+ const toolName = getSdkToolName(request);
5847
+ const attributes = {
5848
+ "mcp.span.category": "protocol",
5849
+ "mcp.transport": transport,
5850
+ "mcp.operation.kind": "tool",
5851
+ "mcp.tool.name": toolName,
5852
+ ...sessionId ? { "mcp.session.id": sessionId } : {}
5853
+ };
5854
+ enrichActiveSdkSpan(attributes);
5855
+ return sdkToolNameStorage.run(toolName, () => tracer.startActiveSpan("mcp.sdk.tools.call", { attributes }, async (span) => {
5856
+ try {
5857
+ const result = await toolHandler(request, extra);
5858
+ if (result?.isError === true) {
5859
+ span.setAttribute("mcp.tool.outcome", "returned_error");
5860
+ span.setStatus({ code: SpanStatusCode.ERROR });
5861
+ } else span.setStatus({ code: SpanStatusCode.OK });
5862
+ return result;
5863
+ } catch (error) {
5864
+ markSdkToolFailure(span, error, toolName);
5865
+ throw error;
5866
+ } finally {
5867
+ span.end();
5868
+ }
5869
+ }));
5870
+ });
5871
+ }
5872
+ function installDiscoveryTracking(handlers) {
5873
+ const discoveryHandler = handlers.get("server/discover");
5874
+ if (!discoveryHandler) return;
5875
+ handlers.set("server/discover", (request, extra) => {
5876
+ const sessionId = getCurrentMcpSessionId();
5877
+ return tracer.startActiveSpan("mcp.server.discover", { attributes: {
5878
+ "mcp.span.category": "discovery",
5879
+ "mcp.transport": getCurrentMcpTransport(),
5880
+ ...sessionId ? { "mcp.session.id": sessionId } : {}
5881
+ } }, async (span) => {
5882
+ try {
5883
+ const result = await discoveryHandler(request, extra);
5884
+ span.setStatus({ code: SpanStatusCode.OK });
5885
+ return result;
5886
+ } catch (error) {
5887
+ const attributes = createFailureAttributes(error, "discovery", "UNKNOWN_ERROR", "McpServerDiscoveryFailure");
5888
+ span.addEvent("mcp.discovery.failure", attributes);
5889
+ recordTelemetryException(error, attributes, span);
5890
+ throw error;
5891
+ } finally {
5892
+ span.end();
5893
+ }
5894
+ });
5895
+ });
5896
+ }
5897
+ function installSdkErrorTracking(server, transport) {
5898
+ installProtocolErrorTracking(server, transport);
5899
+ installValidationErrorTracking(server);
5900
+ const handlers = server.server?._requestHandlers;
5901
+ if (!(handlers instanceof Map)) return;
5902
+ installInitializeEnrichment(handlers, transport);
5903
+ installToolCallTracking(handlers, transport);
5904
+ installDiscoveryTracking(handlers);
5905
+ }
5906
+ //#endregion
5731
5907
  //#region src/utils/version-check.ts
5732
5908
  const CACHE_TTL_MS = 1440 * 60 * 1e3;
5733
5909
  const REQUEST_TIMEOUT_MS = 3e3;
@@ -5917,158 +6093,45 @@ function getSafeValidationDiagnostic(error) {
5917
6093
  const code = error.code;
5918
6094
  return typeof code === "string" && SAFE_NETWORK_ERROR_CODES.has(code) ? code : void 0;
5919
6095
  }
5920
- function recordLifecycleFailure(span, error, phase) {
6096
+ const LIFECYCLE_FAILURE_TAXONOMY = {
6097
+ config: {
6098
+ errorType: "MCP_SERVER_CONFIG_ERROR",
6099
+ errorCategory: "McpServerConfigFailure"
6100
+ },
6101
+ api_key_validation: {
6102
+ errorType: "MCP_API_KEY_VALIDATION_ERROR",
6103
+ errorCategory: "McpApiKeyValidationFailure"
6104
+ },
6105
+ build: {
6106
+ errorType: "MCP_SERVER_BUILD_ERROR",
6107
+ errorCategory: "McpServerBuildFailure"
6108
+ },
6109
+ connect: {
6110
+ errorType: "MCP_TRANSPORT_CONNECT_ERROR",
6111
+ errorCategory: "McpTransportConnectFailure"
6112
+ },
6113
+ run: {
6114
+ errorType: "MCP_SERVER_RUN_ERROR",
6115
+ errorCategory: "McpServerRunFailure"
6116
+ }
6117
+ };
6118
+ function createLifecycleFailureAttributes(error, phase) {
5921
6119
  const diagnostic = createSafeErrorDiagnostic(error);
5922
- const attributes = {
6120
+ const taxonomy = LIFECYCLE_FAILURE_TAXONOMY[phase];
6121
+ return {
5923
6122
  "mcp.failure.phase": phase,
5924
- "error.type": diagnostic.category,
5925
- "error.category": diagnostic.category,
6123
+ "error.type": taxonomy.errorType,
6124
+ "error.category": taxonomy.errorCategory,
5926
6125
  ...diagnostic.code ? { "error.code": diagnostic.code } : {},
5927
6126
  ...diagnostic.status !== void 0 ? { "http.response.status_code": diagnostic.status } : {},
5928
6127
  ...diagnostic.method ? { "http.request.method": diagnostic.method } : {},
5929
6128
  ...diagnostic.endpoint ? { "hevy.api.endpoint": diagnostic.endpoint } : {}
5930
6129
  };
5931
- span.addEvent("mcp.lifecycle.failure", {
5932
- "error.type": diagnostic.category,
5933
- "error.category": diagnostic.category,
5934
- ...diagnostic.code ? { "error.code": diagnostic.code } : {}
5935
- });
5936
- recordTelemetryException(error, attributes, span);
5937
- }
5938
- const sdkToolNameStorage = new AsyncLocalStorage();
5939
- const SAFE_TOOL_NAME_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/u;
5940
- function getSdkToolName(request) {
5941
- if (!request || typeof request !== "object") return "unknown";
5942
- const candidate = request.params?.name;
5943
- return typeof candidate === "string" && SAFE_TOOL_NAME_PATTERN.test(candidate) ? candidate : "unknown";
5944
- }
5945
- function markSdkToolFailure(span, error, toolName = sdkToolNameStorage.getStore() ?? "unknown", errorTypeOverride) {
5946
- const diagnostic = createSafeErrorDiagnostic(error);
5947
- const errorType = errorTypeOverride ?? diagnostic.category;
5948
- span.addEvent("mcp.tool.failure", {
5949
- "mcp.tool.name": toolName,
5950
- "error.type": errorType,
5951
- "error.category": diagnostic.category,
5952
- ...diagnostic.code ? { "error.code": diagnostic.code } : {},
5953
- ...diagnostic.status !== void 0 ? { "http.response.status_code": diagnostic.status } : {},
5954
- ...diagnostic.method ? { "http.request.method": diagnostic.method } : {},
5955
- ...diagnostic.endpoint ? { "hevy.api.endpoint": diagnostic.endpoint } : {}
5956
- });
5957
- span.setAttribute("error.type", errorType);
5958
- recordTelemetryException(error, {
5959
- "mcp.failure.phase": "sdk",
5960
- "error.type": errorType,
5961
- "error.category": diagnostic.category,
5962
- ...diagnostic.code ? { "error.code": diagnostic.code } : {},
5963
- ...diagnostic.status !== void 0 ? { "http.response.status_code": diagnostic.status } : {}
5964
- }, span);
5965
- span.setStatus({ code: SpanStatusCode.ERROR });
5966
6130
  }
5967
- function installSdkErrorTracking(server) {
5968
- const protocol = server.server;
5969
- if (!protocol) return;
5970
- const previous = protocol.onerror;
5971
- protocol.onerror = (error) => {
5972
- const diagnostic = createSafeErrorDiagnostic(error);
5973
- const attributes = {
5974
- "mcp.failure.phase": "sdk",
5975
- "error.category": diagnostic.category,
5976
- ...diagnostic.code ? { "error.code": diagnostic.code } : {},
5977
- ...diagnostic.status !== void 0 ? { "http.response.status_code": diagnostic.status } : {}
5978
- };
5979
- const activeSpan = trace.getActiveSpan();
5980
- const sessionId = getCurrentMcpSessionId();
5981
- if (activeSpan) {
5982
- activeSpan.addEvent("mcp.tool.failure", {
5983
- "mcp.tool.name": sdkToolNameStorage.getStore() ?? "unknown",
5984
- "error.type": "UNKNOWN_ERROR",
5985
- "error.category": diagnostic.category,
5986
- ...diagnostic.code ? { "error.code": diagnostic.code } : {}
5987
- });
5988
- recordTelemetryException(error, attributes, activeSpan);
5989
- } else tracer.startActiveSpan("mcp.sdk.failure", { attributes: { ...sessionId ? { "mcp.session.id": sessionId } : {} } }, (span) => {
5990
- span.addEvent("mcp.tool.failure", {
5991
- "mcp.tool.name": "unknown",
5992
- "error.type": "UNKNOWN_ERROR",
5993
- "error.category": diagnostic.category,
5994
- ...diagnostic.code ? { "error.code": diagnostic.code } : {}
5995
- });
5996
- recordTelemetryException(error, attributes, span);
5997
- span.end();
5998
- });
5999
- try {
6000
- previous?.(error);
6001
- } catch {}
6002
- };
6003
- const toolErrorHost = server;
6004
- const previousCreateToolError = toolErrorHost.createToolError;
6005
- if (previousCreateToolError) {
6006
- const createToolError = previousCreateToolError.bind(server);
6007
- toolErrorHost.createToolError = (message) => {
6008
- const result = createToolError(message);
6009
- const activeSpan = trace.getActiveSpan();
6010
- if (activeSpan) markSdkToolFailure(activeSpan, /* @__PURE__ */ new Error("MCP tool validation failed"), void 0, "VALIDATION_ERROR");
6011
- return result;
6012
- };
6013
- }
6014
- const handlers = protocol._requestHandlers;
6015
- if (!(handlers instanceof Map)) return;
6016
- const toolHandler = handlers.get("tools/call");
6017
- if (toolHandler) handlers.set("tools/call", (request, extra) => {
6018
- const sessionId = getCurrentMcpSessionId();
6019
- const toolName = getSdkToolName(request);
6020
- return sdkToolNameStorage.run(toolName, () => tracer.startActiveSpan("mcp.sdk.tools.call", { attributes: {
6021
- "mcp.span.category": "protocol",
6022
- "mcp.operation.kind": "tool",
6023
- "mcp.tool.name": toolName,
6024
- ...sessionId ? { "mcp.session.id": sessionId } : {}
6025
- } }, async (span) => {
6026
- try {
6027
- const result = await toolHandler(request, extra);
6028
- if (result?.isError === true) {
6029
- span.setAttribute("mcp.tool.outcome", "returned_error");
6030
- span.setStatus({ code: SpanStatusCode.ERROR });
6031
- } else span.setStatus({ code: SpanStatusCode.OK });
6032
- return result;
6033
- } catch (error) {
6034
- markSdkToolFailure(span, error, toolName);
6035
- throw error;
6036
- } finally {
6037
- span.end();
6038
- }
6039
- }));
6040
- });
6041
- const discoveryHandler = handlers.get("server/discover");
6042
- if (discoveryHandler) handlers.set("server/discover", (request, extra) => {
6043
- const sessionId = getCurrentMcpSessionId();
6044
- return tracer.startActiveSpan("mcp.server.discover", { attributes: {
6045
- "mcp.span.category": "discovery",
6046
- "mcp.transport": getCurrentMcpTransport(),
6047
- ...sessionId ? { "mcp.session.id": sessionId } : {}
6048
- } }, async (span) => {
6049
- try {
6050
- const result = await discoveryHandler(request, extra);
6051
- span.setStatus({ code: SpanStatusCode.OK });
6052
- return result;
6053
- } catch (error) {
6054
- const diagnostic = createSafeErrorDiagnostic(error);
6055
- span.addEvent("mcp.discovery.failure", {
6056
- "error.type": diagnostic.category,
6057
- "error.category": diagnostic.category,
6058
- ...diagnostic.code ? { "error.code": diagnostic.code } : {}
6059
- });
6060
- recordTelemetryException(error, {
6061
- "mcp.failure.phase": "discovery",
6062
- "error.type": diagnostic.category,
6063
- "error.category": diagnostic.category,
6064
- ...diagnostic.code ? { "error.code": diagnostic.code } : {}
6065
- }, span);
6066
- throw error;
6067
- } finally {
6068
- span.end();
6069
- }
6070
- });
6071
- });
6131
+ function recordLifecycleFailure(span, error, phase) {
6132
+ const attributes = createLifecycleFailureAttributes(error, phase);
6133
+ span.addEvent("mcp.lifecycle.failure", attributes);
6134
+ recordTelemetryException(error, attributes, span);
6072
6135
  }
6073
6136
  async function validateApiKey(apiKey) {
6074
6137
  const startupProbeClient = createHevyClient({
@@ -6108,7 +6171,7 @@ function buildServer(apiKey, transport = "stdio") {
6108
6171
  observer: createNodeToolObserver(),
6109
6172
  cacheObserver: createNodeCacheObserver()
6110
6173
  });
6111
- installSdkErrorTracking(server);
6174
+ installSdkErrorTracking(server, transport);
6112
6175
  console.error("Hevy client initialized with API key");
6113
6176
  span.setStatus({ code: SpanStatusCode.OK });
6114
6177
  return server;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hevy-mcp",
3
- "version": "5.0.4",
3
+ "version": "5.0.5",
4
4
  "private": false,
5
5
  "description": "A Model Context Protocol (MCP) server implementation that interfaces with the Hevy fitness tracking app and its API.",
6
6
  "repository": {
package/server.json CHANGED
@@ -7,12 +7,12 @@
7
7
  "url": "https://github.com/chrisdoc/hevy-mcp",
8
8
  "source": "github"
9
9
  },
10
- "version": "5.0.4",
10
+ "version": "5.0.5",
11
11
  "packages": [
12
12
  {
13
13
  "registryType": "npm",
14
14
  "identifier": "hevy-mcp",
15
- "version": "5.0.4",
15
+ "version": "5.0.5",
16
16
  "transport": {
17
17
  "type": "stdio"
18
18
  },