hevy-mcp 5.0.5 → 5.0.6
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 +4 -4
- package/dist/cli.mjs +2 -2
- package/dist/index.mjs +2 -2
- package/dist/{src-TBD9ENR3.mjs → src-CT0BzqOm.mjs} +46 -78
- package/package.json +3 -3
- package/server.json +2 -2
package/README.md
CHANGED
|
@@ -423,7 +423,7 @@ self-hosted Streamable HTTP.
|
|
|
423
423
|
| `HEVY_MCP_HTTP_BEARER_TOKEN` | None | Non-loopback HTTP | Required when `--host` is not loopback; use a separate token, never the Hevy API key. |
|
|
424
424
|
| `HEVY_MCP_TELEMETRY` | Enabled | Local Node | Set to exactly `0` before startup/import to disable Sentry errors/traces and OTLP traces/metrics. Takes precedence over `SENTRY_DSN` and packaged/runtime collector credentials. |
|
|
425
425
|
| `XDG_CACHE_HOME` | `~/.cache` | Local stdio | Changes the root for the npm update-check cache at `hevy-mcp/update-check.json`. |
|
|
426
|
-
| `SENTRY_DSN` | Packaged project DSN
|
|
426
|
+
| `SENTRY_DSN` | Packaged GlitchTip project DSN | Optional local Node telemetry | Sentry-compatible override for the destination. An empty value disables Sentry export. The Worker does not import Node telemetry. |
|
|
427
427
|
| `SENTRY_RELEASE` | `hevy-mcp@<installed-version>` | Optional local Node telemetry | Overrides the release label attached to local Sentry events and traces. |
|
|
428
428
|
| `-h`, `--help` | N/A | Local stdio CLI | Print supported options and exit. |
|
|
429
429
|
| `-v`, `--version` | N/A | Local stdio CLI | Print the installed version and exit. |
|
|
@@ -474,9 +474,9 @@ metric readers and makes no telemetry network requests. `SENTRY_DSN` remains a
|
|
|
474
474
|
Sentry-only setting; when telemetry is enabled, an empty value disables only
|
|
475
475
|
Sentry export.
|
|
476
476
|
|
|
477
|
-
When enabled, errors
|
|
478
|
-
<https://
|
|
479
|
-
metrics
|
|
477
|
+
When enabled, errors are sent to the self-hosted GlitchTip project at
|
|
478
|
+
<https://glitchtip.chrisdoc.dev>; Sentry performance tracing is disabled.
|
|
479
|
+
Traces and metrics continue to be sent to the collector at
|
|
480
480
|
<https://otel.chrisdoc.dev/v1/traces> and
|
|
481
481
|
<https://otel.chrisdoc.dev/v1/metrics>, which forward to Honeycomb. Metrics
|
|
482
482
|
export every 10 seconds.
|
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.
|
|
7
|
+
e.SENTRY_RELEASE = { id: "hevy-mcp@5.0.6" };
|
|
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-
|
|
12
|
+
import { a as createSafeErrorDiagnostic, i as MissingHevyApiKeyError, n as runServer, o as flushTelemetry } from "./src-CT0BzqOm.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.
|
|
7
|
+
e.SENTRY_RELEASE = { id: "hevy-mcp@5.0.6" };
|
|
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-
|
|
12
|
+
import { n as runServer, r as runStdioServer, t as createNodeMcpServer } from "./src-CT0BzqOm.mjs";
|
|
13
13
|
export { createNodeMcpServer, runServer, runStdioServer };
|
|
@@ -4,19 +4,18 @@
|
|
|
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.
|
|
7
|
+
e.SENTRY_RELEASE = { id: "hevy-mcp@5.0.6" };
|
|
8
8
|
var n = new e.Error().stack;
|
|
9
|
-
n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "
|
|
9
|
+
n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "8b83767c-bc1c-4e67-8601-3cf4da13a8f9", e._sentryDebugIdIdentifier = "sentry-dbid-8b83767c-bc1c-4e67-8601-3cf4da13a8f9");
|
|
10
10
|
} catch (e) {}
|
|
11
11
|
})();
|
|
12
12
|
import { createHmac, randomBytes, randomUUID, timingSafeEqual } from "node:crypto";
|
|
13
13
|
import * as Sentry from "@sentry/node";
|
|
14
|
-
import { SentryPropagator, SentrySampler, SentrySpanProcessor } from "@sentry/opentelemetry";
|
|
15
14
|
import { SpanStatusCode, context, metrics, trace } from "@opentelemetry/api";
|
|
16
15
|
import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http";
|
|
17
16
|
import { AggregationTemporalityPreference, OTLPMetricExporter } from "@opentelemetry/exporter-metrics-otlp-http";
|
|
18
17
|
import { resourceFromAttributes } from "@opentelemetry/resources";
|
|
19
|
-
import { BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
|
|
18
|
+
import { AlwaysOnSampler, BatchSpanProcessor } from "@opentelemetry/sdk-trace-base";
|
|
20
19
|
import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
|
|
21
20
|
import { MeterProvider, PeriodicExportingMetricReader } from "@opentelemetry/sdk-metrics";
|
|
22
21
|
import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
|
|
@@ -31,52 +30,15 @@ import { mkdir, readFile, rename, unlink, writeFile } from "node:fs/promises";
|
|
|
31
30
|
import { homedir } from "node:os";
|
|
32
31
|
import { dirname, join } from "node:path";
|
|
33
32
|
import semver from "semver";
|
|
34
|
-
//#region src/utils/sentry-privacy.ts
|
|
35
|
-
const SENTRY_PROHIBITED_MCP_ATTRIBUTES = /* @__PURE__ */ new Set([
|
|
36
|
-
"mcp.request.id",
|
|
37
|
-
"mcp.session.id",
|
|
38
|
-
"mcp.cancelled.request_id",
|
|
39
|
-
"mcp.cancelled.reason",
|
|
40
|
-
"mcp.progress.token",
|
|
41
|
-
"mcp.progress.message",
|
|
42
|
-
"mcp.resource.uri",
|
|
43
|
-
"mcp.method.name",
|
|
44
|
-
"mcp.resource.protocol",
|
|
45
|
-
"mcp.prompt.name",
|
|
46
|
-
"mcp.protocol.version",
|
|
47
|
-
"mcp.logging.message",
|
|
48
|
-
"mcp.prompt.result.description",
|
|
49
|
-
"mcp.request.argument",
|
|
50
|
-
"mcp.logging.logger",
|
|
51
|
-
"mcp.logging.level",
|
|
52
|
-
"mcp.client.name",
|
|
53
|
-
"mcp.client.title",
|
|
54
|
-
"mcp.client.version"
|
|
55
|
-
]);
|
|
56
|
-
/** Remove MCP correlation and unbounded client fields before Sentry export. */
|
|
57
|
-
function sanitizeSentryMcpSpan(span) {
|
|
58
|
-
if (!span.data) return span;
|
|
59
|
-
let sanitizedData;
|
|
60
|
-
for (const key of SENTRY_PROHIBITED_MCP_ATTRIBUTES) {
|
|
61
|
-
if (!(key in span.data)) continue;
|
|
62
|
-
sanitizedData ??= { ...span.data };
|
|
63
|
-
delete sanitizedData[key];
|
|
64
|
-
}
|
|
65
|
-
return sanitizedData ? {
|
|
66
|
-
...span,
|
|
67
|
-
data: sanitizedData
|
|
68
|
-
} : span;
|
|
69
|
-
}
|
|
70
|
-
//#endregion
|
|
71
33
|
//#region src/utils/telemetry.ts
|
|
72
34
|
/**
|
|
73
35
|
* Centralized telemetry initialization.
|
|
74
36
|
*
|
|
75
37
|
* This module MUST be imported before any other application code.
|
|
76
|
-
* It sets up
|
|
77
|
-
*
|
|
38
|
+
* It sets up independent telemetry paths: Sentry error events and an OTel
|
|
39
|
+
* Collector (traces + metrics to Honeycomb).
|
|
78
40
|
*
|
|
79
|
-
* Sentry SDK: error
|
|
41
|
+
* Sentry SDK: error monitoring, release tracking
|
|
80
42
|
* OTel Collector → Honeycomb: performance traces, metrics
|
|
81
43
|
*/
|
|
82
44
|
const PROCESS_FAILURE_TAXONOMY = {
|
|
@@ -169,11 +131,12 @@ function installProcessExceptionTracking(processLike = process) {
|
|
|
169
131
|
};
|
|
170
132
|
}
|
|
171
133
|
const name$1 = "hevy-mcp";
|
|
172
|
-
const version$1 = "5.0.
|
|
134
|
+
const version$1 = "5.0.6";
|
|
173
135
|
const telemetryEnabled = process.env.HEVY_MCP_TELEMETRY !== "0";
|
|
174
136
|
const collectorToken = "NH9vOela-HYreQxAbJa68cjEmORoEKM57EvneUDVcOo";
|
|
175
137
|
const COLLECTOR_ENDPOINT = "https://otel.chrisdoc.dev/v1";
|
|
176
138
|
const sentryRelease = process.env.SENTRY_RELEASE ?? `${name$1}@${version$1}`;
|
|
139
|
+
const DEFAULT_SENTRY_DSN = "https://7c08d2c880ff4560a333dff4833594cd@glitchtip.chrisdoc.dev/1";
|
|
177
140
|
function createServiceInstanceId(generate = randomUUID) {
|
|
178
141
|
try {
|
|
179
142
|
const generated = generate();
|
|
@@ -200,32 +163,28 @@ var UserHashSpanProcessor = class {
|
|
|
200
163
|
let tracerProvider;
|
|
201
164
|
let meterProvider;
|
|
202
165
|
if (telemetryEnabled) {
|
|
203
|
-
const rawDsn = process.env.SENTRY_DSN ??
|
|
166
|
+
const rawDsn = process.env.SENTRY_DSN ?? DEFAULT_SENTRY_DSN;
|
|
204
167
|
const isValidDsn = typeof rawDsn === "string" && rawDsn.length > 0 && !rawDsn.startsWith("*");
|
|
205
|
-
|
|
168
|
+
Sentry.init({
|
|
206
169
|
dsn: isValidDsn ? rawDsn : void 0,
|
|
207
|
-
beforeSendSpan: sanitizeSentryMcpSpan,
|
|
208
170
|
release: sentryRelease,
|
|
209
|
-
tracesSampleRate:
|
|
171
|
+
tracesSampleRate: 0,
|
|
210
172
|
sendDefaultPii: false,
|
|
211
173
|
skipOpenTelemetrySetup: true,
|
|
212
174
|
registerEsmLoaderHooks: false,
|
|
213
175
|
ignoreErrors: ["EPIPE", "broken pipe"]
|
|
214
176
|
});
|
|
215
|
-
const spanProcessors = [new UserHashSpanProcessor()
|
|
177
|
+
const spanProcessors = [new UserHashSpanProcessor()];
|
|
216
178
|
spanProcessors.push(new BatchSpanProcessor(new OTLPTraceExporter({
|
|
217
179
|
url: `${COLLECTOR_ENDPOINT}/traces`,
|
|
218
180
|
headers: { Authorization: `Bearer ${collectorToken}` }
|
|
219
181
|
})));
|
|
220
182
|
tracerProvider = new NodeTracerProvider({
|
|
221
183
|
resource,
|
|
222
|
-
sampler:
|
|
184
|
+
sampler: new AlwaysOnSampler(),
|
|
223
185
|
spanProcessors
|
|
224
186
|
});
|
|
225
|
-
tracerProvider.register(
|
|
226
|
-
propagator: new SentryPropagator(),
|
|
227
|
-
contextManager: new Sentry.SentryContextManager()
|
|
228
|
-
});
|
|
187
|
+
tracerProvider.register();
|
|
229
188
|
meterProvider = new MeterProvider({
|
|
230
189
|
resource,
|
|
231
190
|
readers: [new PeriodicExportingMetricReader({
|
|
@@ -234,12 +193,11 @@ if (telemetryEnabled) {
|
|
|
234
193
|
headers: { Authorization: `Bearer ${collectorToken}` },
|
|
235
194
|
temporalityPreference: AggregationTemporalityPreference.DELTA
|
|
236
195
|
}),
|
|
237
|
-
exportIntervalMillis:
|
|
196
|
+
exportIntervalMillis: 3e4
|
|
238
197
|
})]
|
|
239
198
|
});
|
|
240
199
|
metrics.setGlobalMeterProvider(meterProvider);
|
|
241
200
|
trace.setGlobalTracerProvider(tracerProvider);
|
|
242
|
-
Sentry.validateOpenTelemetrySetup();
|
|
243
201
|
}
|
|
244
202
|
async function flushTelemetry(timeoutMs = 1e3) {
|
|
245
203
|
if (!telemetryEnabled) return;
|
|
@@ -1060,7 +1018,7 @@ function isHevyHttpError(error) {
|
|
|
1060
1018
|
const DEFAULT_API_TIMEOUT_MS = 3e4;
|
|
1061
1019
|
const RETRY_BACKOFF_MAX_MS = 5e3;
|
|
1062
1020
|
const RETRYABLE_STATUS_CODES = /* @__PURE__ */ new Set([408, 429]);
|
|
1063
|
-
const SAFE_STATIC_ENDPOINTS = /* @__PURE__ */ new Set([
|
|
1021
|
+
const SAFE_STATIC_ENDPOINTS$1 = /* @__PURE__ */ new Set([
|
|
1064
1022
|
"/v1/body_measurements",
|
|
1065
1023
|
"/v1/exercise_templates",
|
|
1066
1024
|
"/v1/routine_folders",
|
|
@@ -1099,7 +1057,7 @@ const SAFE_OBSERVATION_CODES = /* @__PURE__ */ new Set([
|
|
|
1099
1057
|
HEVY_REQUEST_ABORTED_ERROR_CODE,
|
|
1100
1058
|
HEVY_RETRY_EXHAUSTED_ERROR_CODE
|
|
1101
1059
|
]);
|
|
1102
|
-
const SAFE_DYNAMIC_ENDPOINTS = [
|
|
1060
|
+
const SAFE_DYNAMIC_ENDPOINTS$1 = [
|
|
1103
1061
|
["/v1/body_measurements/", "/v1/body_measurements/:date"],
|
|
1104
1062
|
["/v1/exercise_history/", "/v1/exercise_history/:exerciseTemplateId"],
|
|
1105
1063
|
["/v1/exercise_templates/", "/v1/exercise_templates/:exerciseTemplateId"],
|
|
@@ -1142,8 +1100,8 @@ function getRequestContext(config) {
|
|
|
1142
1100
|
const method = (config.method ?? "GET").toUpperCase();
|
|
1143
1101
|
const rawEndpoint = (config.url ?? "").split("?")[0] ?? "";
|
|
1144
1102
|
let endpoint = "unknown";
|
|
1145
|
-
if (SAFE_STATIC_ENDPOINTS.has(rawEndpoint)) endpoint = rawEndpoint;
|
|
1146
|
-
else endpoint = SAFE_DYNAMIC_ENDPOINTS.find(([prefix]) => rawEndpoint.startsWith(prefix))?.[1] ?? "unknown";
|
|
1103
|
+
if (SAFE_STATIC_ENDPOINTS$1.has(rawEndpoint)) endpoint = rawEndpoint;
|
|
1104
|
+
else endpoint = SAFE_DYNAMIC_ENDPOINTS$1.find(([prefix]) => rawEndpoint.startsWith(prefix))?.[1] ?? "unknown";
|
|
1147
1105
|
const page = config.params !== null && typeof config.params === "object" && "page" in config.params && typeof config.params.page === "number" ? config.params.page : void 0;
|
|
1148
1106
|
return {
|
|
1149
1107
|
method,
|
|
@@ -2844,7 +2802,7 @@ function registerHevyResources(server, runtime) {
|
|
|
2844
2802
|
//#endregion
|
|
2845
2803
|
//#region ../core/src/server-metadata.ts
|
|
2846
2804
|
const SERVER_NAME = "hevy-mcp";
|
|
2847
|
-
const SERVER_VERSION = "5.0.
|
|
2805
|
+
const SERVER_VERSION = "5.0.6";
|
|
2848
2806
|
const SERVER_INSTRUCTIONS = [
|
|
2849
2807
|
"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.",
|
|
2850
2808
|
"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.",
|
|
@@ -5195,6 +5153,29 @@ function debugLog(event, data) {
|
|
|
5195
5153
|
}
|
|
5196
5154
|
//#endregion
|
|
5197
5155
|
//#region src/utils/hevy-client-observability.ts
|
|
5156
|
+
const SAFE_STATIC_ENDPOINTS = /* @__PURE__ */ new Set([
|
|
5157
|
+
"/v1/body_measurements",
|
|
5158
|
+
"/v1/exercise_templates",
|
|
5159
|
+
"/v1/routine_folders",
|
|
5160
|
+
"/v1/routines",
|
|
5161
|
+
"/v1/user/info",
|
|
5162
|
+
"/v1/workouts",
|
|
5163
|
+
"/v1/workouts/count",
|
|
5164
|
+
"/v1/workouts/events"
|
|
5165
|
+
]);
|
|
5166
|
+
const SAFE_DYNAMIC_ENDPOINTS = [
|
|
5167
|
+
["/v1/body_measurements/", "/v1/body_measurements/:date"],
|
|
5168
|
+
["/v1/exercise_history/", "/v1/exercise_history/:exerciseTemplateId"],
|
|
5169
|
+
["/v1/exercise_templates/", "/v1/exercise_templates/:exerciseTemplateId"],
|
|
5170
|
+
["/v1/routine_folders/", "/v1/routine_folders/:folderId"],
|
|
5171
|
+
["/v1/routines/", "/v1/routines/:routineId"],
|
|
5172
|
+
["/v1/workouts/", "/v1/workouts/:workoutId"]
|
|
5173
|
+
];
|
|
5174
|
+
function normalizeHevyMetricEndpoint(endpoint) {
|
|
5175
|
+
const path = endpoint.split("?")[0] ?? "";
|
|
5176
|
+
if (SAFE_STATIC_ENDPOINTS.has(path)) return path;
|
|
5177
|
+
return SAFE_DYNAMIC_ENDPOINTS.find(([prefix]) => path.startsWith(prefix))?.[1] ?? "unknown";
|
|
5178
|
+
}
|
|
5198
5179
|
function safeErrorAttributes(observation) {
|
|
5199
5180
|
if (!observation.error) return {};
|
|
5200
5181
|
const code = observation.error.code;
|
|
@@ -5248,9 +5229,10 @@ function createNodeHevyClientOptions() {
|
|
|
5248
5229
|
onRequestComplete(observation) {
|
|
5249
5230
|
const retryCountBucket = bucketCount(observation.retryCount);
|
|
5250
5231
|
const errorAttributes = safeErrorAttributes(observation);
|
|
5232
|
+
const metricEndpoint = normalizeHevyMetricEndpoint(observation.endpoint);
|
|
5251
5233
|
apiCalls.add(1, {
|
|
5252
5234
|
method: observation.method,
|
|
5253
|
-
endpoint:
|
|
5235
|
+
endpoint: metricEndpoint,
|
|
5254
5236
|
status_code: observation.status,
|
|
5255
5237
|
retry_count_bucket: retryCountBucket,
|
|
5256
5238
|
outcome: observation.outcome,
|
|
@@ -5260,7 +5242,7 @@ function createNodeHevyClientOptions() {
|
|
|
5260
5242
|
});
|
|
5261
5243
|
apiDuration.record(observation.durationMs, {
|
|
5262
5244
|
method: observation.method,
|
|
5263
|
-
endpoint:
|
|
5245
|
+
endpoint: metricEndpoint,
|
|
5264
5246
|
retry_count_bucket: retryCountBucket,
|
|
5265
5247
|
outcome: observation.outcome,
|
|
5266
5248
|
transport: getCurrentMcpTransport(),
|
|
@@ -5370,19 +5352,6 @@ function setResultAttributes(span, completion) {
|
|
|
5370
5352
|
for (const [resource, pageCount] of Object.entries(summary.workflow.pagination)) if (WORKFLOW_PAGINATION_RESOURCES.has(resource) && Number.isSafeInteger(pageCount) && pageCount >= 0) span.setAttribute(`workflow.pagination.${resource}.pages`, pageCount);
|
|
5371
5353
|
}
|
|
5372
5354
|
}
|
|
5373
|
-
function resultMetricAttributes(completion) {
|
|
5374
|
-
const result = completion.result;
|
|
5375
|
-
if (!result) return {};
|
|
5376
|
-
const attributes = {
|
|
5377
|
-
"mcp.tool.result.has_structured_content": result.hasStructuredContent,
|
|
5378
|
-
"mcp.tool.result.content_count_bucket": result.contentCountBucket
|
|
5379
|
-
};
|
|
5380
|
-
const summary = result.summary;
|
|
5381
|
-
if (summary?.itemCountBucket) attributes["mcp.tool.result.item_count_bucket"] = summary.itemCountBucket;
|
|
5382
|
-
if (summary?.exerciseCountBucket) attributes["mcp.tool.result.exercise_count_bucket"] = summary.exerciseCountBucket;
|
|
5383
|
-
if (summary?.setCountBucket) attributes["mcp.tool.result.set_count_bucket"] = summary.setCountBucket;
|
|
5384
|
-
return attributes;
|
|
5385
|
-
}
|
|
5386
5355
|
function setSafeErrorAttributes(span, invocation, completion) {
|
|
5387
5356
|
const diagnostic = completion.error;
|
|
5388
5357
|
const errorType = completion.errorType ?? "UNKNOWN_ERROR";
|
|
@@ -5504,7 +5473,6 @@ function createNodeToolObserver() {
|
|
|
5504
5473
|
}
|
|
5505
5474
|
bestEffort(() => toolDuration.record(durationMs, {
|
|
5506
5475
|
...metrics,
|
|
5507
|
-
...resultMetricAttributes(nextCompletion),
|
|
5508
5476
|
is_error: String(isError),
|
|
5509
5477
|
outcome: nextCompletion.outcome
|
|
5510
5478
|
}));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hevy-mcp",
|
|
3
|
-
"version": "5.0.
|
|
3
|
+
"version": "5.0.6",
|
|
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": {
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"@opentelemetry/sdk-metrics": "^2.10.0",
|
|
44
44
|
"@opentelemetry/sdk-trace-base": "^2.10.0",
|
|
45
45
|
"@opentelemetry/sdk-trace-node": "^2.10.0",
|
|
46
|
-
"@sentry/node": "^10.
|
|
46
|
+
"@sentry/node": "^10.69.0",
|
|
47
47
|
"@sentry/opentelemetry": "^10.68.0",
|
|
48
48
|
"semver": "^7.8.5",
|
|
49
49
|
"zod": "^4.4.3"
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"devDependencies": {
|
|
52
52
|
"@hevy-mcp/core": "*",
|
|
53
53
|
"@hevy-mcp/hevy-client": "*",
|
|
54
|
-
"@types/node": "^26.1.
|
|
54
|
+
"@types/node": "^26.1.2",
|
|
55
55
|
"cross-env": "^10.1.0",
|
|
56
56
|
"tsdown": "^0.22.14",
|
|
57
57
|
"typescript": "^7.0.2"
|
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.
|
|
10
|
+
"version": "5.0.6",
|
|
11
11
|
"packages": [
|
|
12
12
|
{
|
|
13
13
|
"registryType": "npm",
|
|
14
14
|
"identifier": "hevy-mcp",
|
|
15
|
-
"version": "5.0.
|
|
15
|
+
"version": "5.0.6",
|
|
16
16
|
"transport": {
|
|
17
17
|
"type": "stdio"
|
|
18
18
|
},
|