hevy-mcp 1.26.2 → 1.26.4

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 CHANGED
@@ -40,14 +40,14 @@ Pick the workflow that fits your setup:
40
40
 
41
41
  | Scenario | Command | Requirements |
42
42
  | :-------------------- | :------------------------------------------------------------------------------------------ | :------------------------- |
43
- | **One-off stdio run** | `HEVY_API_KEY=sk_live... npx -y hevy-mcp` or `HEVY_API_KEY=sk_live... bunx hevy-mcp@latest` | Node.js ≥ 26, Hevy API key |
43
+ | **One-off stdio run** | `HEVY_API_KEY=sk_live... npx -y hevy-mcp` or `HEVY_API_KEY=sk_live... bunx hevy-mcp@latest` | Node.js ≥ 24, Hevy API key |
44
44
  | **Local development** | `npm install && npm run build && npm start` | `.env` with `HEVY_API_KEY` |
45
45
 
46
46
  ---
47
47
 
48
48
  ## 🛠️ Prerequisites
49
49
 
50
- - **Node.js**: v26 or higher (strongly recommended to use the exact version pinned in `.nvmrc`).
50
+ - **Node.js**: v24 or higher (strongly recommended to use the exact version pinned in `.nvmrc`).
51
51
  - **npm**: v10 or higher.
52
52
  - **Bun** (optional): If you want to launch with `bunx`.
53
53
  - **Hevy API key**: Required for all operations (available with Hevy PRO).
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@1.26.2" };
7
+ e.SENTRY_RELEASE = { id: "hevy-mcp@1.26.4" };
8
8
  var n = new e.Error().stack;
9
9
  n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "03cf150f-6466-4ca3-9cf1-e423cc0e3cd2", e._sentryDebugIdIdentifier = "sentry-dbid-03cf150f-6466-4ca3-9cf1-e423cc0e3cd2");
10
10
  } catch (e) {}
11
11
  })();
12
- import { r as runServer } from "./src-CuOZcBEo.mjs";
12
+ import { r as runServer } from "./src-DSiZLCgu.mjs";
13
13
  //#region src/cli.ts
14
14
  runServer().catch((error) => {
15
15
  console.error("Fatal error in main():", error);
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@1.26.2" };
7
+ e.SENTRY_RELEASE = { id: "hevy-mcp@1.26.4" };
8
8
  var n = new e.Error().stack;
9
9
  n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "5b077b94-9ef8-4f24-a0b0-8dcfbf491be1", e._sentryDebugIdIdentifier = "sentry-dbid-5b077b94-9ef8-4f24-a0b0-8dcfbf491be1");
10
10
  } catch (e) {}
11
11
  })();
12
- import { n as createServer, r as runServer, t as configSchema } from "./src-CuOZcBEo.mjs";
12
+ import { n as createServer, r as runServer, t as configSchema } from "./src-DSiZLCgu.mjs";
13
13
  export { configSchema, createServer, createServer as default, runServer };
@@ -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@1.26.2" };
7
+ e.SENTRY_RELEASE = { id: "hevy-mcp@1.26.4" };
8
8
  var n = new e.Error().stack;
9
- n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "425564da-031b-406e-b160-907df2faf2eb", e._sentryDebugIdIdentifier = "sentry-dbid-425564da-031b-406e-b160-907df2faf2eb");
9
+ n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "38ab92ce-2e6e-45ef-bcda-d9cbe2100f4a", e._sentryDebugIdIdentifier = "sentry-dbid-38ab92ce-2e6e-45ef-bcda-d9cbe2100f4a");
10
10
  } catch (e) {}
11
11
  })();
12
12
  import * as Sentry from "@sentry/node";
@@ -36,10 +36,10 @@ import { deserializeMessage } from "@modelcontextprotocol/sdk/shared/stdio.js";
36
36
  * OTel Collector → Honeycomb: performance traces, metrics
37
37
  */
38
38
  const name$1 = "hevy-mcp";
39
- const version$1 = "1.26.2";
39
+ const version$1 = "1.26.4";
40
40
  const collectorToken = process.env.OTEL_COLLECTOR_TOKEN ?? "";
41
41
  const COLLECTOR_ENDPOINT = "https://otel.chrisdoc.dev/v1";
42
- const sentryRelease = process.env.SENTRY_RELEASE ?? `hevy-mcp@1.26.2`;
42
+ const sentryRelease = process.env.SENTRY_RELEASE ?? `hevy-mcp@1.26.4`;
43
43
  const resource = resourceFromAttributes({
44
44
  "service.name": name$1,
45
45
  "service.version": version$1
@@ -2467,4 +2467,4 @@ async function runServer() {
2467
2467
  //#endregion
2468
2468
  export { createServer as n, runServer as r, configSchema as t };
2469
2469
 
2470
- //# sourceMappingURL=src-CuOZcBEo.mjs.map
2470
+ //# sourceMappingURL=src-DSiZLCgu.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"src-CuOZcBEo.mjs","names":["name","version","normalizeHeaderValue","getHeaderValue","normalizedConfig","createClient","api.getV1Workouts","api.getV1WorkoutsWorkoutid","api.postV1Workouts","api.putV1WorkoutsWorkoutid","api.getV1WorkoutsCount","api.getV1WorkoutsEvents","api.getV1Routines","api.getV1RoutinesRoutineid","api.postV1Routines","api.putV1RoutinesRoutineid","api.getV1ExerciseTemplates","api.getV1ExerciseTemplatesExercisetemplateid","api.getV1ExerciseHistoryExercisetemplateid","api.postV1ExerciseTemplates","api.getV1RoutineFolders","api.postV1RoutineFolders","api.getV1RoutineFoldersFolderid","api.getV1BodyMeasurements","api.getV1BodyMeasurementsDate","api.postV1BodyMeasurements","api.putV1BodyMeasurementsDate","api.getV1UserInfo","createKubbClient","serviceName","serviceVersion"],"sources":["../src/utils/telemetry.ts","../src/utils/metrics.ts","../src/utils/error-handler.ts","../src/utils/formatters.ts","../src/utils/response-formatter.ts","../src/utils/tool-annotations.ts","../src/utils/tool-helpers.ts","../src/utils/schemas.ts","../src/tools/body-measurements.ts","../src/tools/folders.ts","../src/utils/json-parser.ts","../src/tools/routines.ts","../src/utils/cache.ts","../src/tools/templates.ts","../src/tools/user.ts","../src/tools/workouts.ts","../src/utils/config.ts","../src/generated/.kubb/fetch.ts","../src/generated/client/api/getV1BodyMeasurements.ts","../src/generated/client/api/getV1BodyMeasurementsDate.ts","../src/generated/client/api/getV1ExerciseHistoryExercisetemplateid.ts","../src/generated/client/api/getV1ExerciseTemplates.ts","../src/generated/client/api/getV1ExerciseTemplatesExercisetemplateid.ts","../src/generated/client/api/getV1RoutineFolders.ts","../src/generated/client/api/getV1RoutineFoldersFolderid.ts","../src/generated/client/api/getV1Routines.ts","../src/generated/client/api/getV1RoutinesRoutineid.ts","../src/generated/client/api/getV1UserInfo.ts","../src/generated/client/api/getV1Workouts.ts","../src/generated/client/api/getV1WorkoutsCount.ts","../src/generated/client/api/getV1WorkoutsEvents.ts","../src/generated/client/api/getV1WorkoutsWorkoutid.ts","../src/generated/client/api/postV1BodyMeasurements.ts","../src/generated/client/api/postV1ExerciseTemplates.ts","../src/generated/client/api/postV1RoutineFolders.ts","../src/generated/client/api/postV1Routines.ts","../src/generated/client/api/postV1Workouts.ts","../src/generated/client/api/putV1BodyMeasurementsDate.ts","../src/generated/client/api/putV1RoutinesRoutineid.ts","../src/generated/client/api/putV1WorkoutsWorkoutid.ts","../src/utils/hevyClientKubb.ts","../src/utils/hevyClient.ts","../src/utils/stdio-observability.ts","../src/index.ts"],"sourcesContent":["/**\n * Centralized telemetry initialization.\n *\n * This module MUST be imported before any other application code.\n * It sets up OpenTelemetry with dual export: Sentry (error events +\n * traces) and an OTel Collector (traces + metrics to Honeycomb).\n *\n * Sentry SDK: error events, performance traces, release tracking\n * OTel Collector → Honeycomb: performance traces, metrics\n */\n\nimport * as Sentry from \"@sentry/node\";\nimport {\n\tSentryPropagator,\n\tSentrySampler,\n\tSentrySpanProcessor,\n} from \"@sentry/opentelemetry\";\nimport { trace, metrics } from \"@opentelemetry/api\";\nimport { OTLPTraceExporter } from \"@opentelemetry/exporter-trace-otlp-http\";\nimport { OTLPMetricExporter } from \"@opentelemetry/exporter-metrics-otlp-http\";\nimport { resourceFromAttributes } from \"@opentelemetry/resources\";\nimport { BatchSpanProcessor } from \"@opentelemetry/sdk-trace-base\";\nimport type { SpanProcessor } from \"@opentelemetry/sdk-trace\";\nimport { NodeTracerProvider } from \"@opentelemetry/sdk-trace-node\";\nimport {\n\tMeterProvider,\n\tPeriodicExportingMetricReader,\n} from \"@opentelemetry/sdk-metrics\";\n\ndeclare const __HEVY_MCP_NAME__: string | undefined;\ndeclare const __HEVY_MCP_VERSION__: string | undefined;\ndeclare const __HEVY_MCP_BUILD__: boolean | undefined;\ndeclare const __OTEL_COLLECTOR_TOKEN__: string | undefined;\n\nconst name =\n\ttypeof __HEVY_MCP_NAME__ === \"string\" ? __HEVY_MCP_NAME__ : \"hevy-mcp\";\nconst version =\n\ttypeof __HEVY_MCP_VERSION__ === \"string\" ? __HEVY_MCP_VERSION__ : \"dev\";\n\n// Collector token is injected at build time from the OTEL_COLLECTOR_TOKEN\n// GitHub secret via tsdown.config.ts define. The collector forwards\n// traces and metrics to Honeycomb, keeping the Honeycomb API key off the\n// client. The collector endpoint is public (behind Cloudflare Tunnel).\nconst collectorToken =\n\ttypeof __OTEL_COLLECTOR_TOKEN__ === \"string\" && __OTEL_COLLECTOR_TOKEN__\n\t\t? __OTEL_COLLECTOR_TOKEN__\n\t\t: (process.env.OTEL_COLLECTOR_TOKEN ?? \"\");\n\nconst COLLECTOR_ENDPOINT = \"https://otel.chrisdoc.dev/v1\";\n\nconst sentryRelease = process.env.SENTRY_RELEASE ?? `${name}@${version}`;\n\nconst resource = resourceFromAttributes({\n\t\"service.name\": name,\n\t\"service.version\": version,\n});\n\nconst bakedDsn =\n\t\"https://ce696d8333b507acbf5203eb877bce0f@o4508975499575296.ingest.de.sentry.io/4509049671647312\";\nconst rawDsn = process.env.SENTRY_DSN ?? bakedDsn;\nconst isValidDsn =\n\ttypeof rawDsn === \"string\" && rawDsn.length > 0 && !rawDsn.startsWith(\"*\");\n\n// --- Sentry (error monitoring + traces) ---\nconst sentryClient = Sentry.init({\n\tdsn: isValidDsn ? rawDsn : undefined,\n\trelease: sentryRelease,\n\ttracesSampleRate: 1.0,\n\tsendDefaultPii: false,\n\tskipOpenTelemetrySetup: true,\n\tregisterEsmLoaderHooks: false,\n\tignoreErrors: [\"EPIPE\", \"broken pipe\"],\n});\n\n// --- OpenTelemetry tracer provider (dual export) ---\nconst spanProcessors: SpanProcessor[] = [new SentrySpanProcessor()];\n\n// Span processor 2: OTel Collector → Honeycomb (traces) — only if token is available\nif (collectorToken) {\n\tspanProcessors.push(\n\t\tnew BatchSpanProcessor(\n\t\t\tnew OTLPTraceExporter({\n\t\t\t\turl: `${COLLECTOR_ENDPOINT}/traces`,\n\t\t\t\theaders: {\n\t\t\t\t\tAuthorization: `Bearer ${collectorToken}`,\n\t\t\t\t},\n\t\t\t}),\n\t\t),\n\t);\n}\n\nconst tracerProvider = new NodeTracerProvider({\n\tresource,\n\tsampler: sentryClient ? new SentrySampler(sentryClient) : undefined,\n\tspanProcessors,\n});\n\ntracerProvider.register({\n\tpropagator: new SentryPropagator(),\n\tcontextManager: new Sentry.SentryContextManager(),\n});\n\n// --- OpenTelemetry meter provider (→ Collector → Honeycomb metrics) ---\nif (collectorToken) {\n\tconst meterProvider = new MeterProvider({\n\t\tresource,\n\t\treaders: [\n\t\t\tnew PeriodicExportingMetricReader({\n\t\t\t\texporter: new OTLPMetricExporter({\n\t\t\t\t\turl: `${COLLECTOR_ENDPOINT}/metrics`,\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tAuthorization: `Bearer ${collectorToken}`,\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t\texportIntervalMillis: 10_000,\n\t\t\t}),\n\t\t],\n\t});\n\tmetrics.setGlobalMeterProvider(meterProvider);\n}\n\ntrace.setGlobalTracerProvider(tracerProvider);\n\n// Validate that Sentry + OpenTelemetry are wired correctly\nSentry.validateOpenTelemetrySetup();\n\n// --- Shared instances for the rest of the codebase ---\nexport const tracer = trace.getTracer(name);\nexport const meter = metrics.getMeter(name);\nexport { Sentry };\n\n/**\n * Bundled service identity — avoids passing name and version as\n * separate primitives throughout the codebase (Data Clumps smell).\n */\nexport interface ServiceInfo {\n\treadonly name: string;\n\treadonly version: string;\n}\n\nexport const serviceInfo: ServiceInfo = { name, version } as const;\n\n// Keep individual exports for backward compatibility\nexport { name as serviceName, version as serviceVersion };\n\n// --- User context for span attributes ---\nlet currentUserId: string | undefined;\n\nexport function setCurrentUserId(id: string): void {\n\tcurrentUserId = id;\n}\n\nexport function getCurrentUserId(): string | undefined {\n\treturn currentUserId;\n}\n","/**\n * Metric instruments for Honeycomb.\n *\n * These are created once from the shared meter provider and exported\n * for use throughout the codebase. All instruments are sent to Honeycomb\n * via the OTLP metrics exporter configured in telemetry.ts.\n */\n\nimport { meter } from \"./telemetry.js\";\n\n/** Total MCP tool invocations, grouped by tool name. */\nexport const toolInvocations = meter.createCounter(\"mcp.tool.invocations\", {\n\tdescription: \"Total MCP tool invocations\",\n});\n\n/** Total MCP tool errors, grouped by tool name and error type. */\nexport const toolErrors = meter.createCounter(\"mcp.tool.errors\", {\n\tdescription: \"Total MCP tool errors\",\n});\n\n/** MCP tool execution duration in milliseconds. */\nexport const toolDuration = meter.createHistogram(\"mcp.tool.duration_ms\", {\n\tdescription: \"MCP tool execution duration in milliseconds\",\n\tunit: \"ms\",\n});\n\n/** Total Hevy API calls, grouped by method, endpoint, and status code. */\nexport const apiCalls = meter.createCounter(\"hevy.api.calls\", {\n\tdescription: \"Total Hevy API calls\",\n});\n\n/** Hevy API response time in milliseconds. */\nexport const apiDuration = meter.createHistogram(\"hevy.api.duration_ms\", {\n\tdescription: \"Hevy API response time in milliseconds\",\n\tunit: \"ms\",\n});\n\n/** Total stdio JSON parse errors, grouped by failure location. */\nexport const stdioParseErrors = meter.createCounter(\"mcp.stdio.parse_errors\", {\n\tdescription: \"Total stdio JSON parse errors\",\n});\n\n/** Total server startup count, grouped by version. */\nexport const serverStartups = meter.createCounter(\"mcp.server.startups\", {\n\tdescription: \"Total server startup count\",\n});\n","/**\n * Centralized error handling utility for MCP tools\n */\n\nimport { SpanStatusCode } from \"@opentelemetry/api\";\nimport { isAxiosError } from \"axios\";\nimport { Sentry, tracer, getCurrentUserId } from \"./telemetry.js\";\nimport { toolInvocations, toolErrors, toolDuration } from \"./metrics.js\";\nimport type { McpToolResponse } from \"./response-formatter.js\";\n\n/**\n * Standard error response interface\n */\nexport interface ErrorResponse {\n\tmessage: string;\n\tcode?: string;\n\tdetails?: unknown;\n}\n\n/**\n * Specific error types for better categorization\n */\nexport enum ErrorType {\n\tAPI_ERROR = \"API_ERROR\",\n\tRATE_LIMIT = \"RATE_LIMIT\",\n\tVALIDATION_ERROR = \"VALIDATION_ERROR\",\n\tNOT_FOUND = \"NOT_FOUND\",\n\tNETWORK_ERROR = \"NETWORK_ERROR\",\n\tUNKNOWN_ERROR = \"UNKNOWN_ERROR\",\n}\n\ntype RetryAwareError = {\n\thevyRetryCount?: number;\n\thevyRetryExhausted?: boolean;\n};\n\nfunction normalizeHeaderValue(value: unknown): string | undefined {\n\tif (typeof value === \"string\") {\n\t\tconst trimmed = value.trim();\n\t\treturn trimmed.length > 0 ? trimmed : undefined;\n\t}\n\n\tif (typeof value === \"number\" && Number.isFinite(value)) {\n\t\treturn String(value);\n\t}\n\n\tif (Array.isArray(value) && value.length > 0) {\n\t\treturn normalizeHeaderValue(value[0]);\n\t}\n\n\treturn undefined;\n}\n\nfunction getHeaderValue(headers: unknown, key: string): string | undefined {\n\tif (!headers || typeof headers !== \"object\") {\n\t\treturn undefined;\n\t}\n\n\tif (\n\t\t\"get\" in headers &&\n\t\ttypeof (headers as { get?: unknown }).get === \"function\"\n\t) {\n\t\tconst value = (headers as { get: (headerName: string) => unknown }).get(\n\t\t\tkey,\n\t\t);\n\t\treturn normalizeHeaderValue(value);\n\t}\n\n\tconst headerRecord = headers as Record<string, unknown>;\n\treturn normalizeHeaderValue(\n\t\theaderRecord[key] ??\n\t\t\theaderRecord[key.toLowerCase()] ??\n\t\t\theaderRecord[key.toUpperCase()],\n\t);\n}\n\nfunction formatSecondsLabel(seconds: number): string {\n\tconst roundedSeconds = Math.max(0, Math.round(seconds));\n\tconst suffix = roundedSeconds === 1 ? \"\" : \"s\";\n\treturn `${roundedSeconds} second${suffix}`;\n}\n\nfunction getRateLimitMessage(error: unknown): string {\n\tif (!isAxiosError(error)) {\n\t\treturn \"Rate limited by Hevy. Please wait and retry.\";\n\t}\n\n\tconst retryAfterHeader = getHeaderValue(\n\t\terror.response?.headers,\n\t\t\"retry-after\",\n\t);\n\tif (!retryAfterHeader) {\n\t\treturn \"Rate limited by Hevy (HTTP 429). Please wait and retry your request.\";\n\t}\n\n\tconst seconds = Number(retryAfterHeader);\n\tif (Number.isFinite(seconds) && seconds >= 0) {\n\t\treturn `Rate limited by Hevy (HTTP 429). Please wait about ${formatSecondsLabel(seconds)} before retrying.`;\n\t}\n\n\tconst retryAtMillis = Date.parse(retryAfterHeader);\n\tif (!Number.isNaN(retryAtMillis)) {\n\t\tconst secondsUntilRetry = Math.ceil(\n\t\t\tMath.max(0, retryAtMillis - Date.now()) / 1000,\n\t\t);\n\t\treturn `Rate limited by Hevy (HTTP 429). Please wait about ${formatSecondsLabel(secondsUntilRetry)} before retrying.`;\n\t}\n\n\treturn \"Rate limited by Hevy (HTTP 429). Please wait and retry your request.\";\n}\n\nfunction isRetryExhaustedError(error: unknown): boolean {\n\treturn (\n\t\t!!error &&\n\t\ttypeof error === \"object\" &&\n\t\t(error as RetryAwareError).hevyRetryExhausted === true\n\t);\n}\n\nfunction getRetryExhaustedMessage(error: unknown): string {\n\tconst retryCount =\n\t\ttypeof error === \"object\" && error !== null\n\t\t\t? (error as RetryAwareError).hevyRetryCount\n\t\t\t: undefined;\n\tconst attemptCount =\n\t\ttypeof retryCount === \"number\" && Number.isFinite(retryCount)\n\t\t\t? retryCount + 1\n\t\t\t: undefined;\n\n\tif (attemptCount) {\n\t\treturn `Unable to complete the request after ${attemptCount} attempts to the Hevy API due to transient failures. Please try again shortly.`;\n\t}\n\n\treturn \"Unable to complete the request after multiple attempts to the Hevy API due to transient failures. Please try again shortly.\";\n}\n\nfunction getUserFacingMessage(error: unknown, defaultMessage: string): string {\n\tif (isRetryExhaustedError(error)) {\n\t\treturn getRetryExhaustedMessage(error);\n\t}\n\n\tif (isAxiosError(error) && error.response?.status === 429) {\n\t\treturn getRateLimitMessage(error);\n\t}\n\n\treturn defaultMessage;\n}\n\n/**\n * Enhanced error response with type categorization\n */\nexport interface EnhancedErrorResponse extends ErrorResponse {\n\ttype: ErrorType;\n}\n\n/**\n * Structured debug context that preserves original error details\n */\nexport interface ErrorDebugContext {\n\tsourceContext?: string;\n\toriginalErrorMessage: string;\n\terrorCode?: string;\n\terrorType: ErrorType;\n\taxios?: {\n\t\tstatus?: number;\n\t\tstatusText?: string;\n\t\tdata?: unknown;\n\t\tmethod?: string;\n\t\turl?: string;\n\t};\n}\n\n/**\n * Create a standardized error response for MCP tools\n *\n * @param error - The error object or message\n * @param context - Optional context information about where the error occurred\n * @returns A formatted MCP tool response with error information\n */\nexport function createErrorResponse(\n\terror: unknown,\n\tcontext?: string,\n): McpToolResponse {\n\tconst originalErrorMessage = extractErrorMessage(error);\n\tlet errorMessage = originalErrorMessage;\n\tconst axiosErrorContext = extractAxiosErrorContext(error);\n\tconst mappedHevyErrorMessage = mapHevyErrorMessageByStatus(\n\t\taxiosErrorContext?.status,\n\t);\n\n\tif (mappedHevyErrorMessage) {\n\t\terrorMessage = mappedHevyErrorMessage;\n\t}\n\n\t// Check for axios error with response data\n\tif (!mappedHevyErrorMessage && axiosErrorContext?.data) {\n\t\terrorMessage = stringifyErrorData(axiosErrorContext.data);\n\t}\n\n\terrorMessage = getUserFacingMessage(error, errorMessage);\n\n\t// Extract error code if available (for logging purposes)\n\tconst errorCode =\n\t\terror instanceof Error && \"code\" in error\n\t\t\t? (error as { code?: string }).code\n\t\t\t: undefined;\n\n\t// Determine error type based on error characteristics\n\tconst errorType = determineErrorType(error, errorMessage);\n\tconst errorContext: ErrorDebugContext = {\n\t\tsourceContext: context,\n\t\toriginalErrorMessage,\n\t\terrorCode,\n\t\terrorType,\n\t\taxios: axiosErrorContext ?? undefined,\n\t};\n\n\tconst contextPrefix = context ? `[${context}] ` : \"\";\n\tconst formattedMessage = `${contextPrefix}Error: ${errorMessage}`;\n\tconst errorCodeSuffix = errorCode ? `, Code: ${errorCode}` : \"\";\n\n\t// Log the error for server-side debugging with type information\n\tconsole.error(\n\t\t`${formattedMessage} (Type: ${errorType}${errorCodeSuffix})`,\n\t\terror,\n\t);\n\n\treturn {\n\t\tcontent: [\n\t\t\t{\n\t\t\t\ttype: \"text\" as const,\n\t\t\t\ttext: formattedMessage,\n\t\t\t},\n\t\t],\n\t\tisError: true,\n\t\terrorContext,\n\t};\n}\n\nfunction extractErrorMessage(error: unknown): string {\n\tif (error instanceof Error) {\n\t\treturn error.message;\n\t}\n\n\tif (typeof error === \"string\") {\n\t\treturn error;\n\t}\n\n\tif (\n\t\terror &&\n\t\ttypeof error === \"object\" &&\n\t\t\"message\" in error &&\n\t\ttypeof error.message === \"string\"\n\t) {\n\t\treturn error.message;\n\t}\n\n\tif (error && typeof error === \"object\") {\n\t\ttry {\n\t\t\treturn JSON.stringify(error);\n\t\t} catch (_e) {\n\t\t\treturn \"Unknown error object\";\n\t\t}\n\t}\n\n\treturn String(error);\n}\n\nfunction extractAxiosErrorContext(\n\terror: unknown,\n): ErrorDebugContext[\"axios\"] | null {\n\tif (!isAxiosError(error)) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\tstatus: error.response?.status,\n\t\tstatusText: error.response?.statusText,\n\t\tdata: error.response?.data,\n\t\tmethod: error.config?.method,\n\t\turl: error.config?.url,\n\t};\n}\n\nfunction mapHevyErrorMessageByStatus(status?: number): string | null {\n\tif (status === 401 || status === 403) {\n\t\treturn \"The Hevy API key is invalid or has expired. Check HEVY_API_KEY.\";\n\t}\n\n\tif (status === 404) {\n\t\treturn \"The requested resource was not found in Hevy.\";\n\t}\n\n\tif (status === 409) {\n\t\treturn \"A conflict occurred (e.g., a body measurement already exists for this date). Use the update tool instead.\";\n\t}\n\n\tif (status === 422) {\n\t\treturn \"The request failed Hevy validation. Check the field values and try again.\";\n\t}\n\n\tif (status === 429) {\n\t\treturn \"Rate limited by Hevy. Please wait and retry.\";\n\t}\n\n\tif (status && status >= 500 && status <= 599) {\n\t\treturn \"Hevy API experienced an error. Please retry later.\";\n\t}\n\n\treturn null;\n}\n\nfunction stringifyErrorData(data: unknown): string {\n\tif (typeof data === \"string\") {\n\t\treturn data;\n\t}\n\n\tif (data && typeof data === \"object\") {\n\t\ttry {\n\t\t\treturn JSON.stringify(data);\n\t\t} catch (_e) {\n\t\t\treturn \"Unable to serialize error response data\";\n\t\t}\n\t}\n\n\treturn String(data);\n}\n\n/**\n * Determine the type of error based on error characteristics\n */\nfunction determineErrorType(error: unknown, message: string): ErrorType {\n\tif (isRetryExhaustedError(error)) {\n\t\treturn ErrorType.NETWORK_ERROR;\n\t}\n\n\tif (isAxiosError(error) && error.response?.status === 429) {\n\t\treturn ErrorType.RATE_LIMIT;\n\t}\n\n\tconst messageLower = message.toLowerCase();\n\tconst nameLower = error instanceof Error ? error.name.toLowerCase() : \"\";\n\n\tif (\n\t\tnameLower.includes(\"network\") ||\n\t\tmessageLower.includes(\"network\") ||\n\t\tnameLower.includes(\"fetch\") ||\n\t\tmessageLower.includes(\"fetch\") ||\n\t\tnameLower.includes(\"timeout\") ||\n\t\tmessageLower.includes(\"timeout\")\n\t) {\n\t\treturn ErrorType.NETWORK_ERROR;\n\t}\n\n\tif (\n\t\tnameLower.includes(\"validation\") ||\n\t\tmessageLower.includes(\"validation\") ||\n\t\tmessageLower.includes(\"invalid\") ||\n\t\tmessageLower.includes(\"required\")\n\t) {\n\t\treturn ErrorType.VALIDATION_ERROR;\n\t}\n\n\tif (\n\t\tmessageLower.includes(\"not found\") ||\n\t\tmessageLower.includes(\"404\") ||\n\t\tmessageLower.includes(\"does not exist\")\n\t) {\n\t\treturn ErrorType.NOT_FOUND;\n\t}\n\n\tif (\n\t\tnameLower.includes(\"api\") ||\n\t\tmessageLower.includes(\"api\") ||\n\t\tmessageLower.includes(\"server error\") ||\n\t\tmessageLower.includes(\"500\")\n\t) {\n\t\treturn ErrorType.API_ERROR;\n\t}\n\n\treturn ErrorType.UNKNOWN_ERROR;\n}\n\n/**\n * Wrap an async function with standardized error handling\n *\n * This function preserves the parameter types of the wrapped function while\n * providing error handling. The returned function accepts Record<string, unknown>\n * (as required by MCP SDK) but internally casts to the original parameter type.\n *\n * @param fn - The async function to wrap\n * @param context - Context information for error messages\n * @returns A function that catches errors and returns standardized error responses\n */\nexport function withErrorHandling<TParams extends Record<string, unknown>>(\n\tfn: (args: TParams) => Promise<McpToolResponse>,\n\tcontext: string,\n): (args: Record<string, unknown>) => Promise<McpToolResponse> {\n\treturn async (args: Record<string, unknown>) => {\n\t\tconst argumentKeyCount = Object.keys(args).length;\n\t\tconst startTime = Date.now();\n\n\t\ttoolInvocations.add(1, { tool_name: context });\n\n\t\treturn tracer.startActiveSpan(\n\t\t\t`mcp.tool.${context}`,\n\t\t\t{\n\t\t\t\tattributes: {\n\t\t\t\t\t\"mcp.tool.name\": context,\n\t\t\t\t\t\"mcp.tool.args.key_count\": argumentKeyCount,\n\t\t\t\t\t...(getCurrentUserId() ? { \"user.id\": getCurrentUserId() } : {}),\n\t\t\t\t},\n\t\t\t},\n\t\t\tasync (span) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await fn(args as TParams);\n\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\t\t\t\tspan.setAttribute(\n\t\t\t\t\t\t\"mcp.tool.result.is_error\",\n\t\t\t\t\t\tBoolean(result.isError),\n\t\t\t\t\t);\n\t\t\t\t\treturn result;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\t\t\tspan.recordException(error as Error);\n\n\t\t\t\t\tconst errorType = determineErrorType(\n\t\t\t\t\t\terror,\n\t\t\t\t\t\terror instanceof Error ? error.message : String(error),\n\t\t\t\t\t);\n\n\t\t\t\t\tspan.setAttribute(\"error.type\", errorType);\n\t\t\t\t\ttoolErrors.add(1, {\n\t\t\t\t\t\ttool_name: context,\n\t\t\t\t\t\terror_type: errorType,\n\t\t\t\t\t});\n\n\t\t\t\t\tSentry.withScope((scope) => {\n\t\t\t\t\t\tscope.setTag(\"mcp.tool.context\", context);\n\t\t\t\t\t\tscope.setContext(\"mcpTool\", {\n\t\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t\targumentKeyCount,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tSentry.captureException(error);\n\t\t\t\t\t});\n\n\t\t\t\t\treturn createErrorResponse(error, context);\n\t\t\t\t} finally {\n\t\t\t\t\ttoolDuration.record(Date.now() - startTime, {\n\t\t\t\t\t\ttool_name: context,\n\t\t\t\t\t});\n\t\t\t\t\tspan.end();\n\t\t\t\t}\n\t\t\t},\n\t\t);\n\t};\n}\n","import type {\n\tBodyMeasurement,\n\tExerciseHistoryEntry,\n\tExerciseTemplate,\n\tRoutine,\n\tRoutineFolder,\n\tWorkout,\n} from \"../generated/client/types/index.js\";\n\n/**\n * Formatted workout set interface\n */\nexport interface FormattedWorkoutSet {\n\tindex: number | undefined;\n\ttype: string | undefined;\n\tweight: number | undefined | null;\n\treps: number | undefined | null;\n\tdistance: number | undefined | null;\n\tduration: number | undefined | null;\n\trpe: number | undefined | null;\n\tcustomMetric: number | undefined | null;\n}\n\n/**\n * Formatted workout exercise interface\n */\nexport interface FormattedWorkoutExercise {\n\tindex: number | undefined;\n\tname: string | undefined;\n\texerciseTemplateId: string | undefined;\n\tnotes: string | undefined | null;\n\tsupersetsId: number | undefined | null;\n\tsets: FormattedWorkoutSet[] | undefined;\n}\n\n/**\n * Formatted workout interface\n */\nexport interface FormattedWorkout {\n\tid: string | undefined;\n\ttitle: string | undefined;\n\tdescription: string | undefined | null;\n\tstartTime: string | number | undefined;\n\tendTime: string | number | undefined;\n\tcreatedAt: string | undefined;\n\tupdatedAt: string | undefined;\n\tduration: string;\n\texercises: FormattedWorkoutExercise[] | undefined;\n}\n\n/**\n * Formatted routine set interface\n */\nexport interface FormattedRoutineSet {\n\tindex: number | undefined;\n\ttype: string | undefined;\n\tweight: number | undefined | null;\n\treps: number | undefined | null;\n\tdistance: number | undefined | null;\n\tduration: number | undefined | null;\n\tcustomMetric: number | undefined | null;\n\trepRange?: { start?: number | null; end?: number | null } | undefined | null;\n\trpe?: number | undefined | null;\n}\n\n/**\n * Formatted routine exercise interface\n */\nexport interface FormattedRoutineExercise {\n\tname: string | undefined;\n\tindex: number | undefined;\n\texerciseTemplateId: string | undefined;\n\tnotes: string | undefined | null;\n\tsupersetId: number | undefined | null;\n\trestSeconds: string | undefined;\n\tsets: FormattedRoutineSet[] | undefined;\n}\n\n/**\n * Formatted routine interface\n */\nexport interface FormattedRoutine {\n\tid: string | undefined;\n\ttitle: string | undefined;\n\tfolderId: number | undefined | null;\n\tcreatedAt: string | undefined;\n\tupdatedAt: string | undefined;\n\texercises: FormattedRoutineExercise[] | undefined;\n}\n\n/**\n * Formatted routine folder interface\n */\nexport interface FormattedRoutineFolder {\n\tid: number | undefined;\n\ttitle: string | undefined;\n\tcreatedAt: string | undefined;\n\tupdatedAt: string | undefined;\n}\n\n/**\n * Formatted exercise template interface\n */\nexport interface FormattedExerciseTemplate {\n\tid: string | undefined;\n\ttitle: string | undefined;\n\ttype: string | undefined;\n\tprimaryMuscleGroup: string | undefined;\n\tsecondaryMuscleGroups: string[] | undefined;\n\tisCustom: boolean | undefined;\n}\n\nexport interface FormattedExerciseHistoryEntry {\n\tworkoutId: string | undefined;\n\tworkoutTitle: string | undefined;\n\tworkoutStartTime: string | undefined;\n\tworkoutEndTime: string | undefined;\n\texerciseTemplateId: string | undefined;\n\tweight: number | undefined | null;\n\treps: number | undefined | null;\n\tdistance: number | undefined | null;\n\tduration: number | undefined | null;\n\trpe: number | undefined | null;\n\tcustomMetric: number | undefined | null;\n\tsetType: string | undefined;\n}\n\ntype ExerciseWithSupersetVariants = {\n\tsupersets_id?: number | null;\n\tsuperset_id?: number | null;\n};\n\nfunction getSupersetId(exercise: ExerciseWithSupersetVariants): number | null {\n\tif (exercise.superset_id !== undefined) {\n\t\treturn exercise.superset_id;\n\t}\n\n\tif (exercise.supersets_id !== undefined) {\n\t\treturn exercise.supersets_id;\n\t}\n\n\treturn null;\n}\n\n/**\n * Format a workout object for consistent presentation\n *\n * @param workout - The workout object from the API\n * @returns A formatted workout object with standardized properties\n */\nexport function formatWorkout(workout: Workout): FormattedWorkout {\n\treturn {\n\t\tid: workout.id,\n\t\ttitle: workout.title,\n\t\tdescription: workout.description,\n\t\tstartTime: workout.start_time,\n\t\tendTime: workout.end_time,\n\t\tcreatedAt: workout.created_at,\n\t\tupdatedAt: workout.updated_at,\n\t\tduration: calculateDuration(workout.start_time, workout.end_time),\n\t\texercises: workout.exercises?.map((exercise) => {\n\t\t\treturn {\n\t\t\t\tindex: exercise.index,\n\t\t\t\tname: exercise.title,\n\t\t\t\texerciseTemplateId: exercise.exercise_template_id,\n\t\t\t\tnotes: exercise.notes,\n\t\t\t\tsupersetsId: getSupersetId(exercise),\n\t\t\t\tsets: exercise.sets?.map((set) => ({\n\t\t\t\t\tindex: set.index,\n\t\t\t\t\ttype: set.type,\n\t\t\t\t\tweight: set.weight_kg,\n\t\t\t\t\treps: set.reps,\n\t\t\t\t\tdistance: set.distance_meters,\n\t\t\t\t\tduration: set.duration_seconds,\n\t\t\t\t\trpe: set.rpe,\n\t\t\t\t\tcustomMetric: set.custom_metric,\n\t\t\t\t})),\n\t\t\t};\n\t\t}),\n\t};\n}\n\n/**\n * Format a routine object for consistent presentation\n *\n * @param routine - The routine object from the API\n * @returns A formatted routine object with standardized properties\n */\nexport function formatRoutine(routine: Routine): FormattedRoutine {\n\treturn {\n\t\tid: routine.id,\n\t\ttitle: routine.title,\n\t\tfolderId: routine.folder_id,\n\t\tcreatedAt: routine.created_at,\n\t\tupdatedAt: routine.updated_at,\n\t\texercises: routine.exercises?.map((exercise) => {\n\t\t\treturn {\n\t\t\t\tname: exercise.title,\n\t\t\t\tindex: exercise.index,\n\t\t\t\texerciseTemplateId: exercise.exercise_template_id,\n\t\t\t\tnotes: exercise.notes,\n\t\t\t\tsupersetId: getSupersetId(exercise),\n\t\t\t\trestSeconds: exercise.rest_seconds,\n\t\t\t\tsets: exercise.sets?.map((set) => ({\n\t\t\t\t\tindex: set.index,\n\t\t\t\t\ttype: set.type,\n\t\t\t\t\tweight: set.weight_kg,\n\t\t\t\t\treps: set.reps,\n\t\t\t\t\t...(set.rep_range !== undefined && { repRange: set.rep_range }),\n\t\t\t\t\tdistance: set.distance_meters,\n\t\t\t\t\tduration: set.duration_seconds,\n\t\t\t\t\t...(set.rpe !== undefined && { rpe: set.rpe }),\n\t\t\t\t\tcustomMetric: set.custom_metric,\n\t\t\t\t})),\n\t\t\t};\n\t\t}),\n\t};\n}\n\n/**\n * Format a routine folder object for consistent presentation\n *\n * @param folder - The routine folder object from the API\n * @returns A formatted routine folder object with standardized properties\n */\nexport function formatRoutineFolder(\n\tfolder: RoutineFolder,\n): FormattedRoutineFolder {\n\treturn {\n\t\tid: folder.id,\n\t\ttitle: folder.title,\n\t\tcreatedAt: folder.created_at,\n\t\tupdatedAt: folder.updated_at,\n\t};\n}\n\n/**\n * Calculate duration between two ISO timestamp strings\n *\n * @param startTime - The start time as ISO string or timestamp\n * @param endTime - The end time as ISO string or timestamp\n * @returns A formatted duration string (e.g. \"1h 30m 45s\") or \"Unknown duration\" if inputs are invalid\n */\nexport function calculateDuration(\n\tstartTime: string | number | null | undefined,\n\tendTime: string | number | null | undefined,\n): string {\n\tif (!startTime || !endTime) return \"Unknown duration\";\n\n\ttry {\n\t\tconst start = new Date(startTime);\n\t\tconst end = new Date(endTime);\n\n\t\t// Validate dates\n\t\tif (Number.isNaN(start.getTime()) || Number.isNaN(end.getTime())) {\n\t\t\treturn \"Unknown duration\";\n\t\t}\n\n\t\tconst durationMs = end.getTime() - start.getTime();\n\n\t\t// Handle negative durations\n\t\tif (durationMs < 0) {\n\t\t\treturn \"Invalid duration (end time before start time)\";\n\t\t}\n\n\t\tconst hours = Math.floor(durationMs / (1000 * 60 * 60));\n\t\tconst minutes = Math.floor((durationMs % (1000 * 60 * 60)) / (1000 * 60));\n\t\tconst seconds = Math.floor((durationMs % (1000 * 60)) / 1000);\n\n\t\treturn `${hours}h ${minutes}m ${seconds}s`;\n\t} catch (error) {\n\t\tconsole.error(\"Error calculating duration:\", error);\n\t\treturn \"Unknown duration\";\n\t}\n}\n\n/**\n * Format an exercise template object for consistent presentation\n *\n * @param template - The exercise template object from the API\n * @returns A formatted exercise template object with standardized properties\n */\nexport function formatExerciseTemplate(\n\ttemplate: ExerciseTemplate,\n): FormattedExerciseTemplate {\n\treturn {\n\t\tid: template.id,\n\t\ttitle: template.title,\n\t\ttype: template.type,\n\t\tprimaryMuscleGroup: template.primary_muscle_group,\n\t\tsecondaryMuscleGroups: template.secondary_muscle_groups,\n\t\tisCustom: template.is_custom,\n\t};\n}\n\nexport function formatExerciseHistoryEntry(\n\tentry: ExerciseHistoryEntry,\n): FormattedExerciseHistoryEntry {\n\treturn {\n\t\tworkoutId: entry.workout_id,\n\t\tworkoutTitle: entry.workout_title,\n\t\tworkoutStartTime: entry.workout_start_time,\n\t\tworkoutEndTime: entry.workout_end_time,\n\t\texerciseTemplateId: entry.exercise_template_id,\n\t\tweight: entry.weight_kg,\n\t\treps: entry.reps,\n\t\tdistance: entry.distance_meters,\n\t\tduration: entry.duration_seconds,\n\t\trpe: entry.rpe,\n\t\tcustomMetric: entry.custom_metric,\n\t\tsetType: entry.set_type,\n\t};\n}\n\nexport interface FormattedBodyMeasurement {\n\tdate: string;\n\tweightKg: number | null;\n\tleanMassKg: number | null;\n\tfatPercent: number | null;\n\tneckCm: number | null;\n\tshoulderCm: number | null;\n\tchestCm: number | null;\n\tleftBicepCm: number | null;\n\trightBicepCm: number | null;\n\tleftForearmCm: number | null;\n\trightForearmCm: number | null;\n\tabdomen: number | null;\n\twaist: number | null;\n\thips: number | null;\n\tleftThigh: number | null;\n\trightThigh: number | null;\n\tleftCalf: number | null;\n\trightCalf: number | null;\n}\n\nexport function formatBodyMeasurement(\n\tmeasurement: BodyMeasurement,\n): FormattedBodyMeasurement {\n\treturn {\n\t\tdate: measurement.date,\n\t\tweightKg: measurement.weight_kg ?? null,\n\t\tleanMassKg: measurement.lean_mass_kg ?? null,\n\t\tfatPercent: measurement.fat_percent ?? null,\n\t\tneckCm: measurement.neck_cm ?? null,\n\t\tshoulderCm: measurement.shoulder_cm ?? null,\n\t\tchestCm: measurement.chest_cm ?? null,\n\t\tleftBicepCm: measurement.left_bicep_cm ?? null,\n\t\trightBicepCm: measurement.right_bicep_cm ?? null,\n\t\tleftForearmCm: measurement.left_forearm_cm ?? null,\n\t\trightForearmCm: measurement.right_forearm_cm ?? null,\n\t\tabdomen: measurement.abdomen ?? null,\n\t\twaist: measurement.waist ?? null,\n\t\thips: measurement.hips ?? null,\n\t\tleftThigh: measurement.left_thigh ?? null,\n\t\trightThigh: measurement.right_thigh ?? null,\n\t\tleftCalf: measurement.left_calf ?? null,\n\t\trightCalf: measurement.right_calf ?? null,\n\t};\n}\n","import type {\n\tCallToolResult,\n\tTextContent,\n} from \"@modelcontextprotocol/sdk/types.js\";\n\n/**\n * MCP tool response type aligned with MCP SDK CallToolResult while keeping\n * content narrowed to text blocks for this server.\n */\nexport type McpToolResponse = Omit<CallToolResult, \"content\"> & {\n\tcontent: TextContent[];\n};\n\n/**\n * Format options for JSON responses\n */\nexport interface JsonFormatOptions {\n\t/** Whether to pretty-print the JSON with indentation */\n\tpretty?: boolean;\n\t/** Indentation spaces for pretty-printing (default: 2) */\n\tindent?: number;\n}\n\n/**\n * Create a standardized success response with JSON data\n *\n * @param data - The data to include in the response\n * @param options - Formatting options\n * @returns A formatted MCP tool response with the data as JSON\n */\nexport function createJsonResponse(\n\tdata: unknown,\n\toptions: JsonFormatOptions = { pretty: true, indent: 2 },\n): McpToolResponse {\n\tconst jsonString =\n\t\t(options.pretty\n\t\t\t? JSON.stringify(data, null, options.indent)\n\t\t\t: JSON.stringify(data)) ?? \"null\";\n\n\treturn {\n\t\tcontent: [\n\t\t\t{\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: jsonString,\n\t\t\t},\n\t\t],\n\t};\n}\n\n/**\n * Create a standardized success response with text data\n *\n * @param message - The text message to include in the response\n * @returns A formatted MCP tool response with the text message\n */\nexport function createTextResponse(message: string): McpToolResponse {\n\treturn {\n\t\tcontent: [\n\t\t\t{\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: message,\n\t\t\t},\n\t\t],\n\t};\n}\n\n/**\n * Create a standardized success response for empty or null results\n *\n * @param message - Optional message to include (default: \"No data found\")\n * @returns A formatted MCP tool response for empty results\n */\nexport function createEmptyResponse(\n\tmessage = \"No data found\",\n): McpToolResponse {\n\treturn createTextResponse(message);\n}\n","/**\n * Shared MCP tool annotation factories.\n *\n * All hevy-mcp tools talk to the Hevy API, a closed, fully specified domain\n * limited to the authenticated user's own data, so openWorldHint is false\n * across the board.\n */\n\nimport type { ToolAnnotations } from \"@modelcontextprotocol/sdk/types.js\";\n\n/** Read-only tools (get-*, search-*): no side effects. */\nexport function readOnlyAnnotations(title: string): ToolAnnotations {\n\treturn { title, readOnlyHint: true, openWorldHint: false };\n}\n\n/** Create tools (create-*): additive writes, repeating creates duplicates. */\nexport function createAnnotations(title: string): ToolAnnotations {\n\treturn {\n\t\ttitle,\n\t\treadOnlyHint: false,\n\t\tdestructiveHint: false,\n\t\tidempotentHint: false,\n\t\topenWorldHint: false,\n\t};\n}\n\n/**\n * Update tools (update-*): PUT-style overwrites that replace prior data,\n * hence destructive; repeating the same call yields the same state.\n */\nexport function updateAnnotations(title: string): ToolAnnotations {\n\treturn {\n\t\ttitle,\n\t\treadOnlyHint: false,\n\t\tdestructiveHint: true,\n\t\tidempotentHint: true,\n\t\topenWorldHint: false,\n\t};\n}\n\n/** Delete tools (delete-*): destructive and idempotent. */\nexport function destructiveAnnotations(title: string): ToolAnnotations {\n\treturn {\n\t\ttitle,\n\t\treadOnlyHint: false,\n\t\tdestructiveHint: true,\n\t\tidempotentHint: true,\n\t\topenWorldHint: false,\n\t};\n}\n","/**\n * Type-safe utilities for MCP tool handlers\n */\n\nimport { z } from \"zod\";\nimport type { McpToolResponse } from \"./response-formatter.js\";\n\nexport const HEVY_CLIENT_NOT_INITIALIZED_ERROR =\n\t\"API client not initialized. Please provide HEVY_API_KEY.\";\n\n/**\n * Assert that the Hevy API client is initialized before running a tool.\n */\nexport function requireClient<TClient>(client: TClient | null): TClient {\n\tif (!client) {\n\t\tthrow new Error(HEVY_CLIENT_NOT_INITIALIZED_ERROR);\n\t}\n\n\treturn client;\n}\n\n/**\n * Infer TypeScript types from Zod schema objects\n *\n * @example\n * ```typescript\n * const schema = {\n * page: z.number(),\n * pageSize: z.number(),\n * } as const;\n *\n * type Params = InferToolParams<typeof schema>; // { page: number; pageSize: number }\n * ```\n */\nexport type InferToolParams<T extends Record<string, z.ZodTypeAny>> = z.infer<\n\tz.ZodObject<T>\n>;\n\n/**\n * Create a type-safe tool handler that validates and narrows args to inferred types\n *\n * This function wraps a handler with automatic Zod validation, ensuring runtime\n * type safety while maintaining compile-time type inference.\n *\n * @param schema - Zod schema object (e.g., { page: z.number(), ... })\n * @param handler - Handler function that receives validated, typed parameters\n * @returns A handler function that accepts Record<string, unknown> and validates it\n *\n * @example\n * ```typescript\n * const schema = {\n * page: z.coerce.number().int().gte(1).default(1),\n * pageSize: z.coerce.number().int().gte(1).lte(10).default(5),\n * } as const;\n *\n * const handler = createTypedToolHandler(schema, async (args) => {\n * // args is fully typed as { page: number; pageSize: number }\n * const { page, pageSize } = args;\n * // ...\n * });\n * ```\n */\nexport function createTypedToolHandler<T extends Record<string, z.ZodTypeAny>>(\n\tschema: T,\n\thandler: (args: InferToolParams<T>) => Promise<McpToolResponse>,\n): (args: Record<string, unknown>) => Promise<McpToolResponse> {\n\tconst zodSchema = z.object(schema);\n\treturn async (args: Record<string, unknown>) => {\n\t\tconst validated = zodSchema.parse(args);\n\t\treturn handler(validated);\n\t};\n}\n","import { z } from \"zod\";\n\nfunction coerceNullishNumberInput(value: unknown): unknown {\n\tif (value === null || value === undefined) {\n\t\treturn value;\n\t}\n\n\tif (typeof value !== \"string\") {\n\t\treturn value;\n\t}\n\n\tconst trimmed = value.trim();\n\tif (trimmed === \"\") {\n\t\treturn undefined;\n\t}\n\n\tconst lowered = trimmed.toLowerCase();\n\tif (lowered === \"null\") {\n\t\treturn null;\n\t}\n\tif (lowered === \"undefined\") {\n\t\treturn undefined;\n\t}\n\n\tconst asNumber = Number(trimmed);\n\tif (Number.isNaN(asNumber)) {\n\t\treturn value;\n\t}\n\n\treturn asNumber;\n}\n\nexport const zNullableInt = z.preprocess(\n\tcoerceNullishNumberInput,\n\tz.number().int().nullable().optional(),\n);\n\nexport const zNullableNumber = z.preprocess(\n\t(value) => (value === \"\" ? undefined : value),\n\tz.coerce.number().nullable().optional(),\n);\n\nexport const zOptionalRepRange = z.preprocess(\n\t(value) => (value === null ? undefined : value),\n\tz\n\t\t.object({\n\t\t\tstart: zNullableInt,\n\t\t\tend: zNullableInt,\n\t\t})\n\t\t.optional(),\n);\n\nconst setTypeValues = [\"warmup\", \"normal\", \"failure\", \"dropset\"] as const;\nexport const setTypeEnum = z.enum(setTypeValues).default(\"normal\");\n\nconst muscleGroupValues = [\n\t\"abdominals\",\n\t\"shoulders\",\n\t\"biceps\",\n\t\"triceps\",\n\t\"forearms\",\n\t\"quadriceps\",\n\t\"hamstrings\",\n\t\"calves\",\n\t\"glutes\",\n\t\"abductors\",\n\t\"adductors\",\n\t\"lats\",\n\t\"upper_back\",\n\t\"traps\",\n\t\"lower_back\",\n\t\"chest\",\n\t\"cardio\",\n\t\"neck\",\n\t\"full_body\",\n\t\"other\",\n] as const;\nexport const muscleGroupEnum = z.enum(muscleGroupValues);\n\nconst exerciseTypeValues = [\n\t\"weight_reps\",\n\t\"reps_only\",\n\t\"bodyweight_reps\",\n\t\"bodyweight_assisted_reps\",\n\t\"duration\",\n\t\"weight_duration\",\n\t\"distance_duration\",\n\t\"short_distance_weight\",\n] as const;\nexport const exerciseTypeEnum = z.enum(exerciseTypeValues);\n\nconst equipmentCategoryValues = [\n\t\"none\",\n\t\"barbell\",\n\t\"dumbbell\",\n\t\"kettlebell\",\n\t\"machine\",\n\t\"plate\",\n\t\"resistance_band\",\n\t\"suspension\",\n\t\"other\",\n] as const;\nexport const equipmentCategoryEnum = z.enum(equipmentCategoryValues);\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type {\n\tBodyMeasurement,\n\tGetV1BodyMeasurements200,\n\tGetV1BodyMeasurementsDate200,\n} from \"../generated/client/types/index.js\";\nimport { withErrorHandling } from \"../utils/error-handler.js\";\nimport { formatBodyMeasurement } from \"../utils/formatters.js\";\nimport {\n\tcreateEmptyResponse,\n\tcreateJsonResponse,\n\tcreateTextResponse,\n} from \"../utils/response-formatter.js\";\nimport {\n\tcreateAnnotations,\n\treadOnlyAnnotations,\n\tupdateAnnotations,\n} from \"../utils/tool-annotations.js\";\nimport { requireClient, type InferToolParams } from \"../utils/tool-helpers.js\";\nimport { zNullableNumber } from \"../utils/schemas.js\";\n\ntype HevyClient = ReturnType<\n\ttypeof import(\"../utils/hevyClientKubb.js\").createClient\n>;\n\nconst bodyMeasurementFieldsSchema = {\n\tweightKg: zNullableNumber.describe(\"Body weight in kilograms\"),\n\tleanMassKg: zNullableNumber.describe(\"Lean body mass in kilograms\"),\n\tfatPercent: zNullableNumber.describe(\"Body fat percentage\"),\n\tneckCm: zNullableNumber.describe(\"Neck circumference in centimeters\"),\n\tshoulderCm: zNullableNumber.describe(\"Shoulder circumference in centimeters\"),\n\tchestCm: zNullableNumber.describe(\"Chest circumference in centimeters\"),\n\tleftBicepCm: zNullableNumber.describe(\n\t\t\"Left bicep circumference in centimeters\",\n\t),\n\trightBicepCm: zNullableNumber.describe(\n\t\t\"Right bicep circumference in centimeters\",\n\t),\n\tleftForearmCm: zNullableNumber.describe(\n\t\t\"Left forearm circumference in centimeters\",\n\t),\n\trightForearmCm: zNullableNumber.describe(\n\t\t\"Right forearm circumference in centimeters\",\n\t),\n\tabdomen: zNullableNumber.describe(\"Abdomen circumference in centimeters\"),\n\twaist: zNullableNumber.describe(\"Waist circumference in centimeters\"),\n\thips: zNullableNumber.describe(\"Hips circumference in centimeters\"),\n\tleftThigh: zNullableNumber.describe(\n\t\t\"Left thigh circumference in centimeters\",\n\t),\n\trightThigh: zNullableNumber.describe(\n\t\t\"Right thigh circumference in centimeters\",\n\t),\n\tleftCalf: zNullableNumber.describe(\"Left calf circumference in centimeters\"),\n\trightCalf: zNullableNumber.describe(\n\t\t\"Right calf circumference in centimeters\",\n\t),\n} as const;\n\nconst MEASUREMENT_FIELD_TO_API_KEY = {\n\tweightKg: \"weight_kg\",\n\tleanMassKg: \"lean_mass_kg\",\n\tfatPercent: \"fat_percent\",\n\tneckCm: \"neck_cm\",\n\tshoulderCm: \"shoulder_cm\",\n\tchestCm: \"chest_cm\",\n\tleftBicepCm: \"left_bicep_cm\",\n\trightBicepCm: \"right_bicep_cm\",\n\tleftForearmCm: \"left_forearm_cm\",\n\trightForearmCm: \"right_forearm_cm\",\n\tabdomen: \"abdomen\",\n\twaist: \"waist\",\n\thips: \"hips\",\n\tleftThigh: \"left_thigh\",\n\trightThigh: \"right_thigh\",\n\tleftCalf: \"left_calf\",\n\trightCalf: \"right_calf\",\n} as const satisfies Record<\n\tkeyof typeof bodyMeasurementFieldsSchema,\n\tkeyof Omit<BodyMeasurement, \"date\">\n>;\n\ntype MeasurementFieldArgs = Partial<\n\tRecord<keyof typeof MEASUREMENT_FIELD_TO_API_KEY, number | null>\n>;\n\n// The Hevy API rejects null for omitted fields, so only fields with actual\n// values are included in the payload (#341).\nfunction buildMeasurementPayload(\n\targs: MeasurementFieldArgs,\n): Omit<BodyMeasurement, \"date\"> {\n\tconst payload: Omit<BodyMeasurement, \"date\"> = {};\n\tfor (const [camelKey, apiKey] of Object.entries(\n\t\tMEASUREMENT_FIELD_TO_API_KEY,\n\t) as [keyof MeasurementFieldArgs, keyof Omit<BodyMeasurement, \"date\">][]) {\n\t\tconst value = args[camelKey];\n\t\tif (value != null) {\n\t\t\tpayload[apiKey] = value;\n\t\t}\n\t}\n\treturn payload;\n}\n\nexport function registerBodyMeasurementTools(\n\tserver: McpServer,\n\thevyClient: HevyClient | null,\n) {\n\t// Get body measurements (paginated list)\n\tconst getBodyMeasurementsSchema = {\n\t\tpage: z.coerce.number().int().gte(1).default(1),\n\t\tpageSize: z.coerce.number().int().gte(1).lte(10).default(10),\n\t} as const;\n\ttype GetBodyMeasurementsParams = InferToolParams<\n\t\ttypeof getBodyMeasurementsSchema\n\t>;\n\n\tserver.tool(\n\t\t\"get-body-measurements\",\n\t\t\"Get a paginated list of body measurements for the authenticated user. Returns measurements including weight, body fat, and various circumference measurements.\",\n\t\tgetBodyMeasurementsSchema,\n\t\treadOnlyAnnotations(\"Get Body Measurements\"),\n\t\twithErrorHandling(async (args: GetBodyMeasurementsParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { page, pageSize } = args;\n\t\t\tconst data: GetV1BodyMeasurements200 = await client.getBodyMeasurements({\n\t\t\t\tpage,\n\t\t\t\tpageSize,\n\t\t\t});\n\n\t\t\tconst measurements =\n\t\t\t\tdata?.body_measurements?.map((measurement: BodyMeasurement) =>\n\t\t\t\t\tformatBodyMeasurement(measurement),\n\t\t\t\t) || [];\n\n\t\t\tif (measurements.length === 0) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"No body measurements found for the specified parameters\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createJsonResponse(measurements);\n\t\t}, \"get-body-measurements\"),\n\t);\n\n\t// Get single body measurement by date\n\tconst getBodyMeasurementSchema = {\n\t\tdate: z\n\t\t\t.string()\n\t\t\t.regex(/^\\d{4}-\\d{2}-\\d{2}$/, \"Date must be in YYYY-MM-DD format\")\n\t\t\t.describe(\"The date of the body measurement (YYYY-MM-DD)\"),\n\t} as const;\n\ttype GetBodyMeasurementParams = InferToolParams<\n\t\ttypeof getBodyMeasurementSchema\n\t>;\n\n\tserver.tool(\n\t\t\"get-body-measurement\",\n\t\t\"Get a single body measurement by date. Returns all measurement fields for the specified date.\",\n\t\tgetBodyMeasurementSchema,\n\t\treadOnlyAnnotations(\"Get Body Measurement\"),\n\t\twithErrorHandling(async (args: GetBodyMeasurementParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { date } = args;\n\t\t\tconst data: GetV1BodyMeasurementsDate200 =\n\t\t\t\tawait client.getBodyMeasurement(date);\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t`No body measurement found for date ${date}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createJsonResponse(formatBodyMeasurement(data));\n\t\t}, \"get-body-measurement\"),\n\t);\n\n\t// Create body measurement\n\tconst createBodyMeasurementSchema = {\n\t\tdate: z\n\t\t\t.string()\n\t\t\t.regex(/^\\d{4}-\\d{2}-\\d{2}$/, \"Date must be in YYYY-MM-DD format\")\n\t\t\t.describe(\n\t\t\t\t\"The date of the body measurement (YYYY-MM-DD). Must be unique — returns 409 if an entry already exists for this date.\",\n\t\t\t),\n\t\t...bodyMeasurementFieldsSchema,\n\t} as const;\n\ttype CreateBodyMeasurementParams = InferToolParams<\n\t\ttypeof createBodyMeasurementSchema\n\t>;\n\n\tserver.tool(\n\t\t\"create-body-measurement\",\n\t\t\"Create a body measurement entry for a given date. All measurement fields are optional; null values are treated as omitted, since the Hevy API does not support clearing individual fields. Returns 409 if an entry already exists for that date — use update-body-measurement instead.\",\n\t\tcreateBodyMeasurementSchema,\n\t\tcreateAnnotations(\"Create Body Measurement\"),\n\t\twithErrorHandling(async (args: CreateBodyMeasurementParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { date, ...fields } = args;\n\t\t\tawait client.createBodyMeasurement({\n\t\t\t\tdate,\n\t\t\t\t...buildMeasurementPayload(fields),\n\t\t\t});\n\n\t\t\treturn createTextResponse(\n\t\t\t\t`Body measurement for ${date} created successfully.`,\n\t\t\t);\n\t\t}, \"create-body-measurement\"),\n\t);\n\n\t// Update body measurement\n\tconst updateBodyMeasurementSchema = {\n\t\tdate: z\n\t\t\t.string()\n\t\t\t.regex(/^\\d{4}-\\d{2}-\\d{2}$/, \"Date must be in YYYY-MM-DD format\")\n\t\t\t.describe(\n\t\t\t\t\"The date of the body measurement to update (YYYY-MM-DD). Must already exist — returns 404 otherwise.\",\n\t\t\t),\n\t\t...bodyMeasurementFieldsSchema,\n\t} as const;\n\ttype UpdateBodyMeasurementParams = InferToolParams<\n\t\ttypeof updateBodyMeasurementSchema\n\t>;\n\n\tserver.tool(\n\t\t\"update-body-measurement\",\n\t\t\"Update an existing body measurement entry for a given date. Only the fields you provide are sent and updated; null values are treated as omitted, since the Hevy API does not support clearing individual fields. Requires at least one measurement field. Returns 404 if no entry exists for the date.\",\n\t\tupdateBodyMeasurementSchema,\n\t\tupdateAnnotations(\"Update Body Measurement\"),\n\t\twithErrorHandling(async (args: UpdateBodyMeasurementParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { date, ...fields } = args;\n\t\t\tconst payload = buildMeasurementPayload(fields);\n\t\t\tif (Object.keys(payload).length === 0) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"No measurement fields provided. Include at least one numeric measurement field (e.g. weightKg) to update.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tawait client.updateBodyMeasurement(date, payload);\n\n\t\t\treturn createTextResponse(\n\t\t\t\t`Body measurement for ${date} updated successfully.`,\n\t\t\t);\n\t\t}, \"update-body-measurement\"),\n\t);\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n// Import types from generated client\nimport type {\n\tGetV1RoutineFolders200,\n\tGetV1RoutineFoldersFolderid200,\n\tPostV1RoutineFolders201,\n\tRoutineFolder,\n} from \"../generated/client/types/index.js\";\nimport { withErrorHandling } from \"../utils/error-handler.js\";\nimport { formatRoutineFolder } from \"../utils/formatters.js\";\nimport {\n\tcreateEmptyResponse,\n\tcreateJsonResponse,\n} from \"../utils/response-formatter.js\";\nimport {\n\tcreateAnnotations,\n\treadOnlyAnnotations,\n} from \"../utils/tool-annotations.js\";\nimport { requireClient, type InferToolParams } from \"../utils/tool-helpers.js\";\n\n// Type definitions for the folder operations\ntype HevyClient = ReturnType<\n\ttypeof import(\"../utils/hevyClientKubb.js\").createClient\n>;\n\n/**\n * Register all routine folder-related tools with the MCP server\n */\nexport function registerFolderTools(\n\tserver: McpServer,\n\thevyClient: HevyClient | null,\n) {\n\t// Get routine folders\n\tconst getRoutineFoldersSchema = {\n\t\tpage: z.coerce.number().int().gte(1).default(1),\n\t\tpageSize: z.coerce.number().int().gte(1).lte(10).default(5),\n\t} as const;\n\ttype GetRoutineFoldersParams = InferToolParams<\n\t\ttypeof getRoutineFoldersSchema\n\t>;\n\n\tserver.tool(\n\t\t\"get-routine-folders\",\n\t\t\"Get a paginated list of your routine folders, including both default and custom folders. Useful for organizing and browsing your workout routines.\",\n\t\tgetRoutineFoldersSchema,\n\t\treadOnlyAnnotations(\"Get Routine Folders\"),\n\t\twithErrorHandling(async (args: GetRoutineFoldersParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { page, pageSize } = args;\n\t\t\tconst data: GetV1RoutineFolders200 = await client.getRoutineFolders({\n\t\t\t\tpage,\n\t\t\t\tpageSize,\n\t\t\t});\n\n\t\t\t// Process routine folders to extract relevant information\n\t\t\tconst folders =\n\t\t\t\tdata?.routine_folders?.map((folder: RoutineFolder) =>\n\t\t\t\t\tformatRoutineFolder(folder),\n\t\t\t\t) || [];\n\n\t\t\tif (folders.length === 0) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"No routine folders found for the specified parameters\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createJsonResponse(folders);\n\t\t}, \"get-routine-folders\"),\n\t);\n\n\t// Get single routine folder by ID\n\tconst getRoutineFolderSchema = {\n\t\tfolderId: z.string().min(1),\n\t} as const;\n\ttype GetRoutineFolderParams = InferToolParams<typeof getRoutineFolderSchema>;\n\n\tserver.tool(\n\t\t\"get-routine-folder\",\n\t\t\"Get complete details of a specific routine folder by its ID, including name, creation date, and associated routines.\",\n\t\tgetRoutineFolderSchema,\n\t\treadOnlyAnnotations(\"Get Routine Folder\"),\n\t\twithErrorHandling(async (args: GetRoutineFolderParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { folderId } = args;\n\t\t\tconst data: GetV1RoutineFoldersFolderid200 =\n\t\t\t\tawait client.getRoutineFolder(folderId);\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t`Routine folder with ID ${folderId} not found`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst folder = formatRoutineFolder(data);\n\t\t\treturn createJsonResponse(folder);\n\t\t}, \"get-routine-folder\"),\n\t);\n\n\t// Create new routine folder\n\tconst createRoutineFolderSchema = {\n\t\tname: z.string().min(1),\n\t} as const;\n\ttype CreateRoutineFolderParams = InferToolParams<\n\t\ttypeof createRoutineFolderSchema\n\t>;\n\n\tserver.tool(\n\t\t\"create-routine-folder\",\n\t\t\"Create a new routine folder in your Hevy account. Requires a name for the folder. Returns the full folder details including the new folder ID.\",\n\t\tcreateRoutineFolderSchema,\n\t\tcreateAnnotations(\"Create Routine Folder\"),\n\t\twithErrorHandling(async (args: CreateRoutineFolderParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { name } = args;\n\t\t\tconst data: PostV1RoutineFolders201 = await client.createRoutineFolder({\n\t\t\t\troutine_folder: {\n\t\t\t\t\ttitle: name,\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"Failed to create routine folder: Server returned no data\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst folder = formatRoutineFolder(data);\n\t\t\treturn createJsonResponse(folder, {\n\t\t\t\tpretty: true,\n\t\t\t\tindent: 2,\n\t\t\t});\n\t\t}, \"create-routine-folder\"),\n\t);\n}\n","/**\n * Preprocessor to handle MCP clients that send JSON-stringified arrays\n * instead of native arrays for complex parameters.\n *\n * This is used with Zod's z.preprocess to handle cases where MCP clients\n * serialize complex nested structures as JSON strings.\n *\n * @param val - The value to potentially parse\n * @returns The parsed array if val is a valid JSON string, otherwise returns val unchanged\n */\nexport function parseJsonArray(val: unknown): unknown {\n\t// Handle case where MCP client sends JSON string instead of array\n\tif (typeof val === \"string\") {\n\t\ttry {\n\t\t\treturn JSON.parse(val);\n\t\t} catch {\n\t\t\t// Let Zod validation handle the error\n\t\t\treturn val;\n\t\t}\n\t}\n\treturn val;\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n// Import types from generated client\nimport type {\n\tGetV1Routines200,\n\tGetV1RoutinesRoutineid200,\n\tPostRoutinesRequestExercise,\n\tPostRoutinesRequestSet,\n\tPostRoutinesRequestSetTypeEnumKey,\n\tPostV1Routines201,\n\tPutRoutinesRequestExercise,\n\tPutRoutinesRequestSet,\n\tPutRoutinesRequestSetTypeEnumKey,\n\tPutV1RoutinesRoutineid200,\n\tRoutine,\n} from \"../generated/client/types/index.js\";\nimport { withErrorHandling } from \"../utils/error-handler.js\";\nimport { formatRoutine } from \"../utils/formatters.js\";\nimport { parseJsonArray } from \"../utils/json-parser.js\";\nimport {\n\tcreateEmptyResponse,\n\tcreateJsonResponse,\n} from \"../utils/response-formatter.js\";\nimport {\n\tcreateAnnotations,\n\treadOnlyAnnotations,\n\tupdateAnnotations,\n} from \"../utils/tool-annotations.js\";\nimport { requireClient, type InferToolParams } from \"../utils/tool-helpers.js\";\nimport {\n\tsetTypeEnum,\n\tzNullableInt,\n\tzOptionalRepRange,\n} from \"../utils/schemas.js\";\n\n// Type definitions for the routine operations\ntype HevyClient = ReturnType<\n\ttypeof import(\"../utils/hevyClientKubb.js\").createClient\n>;\n\nfunction buildRepRange(repRange?: {\n\tstart?: number | null;\n\tend?: number | null;\n}): { start?: number; end?: number } | null {\n\tif (!repRange) {\n\t\treturn null;\n\t}\n\n\tconst start = repRange.start ?? undefined;\n\tconst end = repRange.end ?? undefined;\n\tif (start === undefined && end === undefined) {\n\t\treturn null;\n\t}\n\n\treturn { start, end };\n}\n\n/**\n * Returns a fixed rep count when `repRange` is a fixed range (start and end are\n * both non-null and equal). Otherwise returns null.\n */\nfunction getFixedRepsFromRepRange(\n\trepRange:\n\t\t| {\n\t\t\t\tstart?: number | null;\n\t\t\t\tend?: number | null;\n\t\t }\n\t\t| null\n\t\t| undefined,\n): number | null {\n\tif (!repRange) {\n\t\treturn null;\n\t}\n\n\tconst start = repRange.start ?? null;\n\tconst end = repRange.end ?? null;\n\tif (start === null || end === null) {\n\t\treturn null;\n\t}\n\tif (start !== end) {\n\t\treturn null;\n\t}\n\n\treturn start;\n}\n\nconst repRangeDisplayWarningText =\n\t\"Note: Hevy's public API stores rep ranges (rep_range), but the Hevy apps may \" +\n\t\"not display them because they rely on an internal-only exercise field \" +\n\t\"(input_modifier). See https://github.com/chrisdoc/hevy-mcp/issues/261 for \" +\n\t\"details/workarounds.\";\n\n/**\n * Register all routine-related tools with the MCP server\n */\nexport function registerRoutineTools(\n\tserver: McpServer,\n\thevyClient: HevyClient | null,\n) {\n\t// Get routines\n\tconst getRoutinesSchema = {\n\t\tpage: z.coerce.number().int().gte(1).default(1),\n\t\tpageSize: z.coerce.number().int().gte(1).lte(10).default(5),\n\t} as const;\n\ttype GetRoutinesParams = InferToolParams<typeof getRoutinesSchema>;\n\n\tserver.tool(\n\t\t\"get-routines\",\n\t\t\"Get a paginated list of your workout routines, including custom and default routines. Useful for browsing or searching your available routines.\",\n\t\tgetRoutinesSchema,\n\t\treadOnlyAnnotations(\"Get Routines\"),\n\t\twithErrorHandling(async (args: GetRoutinesParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { page, pageSize } = args;\n\t\t\tconst data: GetV1Routines200 = await client.getRoutines({\n\t\t\t\tpage,\n\t\t\t\tpageSize,\n\t\t\t});\n\n\t\t\t// Process routines to extract relevant information\n\t\t\tconst routines =\n\t\t\t\tdata?.routines?.map((routine: Routine) => formatRoutine(routine)) || [];\n\n\t\t\tif (routines.length === 0) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"No routines found for the specified parameters\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createJsonResponse(routines);\n\t\t}, \"get-routines\"),\n\t);\n\n\t// Get single routine by ID (new, direct endpoint)\n\tconst getRoutineSchema = {\n\t\troutineId: z.string().min(1),\n\t} as const;\n\ttype GetRoutineParams = InferToolParams<typeof getRoutineSchema>;\n\n\tserver.tool(\n\t\t\"get-routine\",\n\t\t\"Get a routine by its ID using the direct endpoint. Returns all details for the specified routine.\",\n\t\tgetRoutineSchema,\n\t\treadOnlyAnnotations(\"Get Routine\"),\n\t\twithErrorHandling(async (args: GetRoutineParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { routineId } = args;\n\t\t\tconst data: GetV1RoutinesRoutineid200 = await client.getRoutineById(\n\t\t\t\tString(routineId),\n\t\t\t);\n\t\t\tif (!data || !data.routine) {\n\t\t\t\treturn createEmptyResponse(`Routine with ID ${routineId} not found`);\n\t\t\t}\n\t\t\tconst routine = formatRoutine(data.routine);\n\t\t\treturn createJsonResponse(routine);\n\t\t}, \"get-routine\"),\n\t);\n\n\t// Create new routine\n\tconst createRoutineSchema = {\n\t\ttitle: z.string().min(1),\n\t\tfolderId: z.coerce.number().nullable().optional(),\n\t\tnotes: z.string().optional(),\n\t\texercises: z.preprocess(\n\t\t\tparseJsonArray,\n\t\t\tz.array(\n\t\t\t\tz.object({\n\t\t\t\t\texerciseTemplateId: z.string().min(1),\n\t\t\t\t\tsupersetId: z.coerce.number().nullable().optional(),\n\t\t\t\t\trestSeconds: z.coerce.number().int().min(0).optional(),\n\t\t\t\t\tnotes: z.string().optional(),\n\t\t\t\t\tsets: z.array(\n\t\t\t\t\t\tz.object({\n\t\t\t\t\t\t\ttype: setTypeEnum,\n\t\t\t\t\t\t\tweight: z.coerce.number().optional(),\n\t\t\t\t\t\t\tweightKg: z.coerce.number().optional(),\n\t\t\t\t\t\t\treps: zNullableInt,\n\t\t\t\t\t\t\tdistance: z.coerce.number().int().optional(),\n\t\t\t\t\t\t\tdistanceMeters: z.coerce.number().int().optional(),\n\t\t\t\t\t\t\tduration: z.coerce.number().int().optional(),\n\t\t\t\t\t\t\tdurationSeconds: z.coerce.number().int().optional(),\n\t\t\t\t\t\t\tcustomMetric: z.coerce.number().optional(),\n\t\t\t\t\t\t\trepRange: zOptionalRepRange,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t),\n\t\t),\n\t} as const;\n\ttype CreateRoutineParams = InferToolParams<typeof createRoutineSchema>;\n\n\tserver.tool(\n\t\t\"create-routine\",\n\t\t\"Create a new workout routine in your Hevy account. Requires a title and at least one exercise with sets. Optionally assign to a folder. Returns the full routine details including the new routine ID.\",\n\t\tcreateRoutineSchema,\n\t\tcreateAnnotations(\"Create Routine\"),\n\t\twithErrorHandling(async (args: CreateRoutineParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { title, folderId, notes, exercises } = args;\n\t\t\tlet usesRepRanges = false;\n\t\t\tconst data: PostV1Routines201 = await client.createRoutine({\n\t\t\t\troutine: {\n\t\t\t\t\ttitle,\n\t\t\t\t\tfolder_id: folderId ?? null,\n\t\t\t\t\tnotes: notes ?? \"\",\n\t\t\t\t\texercises: exercises.map((exercise): PostRoutinesRequestExercise => {\n\t\t\t\t\t\tconst sets = exercise.sets.map((set): PostRoutinesRequestSet => {\n\t\t\t\t\t\t\tconst repRange = buildRepRange(set.repRange);\n\t\t\t\t\t\t\tconst fixedReps = getFixedRepsFromRepRange(repRange);\n\t\t\t\t\t\t\tconst reps = typeof set.reps === \"number\" ? set.reps : fixedReps;\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\ttype: set.type as PostRoutinesRequestSetTypeEnumKey,\n\t\t\t\t\t\t\t\tweight_kg: set.weight ?? set.weightKg ?? null,\n\t\t\t\t\t\t\t\treps: reps ?? null,\n\t\t\t\t\t\t\t\tdistance_meters: set.distance ?? set.distanceMeters ?? null,\n\t\t\t\t\t\t\t\tduration_seconds: set.duration ?? set.durationSeconds ?? null,\n\t\t\t\t\t\t\t\tcustom_metric: set.customMetric ?? null,\n\t\t\t\t\t\t\t\trep_range: repRange,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tsets.some(\n\t\t\t\t\t\t\t\t(set) =>\n\t\t\t\t\t\t\t\t\tset.rep_range != null &&\n\t\t\t\t\t\t\t\t\tgetFixedRepsFromRepRange(set.rep_range) === null,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tusesRepRanges = true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\texercise_template_id: exercise.exerciseTemplateId,\n\t\t\t\t\t\t\tsuperset_id: exercise.supersetId ?? null,\n\t\t\t\t\t\t\trest_seconds: exercise.restSeconds ?? null,\n\t\t\t\t\t\t\tnotes: exercise.notes ?? null,\n\t\t\t\t\t\t\tsets,\n\t\t\t\t\t\t};\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"Failed to create routine: Server returned no data\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst routine = formatRoutine(data);\n\t\t\tconst response = createJsonResponse(routine, {\n\t\t\t\tpretty: true,\n\t\t\t\tindent: 2,\n\t\t\t});\n\n\t\t\tif (usesRepRanges) {\n\t\t\t\tresponse.content.push({\n\t\t\t\t\ttype: \"text\",\n\t\t\t\t\ttext: repRangeDisplayWarningText,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn response;\n\t\t}, \"create-routine\"),\n\t);\n\n\t// Update existing routine\n\tconst updateRoutineSchema = {\n\t\troutineId: z.string().min(1),\n\t\ttitle: z.string().min(1),\n\t\tnotes: z.string().optional(),\n\t\texercises: z.preprocess(\n\t\t\tparseJsonArray,\n\t\t\tz.array(\n\t\t\t\tz.object({\n\t\t\t\t\texerciseTemplateId: z.string().min(1),\n\t\t\t\t\tsupersetId: z.coerce.number().nullable().optional(),\n\t\t\t\t\trestSeconds: z.coerce.number().int().min(0).optional(),\n\t\t\t\t\tnotes: z.string().optional(),\n\t\t\t\t\tsets: z.array(\n\t\t\t\t\t\tz.object({\n\t\t\t\t\t\t\ttype: setTypeEnum,\n\t\t\t\t\t\t\tweight: z.coerce.number().optional(),\n\t\t\t\t\t\t\tweightKg: z.coerce.number().optional(),\n\t\t\t\t\t\t\treps: zNullableInt,\n\t\t\t\t\t\t\tdistance: z.coerce.number().int().optional(),\n\t\t\t\t\t\t\tdistanceMeters: z.coerce.number().int().optional(),\n\t\t\t\t\t\t\tduration: z.coerce.number().int().optional(),\n\t\t\t\t\t\t\tdurationSeconds: z.coerce.number().int().optional(),\n\t\t\t\t\t\t\tcustomMetric: z.coerce.number().optional(),\n\t\t\t\t\t\t\trepRange: zOptionalRepRange,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t),\n\t\t),\n\t} as const;\n\ttype UpdateRoutineParams = InferToolParams<typeof updateRoutineSchema>;\n\n\tserver.tool(\n\t\t\"update-routine\",\n\t\t\"Update an existing routine by ID. You can modify the title, notes, and exercise configurations. Returns the updated routine with all changes applied.\",\n\t\tupdateRoutineSchema,\n\t\tupdateAnnotations(\"Update Routine\"),\n\t\twithErrorHandling(async (args: UpdateRoutineParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { routineId, title, notes, exercises } = args;\n\t\t\tlet usesRepRanges = false;\n\t\t\tconst data: PutV1RoutinesRoutineid200 = await client.updateRoutine(\n\t\t\t\troutineId,\n\t\t\t\t{\n\t\t\t\t\troutine: {\n\t\t\t\t\t\ttitle,\n\t\t\t\t\t\tnotes: notes ?? null,\n\t\t\t\t\t\texercises: exercises.map((exercise): PutRoutinesRequestExercise => {\n\t\t\t\t\t\t\tconst sets = exercise.sets.map((set): PutRoutinesRequestSet => {\n\t\t\t\t\t\t\t\tconst repRange = buildRepRange(set.repRange);\n\t\t\t\t\t\t\t\tconst fixedReps = getFixedRepsFromRepRange(repRange);\n\t\t\t\t\t\t\t\tconst reps =\n\t\t\t\t\t\t\t\t\ttypeof set.reps === \"number\" ? set.reps : fixedReps;\n\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\ttype: set.type as PutRoutinesRequestSetTypeEnumKey,\n\t\t\t\t\t\t\t\t\tweight_kg: set.weight ?? set.weightKg ?? null,\n\t\t\t\t\t\t\t\t\treps: reps ?? null,\n\t\t\t\t\t\t\t\t\tdistance_meters: set.distance ?? set.distanceMeters ?? null,\n\t\t\t\t\t\t\t\t\tduration_seconds: set.duration ?? set.durationSeconds ?? null,\n\t\t\t\t\t\t\t\t\tcustom_metric: set.customMetric ?? null,\n\t\t\t\t\t\t\t\t\t...(repRange ? { rep_range: repRange } : {}),\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\tsets.some(\n\t\t\t\t\t\t\t\t\t(set) =>\n\t\t\t\t\t\t\t\t\t\tset.rep_range != null &&\n\t\t\t\t\t\t\t\t\t\tgetFixedRepsFromRepRange(set.rep_range) === null,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tusesRepRanges = true;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\texercise_template_id: exercise.exerciseTemplateId,\n\t\t\t\t\t\t\t\tsuperset_id: exercise.supersetId ?? null,\n\t\t\t\t\t\t\t\trest_seconds: exercise.restSeconds ?? null,\n\t\t\t\t\t\t\t\tnotes: exercise.notes ?? null,\n\t\t\t\t\t\t\t\tsets,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t`Failed to update routine with ID ${routineId}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst routine = formatRoutine(data);\n\t\t\tconst response = createJsonResponse(routine, {\n\t\t\t\tpretty: true,\n\t\t\t\tindent: 2,\n\t\t\t});\n\n\t\t\tif (usesRepRanges) {\n\t\t\t\tresponse.content.push({\n\t\t\t\t\ttype: \"text\",\n\t\t\t\t\ttext: repRangeDisplayWarningText,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn response;\n\t\t}, \"update-routine\"),\n\t);\n}\n","export interface AsyncCacheOptions {\n\tttlMs: number;\n\tmaxSize: number;\n}\n\nexport interface CacheGetOptions {\n\trefresh?: boolean;\n}\n\ninterface CacheEntry<TValue> {\n\tvalue: TValue;\n\texpiresAt: number;\n}\n\ninterface InFlightEntry<TValue> {\n\tpromise: Promise<TValue>;\n\trequestId: number;\n}\n\n/**\n * Shared in-memory cache for async fetches with TTL, LRU eviction,\n * in-flight de-duplication, and explicit refresh/invalidation support.\n */\nexport class AsyncTtlCache<TKey, TValue> {\n\tprivate readonly ttlMs: number;\n\tprivate readonly maxSize: number;\n\tprivate readonly now: () => number;\n\tprivate readonly entries = new Map<TKey, CacheEntry<TValue>>();\n\tprivate readonly inFlight = new Map<TKey, InFlightEntry<TValue>>();\n\tprivate requestCounter = 0;\n\n\tconstructor(options: AsyncCacheOptions, now: () => number = Date.now) {\n\t\tconst { ttlMs, maxSize } = options;\n\t\tif (ttlMs <= 0) {\n\t\t\tthrow new Error(\"Cache ttlMs must be greater than 0.\");\n\t\t}\n\t\tif (maxSize <= 0) {\n\t\t\tthrow new Error(\"Cache maxSize must be greater than 0.\");\n\t\t}\n\n\t\tthis.ttlMs = ttlMs;\n\t\tthis.maxSize = maxSize;\n\t\tthis.now = now;\n\t}\n\n\tasync getOrFetch(\n\t\tkey: TKey,\n\t\tfetcher: () => Promise<TValue>,\n\t\toptions: CacheGetOptions = {},\n\t): Promise<TValue> {\n\t\tconst { refresh = false } = options;\n\n\t\tif (refresh) {\n\t\t\tthis.invalidate(key);\n\t\t} else {\n\t\t\tconst cachedEntry = this.entries.get(key);\n\t\t\tif (cachedEntry !== undefined) {\n\t\t\t\tif (cachedEntry.expiresAt > this.now()) {\n\t\t\t\t\tthis.markAsRecentlyUsed(key, cachedEntry);\n\t\t\t\t\treturn cachedEntry.value;\n\t\t\t\t}\n\n\t\t\t\tthis.entries.delete(key);\n\t\t\t}\n\n\t\t\tconst inFlightEntry = this.inFlight.get(key);\n\t\t\tif (inFlightEntry !== undefined) {\n\t\t\t\treturn inFlightEntry.promise;\n\t\t\t}\n\t\t}\n\n\t\tconst requestId = ++this.requestCounter;\n\t\tconst request = (async () => {\n\t\t\ttry {\n\t\t\t\tconst value = await fetcher();\n\n\t\t\t\tif (this.isCurrentRequest(key, requestId)) {\n\t\t\t\t\tthis.setValue(key, value);\n\t\t\t\t}\n\n\t\t\t\treturn value;\n\t\t\t} finally {\n\t\t\t\tconst inFlightEntry = this.inFlight.get(key);\n\t\t\t\tif (inFlightEntry?.requestId === requestId) {\n\t\t\t\t\tthis.inFlight.delete(key);\n\t\t\t\t}\n\t\t\t}\n\t\t})();\n\n\t\tthis.inFlight.set(key, { promise: request, requestId });\n\t\treturn request;\n\t}\n\n\tinvalidate(key: TKey): void {\n\t\tthis.entries.delete(key);\n\t\tthis.inFlight.delete(key);\n\t}\n\n\tclear(): void {\n\t\tthis.entries.clear();\n\t\tthis.inFlight.clear();\n\t}\n\n\tget size(): number {\n\t\treturn this.entries.size;\n\t}\n\n\tprivate isCurrentRequest(key: TKey, requestId: number): boolean {\n\t\treturn this.inFlight.get(key)?.requestId === requestId;\n\t}\n\n\tprivate markAsRecentlyUsed(key: TKey, entry: CacheEntry<TValue>): void {\n\t\tthis.entries.delete(key);\n\t\tthis.entries.set(key, entry);\n\t}\n\n\tprivate setValue(key: TKey, value: TValue): void {\n\t\tthis.entries.delete(key);\n\t\tthis.entries.set(key, {\n\t\t\tvalue,\n\t\t\texpiresAt: this.now() + this.ttlMs,\n\t\t});\n\n\t\tthis.evictLeastRecentlyUsed();\n\t}\n\n\tprivate evictLeastRecentlyUsed(): void {\n\t\twhile (this.entries.size > this.maxSize) {\n\t\t\tconst oldestKey = this.entries.keys().next().value;\n\t\t\tif (oldestKey === undefined) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.entries.delete(oldestKey);\n\t\t}\n\t}\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n// Import types from generated client\nimport type {\n\tExerciseTemplate,\n\tGetV1ExerciseHistoryExercisetemplateid200,\n\tGetV1ExerciseTemplates200,\n\tGetV1ExerciseTemplatesExercisetemplateid200,\n\tPostV1ExerciseTemplates200,\n} from \"../generated/client/types/index.js\";\nimport { AsyncTtlCache } from \"../utils/cache.js\";\nimport { withErrorHandling } from \"../utils/error-handler.js\";\nimport {\n\tformatExerciseHistoryEntry,\n\tformatExerciseTemplate,\n} from \"../utils/formatters.js\";\nimport {\n\tcreateEmptyResponse,\n\tcreateJsonResponse,\n} from \"../utils/response-formatter.js\";\nimport {\n\tcreateAnnotations,\n\treadOnlyAnnotations,\n} from \"../utils/tool-annotations.js\";\nimport { requireClient, type InferToolParams } from \"../utils/tool-helpers.js\";\nimport {\n\tequipmentCategoryEnum,\n\texerciseTypeEnum,\n\tmuscleGroupEnum,\n} from \"../utils/schemas.js\";\n\n// Type definitions for the template operations\ntype HevyClient = ReturnType<\n\ttypeof import(\"../utils/hevyClientKubb.js\").createClient\n>;\n\nconst EXERCISE_TEMPLATE_CATALOG_CACHE_KEY = \"exercise-template-catalog\";\nconst EXERCISE_TEMPLATE_CATALOG_CACHE_TTL_MS = 5 * 60 * 1000;\nconst EXERCISE_TEMPLATE_CATALOG_CACHE_MAX_SIZE = 1;\n\nconst exerciseTemplateCatalogCache = new AsyncTtlCache<\n\tstring,\n\tExerciseTemplate[]\n>({\n\tttlMs: EXERCISE_TEMPLATE_CATALOG_CACHE_TTL_MS,\n\tmaxSize: EXERCISE_TEMPLATE_CATALOG_CACHE_MAX_SIZE,\n});\n\nasync function fetchExerciseTemplateCatalog(\n\thevyClient: HevyClient,\n): Promise<ExerciseTemplate[]> {\n\tconst allTemplates: ExerciseTemplate[] = [];\n\tlet page = 1;\n\tlet pageCount = 1;\n\n\tdo {\n\t\tconst data: GetV1ExerciseTemplates200 =\n\t\t\tawait hevyClient.getExerciseTemplates({\n\t\t\t\tpage,\n\t\t\t\tpageSize: 100,\n\t\t\t});\n\n\t\tconst templates = data?.exercise_templates ?? [];\n\t\tallTemplates.push(...templates);\n\t\tpageCount = data?.page_count ?? 1;\n\t\tpage++;\n\t} while (page <= pageCount);\n\n\treturn allTemplates;\n}\n\n/** Reset the exercise template cache (exposed for testing). */\nexport function resetExerciseTemplateCache(): void {\n\texerciseTemplateCatalogCache.clear();\n}\n\n/**\n * Register all exercise template-related tools with the MCP server\n */\nexport function registerTemplateTools(\n\tserver: McpServer,\n\thevyClient: HevyClient | null,\n) {\n\t// Get exercise templates\n\tconst getExerciseTemplatesSchema = {\n\t\tpage: z.coerce.number().int().gte(1).default(1),\n\t\tpageSize: z.coerce.number().int().gte(1).lte(100).default(5),\n\t} as const;\n\ttype GetExerciseTemplatesParams = InferToolParams<\n\t\ttypeof getExerciseTemplatesSchema\n\t>;\n\n\tserver.tool(\n\t\t\"get-exercise-templates\",\n\t\t\"Get a paginated list of exercise templates (default and custom) with details like name, category, equipment, and muscle groups. Useful for browsing or searching available exercises.\",\n\t\tgetExerciseTemplatesSchema,\n\t\treadOnlyAnnotations(\"Get Exercise Templates\"),\n\t\twithErrorHandling(async (args: GetExerciseTemplatesParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { page, pageSize } = args;\n\t\t\tconst data: GetV1ExerciseTemplates200 = await client.getExerciseTemplates(\n\t\t\t\t{\n\t\t\t\t\tpage,\n\t\t\t\t\tpageSize,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\t// Process exercise templates to extract relevant information\n\t\t\tconst templates =\n\t\t\t\tdata?.exercise_templates?.map((template: ExerciseTemplate) =>\n\t\t\t\t\tformatExerciseTemplate(template),\n\t\t\t\t) || [];\n\n\t\t\tif (templates.length === 0) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"No exercise templates found for the specified parameters\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createJsonResponse(templates);\n\t\t}, \"get-exercise-templates\"),\n\t);\n\n\t// Get single exercise template by ID\n\tconst getExerciseTemplateSchema = {\n\t\texerciseTemplateId: z.string().min(1),\n\t} as const;\n\ttype GetExerciseTemplateParams = InferToolParams<\n\t\ttypeof getExerciseTemplateSchema\n\t>;\n\n\tserver.tool(\n\t\t\"get-exercise-template\",\n\t\t\"Get complete details of a specific exercise template by its ID, including name, category, equipment, muscle groups, and notes.\",\n\t\tgetExerciseTemplateSchema,\n\t\treadOnlyAnnotations(\"Get Exercise Template\"),\n\t\twithErrorHandling(async (args: GetExerciseTemplateParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { exerciseTemplateId } = args;\n\t\t\tconst data: GetV1ExerciseTemplatesExercisetemplateid200 =\n\t\t\t\tawait client.getExerciseTemplate(exerciseTemplateId);\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t`Exercise template with ID ${exerciseTemplateId} not found`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst template = formatExerciseTemplate(data);\n\t\t\treturn createJsonResponse(template);\n\t\t}, \"get-exercise-template\"),\n\t);\n\n\t// Get exercise history for a template\n\tconst getExerciseHistorySchema = {\n\t\texerciseTemplateId: z.string().min(1),\n\t\tstartDate: z\n\t\t\t.string()\n\t\t\t.datetime({ offset: true })\n\t\t\t.describe(\"ISO 8601 start date for filtering history\")\n\t\t\t.optional(),\n\t\tendDate: z\n\t\t\t.string()\n\t\t\t.datetime({ offset: true })\n\t\t\t.describe(\"ISO 8601 end date for filtering history\")\n\t\t\t.optional(),\n\t} as const;\n\ttype GetExerciseHistoryParams = InferToolParams<\n\t\ttypeof getExerciseHistorySchema\n\t>;\n\n\tserver.tool(\n\t\t\"get-exercise-history\",\n\t\t\"Get past sets for a specific exercise template, optionally filtered by start and end dates.\",\n\t\tgetExerciseHistorySchema,\n\t\treadOnlyAnnotations(\"Get Exercise History\"),\n\t\twithErrorHandling(async (args: GetExerciseHistoryParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { exerciseTemplateId, startDate, endDate } = args;\n\t\t\tconst data: GetV1ExerciseHistoryExercisetemplateid200 =\n\t\t\t\tawait client.getExerciseHistory(exerciseTemplateId, {\n\t\t\t\t\t...(startDate ? { start_date: startDate } : {}),\n\t\t\t\t\t...(endDate ? { end_date: endDate } : {}),\n\t\t\t\t});\n\n\t\t\tconst history =\n\t\t\t\tdata?.exercise_history?.map((entry) =>\n\t\t\t\t\tformatExerciseHistoryEntry(entry),\n\t\t\t\t) || [];\n\n\t\t\tif (history.length === 0) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t`No exercise history found for template ${exerciseTemplateId}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createJsonResponse(history);\n\t\t}, \"get-exercise-history\"),\n\t);\n\n\t// Create a custom exercise template\n\tconst createExerciseTemplateSchema = {\n\t\ttitle: z.string().min(1),\n\t\texerciseType: exerciseTypeEnum,\n\t\tequipmentCategory: equipmentCategoryEnum,\n\t\tmuscleGroup: muscleGroupEnum,\n\t\totherMuscles: z.array(muscleGroupEnum).default([]),\n\t} as const;\n\ttype CreateExerciseTemplateParams = InferToolParams<\n\t\ttypeof createExerciseTemplateSchema\n\t>;\n\n\tserver.tool(\n\t\t\"create-exercise-template\",\n\t\t\"Create a custom exercise template with title, type, equipment, and muscle groups.\",\n\t\tcreateExerciseTemplateSchema,\n\t\tcreateAnnotations(\"Create Exercise Template\"),\n\t\twithErrorHandling(async (args: CreateExerciseTemplateParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst {\n\t\t\t\ttitle,\n\t\t\t\texerciseType,\n\t\t\t\tequipmentCategory,\n\t\t\t\tmuscleGroup,\n\t\t\t\totherMuscles,\n\t\t\t} = args;\n\n\t\t\tconst response: PostV1ExerciseTemplates200 =\n\t\t\t\tawait client.createExerciseTemplate({\n\t\t\t\t\texercise: {\n\t\t\t\t\t\ttitle,\n\t\t\t\t\t\texercise_type: exerciseType,\n\t\t\t\t\t\tequipment_category: equipmentCategory,\n\t\t\t\t\t\tmuscle_group: muscleGroup,\n\t\t\t\t\t\tother_muscles: otherMuscles,\n\t\t\t\t\t},\n\t\t\t\t});\n\n\t\t\treturn createJsonResponse({\n\t\t\t\tid: response?.id,\n\t\t\t\tmessage: \"Exercise template created successfully\",\n\t\t\t});\n\t\t}, \"create-exercise-template\"),\n\t);\n\n\t// Search exercise templates (cached)\n\tconst searchExerciseTemplatesSchema = {\n\t\tquery: z\n\t\t\t.string()\n\t\t\t.min(1)\n\t\t\t.describe(\n\t\t\t\t\"Case-insensitive substring to match against exercise template titles\",\n\t\t\t),\n\t\tprimaryMuscleGroup: muscleGroupEnum\n\t\t\t.optional()\n\t\t\t.describe(\n\t\t\t\t\"Optional filter to restrict results to a specific primary muscle group\",\n\t\t\t),\n\t\trefresh: z\n\t\t\t.boolean()\n\t\t\t.optional()\n\t\t\t.default(false)\n\t\t\t.describe(\n\t\t\t\t\"Set to true to invalidate the catalog cache and re-fetch all templates from the API\",\n\t\t\t),\n\t} as const;\n\ttype SearchExerciseTemplatesParams = InferToolParams<\n\t\ttypeof searchExerciseTemplatesSchema\n\t>;\n\n\tserver.tool(\n\t\t\"search-exercise-templates\",\n\t\t\"Search exercise templates by name with optional muscle group filter. Fetches all templates from the Hevy API on first call, caches the catalog in memory with a bounded TTL cache, and reuses it for subsequent searches. Use refresh:true to force a re-fetch.\",\n\t\tsearchExerciseTemplatesSchema,\n\t\treadOnlyAnnotations(\"Search Exercise Templates\"),\n\t\twithErrorHandling(async (args: SearchExerciseTemplatesParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { query, primaryMuscleGroup, refresh } = args;\n\t\t\tconst catalog = await exerciseTemplateCatalogCache.getOrFetch(\n\t\t\t\tEXERCISE_TEMPLATE_CATALOG_CACHE_KEY,\n\t\t\t\t() => fetchExerciseTemplateCatalog(client),\n\t\t\t\t{ refresh },\n\t\t\t);\n\n\t\t\t// Filter by query (case-insensitive title substring match)\n\t\t\tconst queryLower = query.toLowerCase();\n\t\t\tlet results = catalog.filter((t) =>\n\t\t\t\t(t.title ?? \"\").toLowerCase().includes(queryLower),\n\t\t\t);\n\n\t\t\t// Optional primary muscle group filter\n\t\t\tif (primaryMuscleGroup !== undefined) {\n\t\t\t\tresults = results.filter(\n\t\t\t\t\t(t) => t.primary_muscle_group === primaryMuscleGroup,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (results.length === 0) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t`No exercise templates found matching \"${query}\"${primaryMuscleGroup ? ` with primary muscle group \"${primaryMuscleGroup}\"` : \"\"}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createJsonResponse(results.map(formatExerciseTemplate));\n\t\t}, \"search-exercise-templates\"),\n\t);\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { UserInfoResponse } from \"../generated/client/types/index.js\";\nimport { withErrorHandling } from \"../utils/error-handler.js\";\nimport {\n\tcreateEmptyResponse,\n\tcreateJsonResponse,\n} from \"../utils/response-formatter.js\";\nimport { readOnlyAnnotations } from \"../utils/tool-annotations.js\";\nimport { requireClient, type InferToolParams } from \"../utils/tool-helpers.js\";\n\ntype HevyClient = ReturnType<\n\ttypeof import(\"../utils/hevyClientKubb.js\").createClient\n>;\n\nexport function registerUserTools(\n\tserver: McpServer,\n\thevyClient: HevyClient | null,\n) {\n\t// Get user info\n\tconst getUserInfoSchema = {} as const;\n\ttype GetUserInfoParams = InferToolParams<typeof getUserInfoSchema>;\n\n\tserver.tool(\n\t\t\"get-user-info\",\n\t\t\"Get the authenticated user's account info, including user ID, display name, and public profile URL. Useful for verifying which account the API key belongs to.\",\n\t\tgetUserInfoSchema,\n\t\treadOnlyAnnotations(\"Get User Info\"),\n\t\twithErrorHandling(async (_args: GetUserInfoParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst data: UserInfoResponse = await client.getUserInfo();\n\t\t\tif (!data?.data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"No user info found for the authenticated user\",\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn createJsonResponse(data.data);\n\t\t}, \"get-user-info\"),\n\t);\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type {\n\tGetV1Workouts200,\n\tGetV1WorkoutsCount200,\n\tGetV1WorkoutsEvents200,\n\tGetV1WorkoutsWorkoutid200,\n\tPostV1Workouts201,\n\tPostWorkoutsRequestBody,\n\tPostWorkoutsRequestExercise,\n\tPostWorkoutsRequestSetRpeEnumKey,\n\tPostWorkoutsRequestSetTypeEnumKey,\n\tPutV1WorkoutsWorkoutid200,\n} from \"../generated/client/types/index.js\";\nimport { withErrorHandling } from \"../utils/error-handler.js\";\nimport { formatWorkout } from \"../utils/formatters.js\";\nimport type { HevyClient } from \"../utils/hevyClient.js\";\nimport { parseJsonArray } from \"../utils/json-parser.js\";\nimport {\n\tcreateEmptyResponse,\n\tcreateJsonResponse,\n} from \"../utils/response-formatter.js\";\nimport {\n\tcreateAnnotations,\n\treadOnlyAnnotations,\n\tupdateAnnotations,\n} from \"../utils/tool-annotations.js\";\nimport { requireClient, type InferToolParams } from \"../utils/tool-helpers.js\";\nimport { setTypeEnum } from \"../utils/schemas.js\";\n\n/**\n * Register all workout-related tools with the MCP server\n */\nexport function registerWorkoutTools(\n\tserver: McpServer,\n\thevyClient: HevyClient | null,\n) {\n\t// Get workouts\n\tconst getWorkoutsSchema = {\n\t\tpage: z.coerce.number().gte(1).default(1),\n\t\tpageSize: z.coerce.number().int().gte(1).lte(10).default(5),\n\t} as const;\n\ttype GetWorkoutsParams = InferToolParams<typeof getWorkoutsSchema>;\n\n\tserver.tool(\n\t\t\"get-workouts\",\n\t\t\"Get a paginated list of workouts. Returns workout details including title, description, start/end times, and exercises performed. Results are ordered from newest to oldest.\",\n\t\tgetWorkoutsSchema,\n\t\treadOnlyAnnotations(\"Get Workouts\"),\n\t\twithErrorHandling(async (args: GetWorkoutsParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { page, pageSize } = args;\n\t\t\tconst data: GetV1Workouts200 = await client.getWorkouts({\n\t\t\t\tpage,\n\t\t\t\tpageSize,\n\t\t\t});\n\n\t\t\tconst workouts =\n\t\t\t\tdata?.workouts?.map((workout) => formatWorkout(workout)) || [];\n\n\t\t\tif (workouts.length === 0) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"No workouts found for the specified parameters\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createJsonResponse(workouts);\n\t\t}, \"get-workouts\"),\n\t);\n\n\t// Get single workout by ID\n\tconst getWorkoutSchema = {\n\t\tworkoutId: z.string().min(1),\n\t} as const;\n\ttype GetWorkoutParams = InferToolParams<typeof getWorkoutSchema>;\n\n\tserver.tool(\n\t\t\"get-workout\",\n\t\t\"Get complete details of a specific workout by ID. Returns all workout information including title, description, start/end times, and detailed exercise data.\",\n\t\tgetWorkoutSchema,\n\t\treadOnlyAnnotations(\"Get Workout\"),\n\t\twithErrorHandling(async (args: GetWorkoutParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { workoutId } = args;\n\t\t\tconst data: GetV1WorkoutsWorkoutid200 =\n\t\t\t\tawait client.getWorkout(workoutId);\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(`Workout with ID ${workoutId} not found`);\n\t\t\t}\n\n\t\t\tconst workout = formatWorkout(data);\n\t\t\treturn createJsonResponse(workout);\n\t\t}, \"get-workout\"),\n\t);\n\n\t// Get workout count\n\tserver.tool(\n\t\t\"get-workout-count\",\n\t\t\"Get the total number of workouts on the account. Useful for pagination or statistics.\",\n\t\t{},\n\t\treadOnlyAnnotations(\"Get Workout Count\"),\n\t\twithErrorHandling(async () => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst data: GetV1WorkoutsCount200 = await client.getWorkoutCount();\n\t\t\tconst count = data?.workout_count ?? 0;\n\t\t\treturn createJsonResponse({ count });\n\t\t}, \"get-workout-count\"),\n\t);\n\n\t// Get workout events (updates/deletes)\n\tconst getWorkoutEventsSchema = {\n\t\tpage: z.coerce.number().int().gte(1).default(1),\n\t\tpageSize: z.coerce.number().int().gte(1).lte(10).default(5),\n\t\tsince: z.string().default(\"1970-01-01T00:00:00Z\"),\n\t} as const;\n\ttype GetWorkoutEventsParams = InferToolParams<typeof getWorkoutEventsSchema>;\n\n\tserver.tool(\n\t\t\"get-workout-events\",\n\t\t\"Retrieve a paged list of workout events (updates or deletes) since a given date. Events are ordered from newest to oldest. The intention is to allow clients to keep their local cache of workouts up to date without having to fetch the entire list of workouts.\",\n\t\tgetWorkoutEventsSchema,\n\t\treadOnlyAnnotations(\"Get Workout Events\"),\n\t\twithErrorHandling(async (args: GetWorkoutEventsParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { page, pageSize, since } = args;\n\t\t\tconst data: GetV1WorkoutsEvents200 = await client.getWorkoutEvents({\n\t\t\t\tpage,\n\t\t\t\tpageSize,\n\t\t\t\tsince,\n\t\t\t});\n\n\t\t\tconst events = data?.events || [];\n\n\t\t\tif (events.length === 0) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t`No workout events found for the specified parameters since ${since}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createJsonResponse(events);\n\t\t}, \"get-workout-events\"),\n\t);\n\n\t// Create workout\n\tconst createWorkoutSchema = {\n\t\ttitle: z.string().min(1),\n\t\tdescription: z.string().optional().nullable(),\n\t\tstartTime: z.string().regex(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$/),\n\t\tendTime: z.string().regex(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$/),\n\t\tisPrivate: z.boolean().default(false),\n\t\texercises: z.preprocess(\n\t\t\tparseJsonArray,\n\t\t\tz.array(\n\t\t\t\tz.object({\n\t\t\t\t\texerciseTemplateId: z.string().min(1),\n\t\t\t\t\tsupersetId: z.coerce.number().nullable().optional(),\n\t\t\t\t\tnotes: z.string().optional().nullable(),\n\t\t\t\t\tsets: z.array(\n\t\t\t\t\t\tz.object({\n\t\t\t\t\t\t\ttype: setTypeEnum,\n\t\t\t\t\t\t\tweight: z.coerce.number().optional().nullable(),\n\t\t\t\t\t\t\tweightKg: z.coerce.number().optional().nullable(),\n\t\t\t\t\t\t\treps: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\tdistance: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\tdistanceMeters: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\tduration: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\tdurationSeconds: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\trpe: z.coerce.number().optional().nullable(),\n\t\t\t\t\t\t\tcustomMetric: z.coerce.number().optional().nullable(),\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t),\n\t\t),\n\t} as const;\n\ttype CreateWorkoutParams = InferToolParams<typeof createWorkoutSchema>;\n\n\tserver.tool(\n\t\t\"create-workout\",\n\t\t\"Create a new workout in your Hevy account. Requires title, start/end times, and at least one exercise with sets. Returns the complete workout details upon successful creation including the newly assigned workout ID.\",\n\t\tcreateWorkoutSchema,\n\t\tcreateAnnotations(\"Create Workout\"),\n\t\twithErrorHandling(async (args: CreateWorkoutParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { title, description, startTime, endTime, isPrivate, exercises } =\n\t\t\t\targs;\n\t\t\tconst workoutPayload: NonNullable<PostWorkoutsRequestBody[\"workout\"]> = {\n\t\t\t\ttitle,\n\t\t\t\tdescription: description ?? null,\n\t\t\t\tstart_time: startTime,\n\t\t\t\tend_time: endTime,\n\t\t\t\tis_private: isPrivate,\n\t\t\t\texercises: exercises.map(\n\t\t\t\t\t(exercise): PostWorkoutsRequestExercise => ({\n\t\t\t\t\t\texercise_template_id: exercise.exerciseTemplateId,\n\t\t\t\t\t\tsuperset_id: exercise.supersetId ?? null,\n\t\t\t\t\t\tnotes: exercise.notes ?? null,\n\t\t\t\t\t\tsets: exercise.sets.map((set) => ({\n\t\t\t\t\t\t\ttype: set.type as PostWorkoutsRequestSetTypeEnumKey,\n\t\t\t\t\t\t\tweight_kg: set.weight ?? set.weightKg ?? null,\n\t\t\t\t\t\t\treps: set.reps ?? null,\n\t\t\t\t\t\t\tdistance_meters: set.distance ?? set.distanceMeters ?? null,\n\t\t\t\t\t\t\tduration_seconds: set.duration ?? set.durationSeconds ?? null,\n\t\t\t\t\t\t\trpe: (set.rpe as PostWorkoutsRequestSetRpeEnumKey | null) ?? null,\n\t\t\t\t\t\t\tcustom_metric: set.customMetric ?? null,\n\t\t\t\t\t\t})),\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t};\n\t\t\tconst requestBody: PostWorkoutsRequestBody = { workout: workoutPayload };\n\n\t\t\tconst data: PostV1Workouts201 = await client.createWorkout(requestBody);\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"Failed to create workout: Server returned no data\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst workout = formatWorkout(data);\n\t\t\treturn createJsonResponse(workout, {\n\t\t\t\tpretty: true,\n\t\t\t\tindent: 2,\n\t\t\t});\n\t\t}, \"create-workout\"),\n\t);\n\n\t// Update workout\n\tconst updateWorkoutSchema = {\n\t\tworkoutId: z.string().min(1),\n\t\ttitle: z.string().min(1),\n\t\tdescription: z.string().optional().nullable(),\n\t\tstartTime: z.string().regex(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$/),\n\t\tendTime: z.string().regex(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$/),\n\t\tisPrivate: z.boolean().default(false),\n\t\texercises: z.preprocess(\n\t\t\tparseJsonArray,\n\t\t\tz.array(\n\t\t\t\tz.object({\n\t\t\t\t\texerciseTemplateId: z.string().min(1),\n\t\t\t\t\tsupersetId: z.coerce.number().nullable().optional(),\n\t\t\t\t\tnotes: z.string().optional().nullable(),\n\t\t\t\t\tsets: z.array(\n\t\t\t\t\t\tz.object({\n\t\t\t\t\t\t\ttype: setTypeEnum,\n\t\t\t\t\t\t\tweight: z.coerce.number().optional().nullable(),\n\t\t\t\t\t\t\tweightKg: z.coerce.number().optional().nullable(),\n\t\t\t\t\t\t\treps: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\tdistance: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\tdistanceMeters: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\tduration: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\tdurationSeconds: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\trpe: z.coerce.number().optional().nullable(),\n\t\t\t\t\t\t\tcustomMetric: z.coerce.number().optional().nullable(),\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t),\n\t\t),\n\t} as const;\n\ttype UpdateWorkoutParams = InferToolParams<typeof updateWorkoutSchema>;\n\n\tserver.tool(\n\t\t\"update-workout\",\n\t\t\"Update an existing workout by ID. You can modify the title, description, start/end times, privacy setting, and exercise data. Returns the updated workout with all changes applied.\",\n\t\tupdateWorkoutSchema,\n\t\tupdateAnnotations(\"Update Workout\"),\n\t\twithErrorHandling(async (args: UpdateWorkoutParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst {\n\t\t\t\tworkoutId,\n\t\t\t\ttitle,\n\t\t\t\tdescription,\n\t\t\t\tstartTime,\n\t\t\t\tendTime,\n\t\t\t\tisPrivate,\n\t\t\t\texercises,\n\t\t\t} = args;\n\t\t\tconst workoutPayload: NonNullable<PostWorkoutsRequestBody[\"workout\"]> = {\n\t\t\t\ttitle,\n\t\t\t\tdescription: description ?? null,\n\t\t\t\tstart_time: startTime,\n\t\t\t\tend_time: endTime,\n\t\t\t\tis_private: isPrivate,\n\t\t\t\texercises: exercises.map(\n\t\t\t\t\t(exercise): PostWorkoutsRequestExercise => ({\n\t\t\t\t\t\texercise_template_id: exercise.exerciseTemplateId,\n\t\t\t\t\t\tsuperset_id: exercise.supersetId ?? null,\n\t\t\t\t\t\tnotes: exercise.notes ?? null,\n\t\t\t\t\t\tsets: exercise.sets.map((set) => ({\n\t\t\t\t\t\t\ttype: set.type as PostWorkoutsRequestSetTypeEnumKey,\n\t\t\t\t\t\t\tweight_kg: set.weight ?? set.weightKg ?? null,\n\t\t\t\t\t\t\treps: set.reps ?? null,\n\t\t\t\t\t\t\tdistance_meters: set.distance ?? set.distanceMeters ?? null,\n\t\t\t\t\t\t\tduration_seconds: set.duration ?? set.durationSeconds ?? null,\n\t\t\t\t\t\t\trpe: (set.rpe as PostWorkoutsRequestSetRpeEnumKey | null) ?? null,\n\t\t\t\t\t\t\tcustom_metric: set.customMetric ?? null,\n\t\t\t\t\t\t})),\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t};\n\t\t\tconst requestBody: PostWorkoutsRequestBody = { workout: workoutPayload };\n\n\t\t\tconst data: PutV1WorkoutsWorkoutid200 = await client.updateWorkout(\n\t\t\t\tworkoutId,\n\t\t\t\trequestBody,\n\t\t\t);\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t`Failed to update workout with ID ${workoutId}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst workout = formatWorkout(data);\n\t\t\treturn createJsonResponse(workout, {\n\t\t\t\tpretty: true,\n\t\t\t\tindent: 2,\n\t\t\t});\n\t\t}, \"update-workout-operation\"),\n\t);\n}\n","export interface HevyConfig {\n\tapiKey?: string;\n}\n\nconst DEPRECATED_CLI_ARGUMENT_WARNING = [\n\t\"DEPRECATION WARNING: Passing the Hevy API key via CLI arguments\",\n\t\"(--hevy-api-key=..., --hevyApiKey=..., hevy-api-key=...) is\",\n\t\"deprecated and insecure. Use the HEVY_API_KEY environment\",\n\t\"variable instead.\",\n].join(\" \");\n\n/**\n * Parse CLI arguments and environment to derive configuration.\n * Priority order for API key: deprecated CLI flag forms > environment variable.\n * Supported deprecated CLI arg forms:\n * --hevy-api-key=KEY\n * --hevyApiKey=KEY\n * hevy-api-key=KEY (bare, e.g. when passed after npm start -- )\n */\nexport function parseConfig(\n\targv: string[],\n\tenv: NodeJS.ProcessEnv,\n): HevyConfig {\n\tlet apiKey = \"\";\n\tlet usedDeprecatedApiKeyArg = false;\n\tconst apiKeyArgPatterns = [\n\t\t/^--hevy-api-key=(.+)$/i,\n\t\t/^--hevyApiKey=(.+)$/i,\n\t\t/^hevy-api-key=(.+)$/i,\n\t];\n\tfor (const raw of argv) {\n\t\tfor (const pattern of apiKeyArgPatterns) {\n\t\t\tconst m = raw.match(pattern);\n\t\t\tif (m) {\n\t\t\t\tapiKey = m[1];\n\t\t\t\tusedDeprecatedApiKeyArg = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (apiKey) break;\n\t}\n\tif (usedDeprecatedApiKeyArg) {\n\t\tconsole.error(DEPRECATED_CLI_ARGUMENT_WARNING);\n\t}\n\tif (!apiKey) {\n\t\tapiKey = env.HEVY_API_KEY || \"\";\n\t}\n\n\treturn {\n\t\tapiKey,\n\t};\n}\n\nexport function assertApiKey(\n\tapiKey: string | undefined,\n): asserts apiKey is string {\n\tif (!apiKey) {\n\t\tconsole.error(\n\t\t\t\"Hevy API key is required. Provide it via the HEVY_API_KEY environment variable.\",\n\t\t);\n\t\tprocess.exit(1);\n\t}\n}\n","import type { AxiosError, AxiosRequestConfig, AxiosResponse } from \"axios\";\nimport axios from \"axios\";\n\ndeclare const AXIOS_BASE: string;\ndeclare const AXIOS_HEADERS: string;\n\n/**\n * Subset of AxiosRequestConfig\n */\nexport type RequestConfig<TData = unknown> = {\n baseURL?: string;\n url?: string;\n method?: \"GET\" | \"PUT\" | \"PATCH\" | \"POST\" | \"DELETE\" | \"OPTIONS\" | \"HEAD\";\n params?: unknown;\n data?: TData | FormData;\n responseType?:\n | \"arraybuffer\"\n | \"blob\"\n | \"document\"\n | \"json\"\n | \"text\"\n | \"stream\";\n signal?: AbortSignal;\n validateStatus?: (status: number) => boolean;\n headers?: AxiosRequestConfig[\"headers\"];\n};\n\n/**\n * Subset of AxiosResponse\n */\nexport type ResponseConfig<TData = unknown> = {\n data: TData;\n status: number;\n statusText: string;\n headers: AxiosResponse[\"headers\"];\n};\n\nexport type ResponseErrorConfig<TError = unknown> = AxiosError<TError>;\n\nexport type Client = <TData, _TError = unknown, TVariables = unknown>(\n config: RequestConfig<TVariables>,\n) => Promise<ResponseConfig<TData>>;\n\nlet _config: Partial<RequestConfig> = {\n baseURL: typeof AXIOS_BASE !== \"undefined\" ? AXIOS_BASE : undefined,\n headers:\n typeof AXIOS_HEADERS !== \"undefined\"\n ? JSON.parse(AXIOS_HEADERS)\n : undefined,\n};\n\nexport const getConfig = () => _config;\n\nexport const setConfig = (config: RequestConfig) => {\n _config = config;\n return getConfig();\n};\n\nexport const mergeConfig = <T extends RequestConfig>(\n ...configs: Array<Partial<T>>\n): Partial<T> => {\n return configs.reduce<Partial<T>>((merged, config) => {\n return {\n ...merged,\n ...config,\n headers: {\n ...merged.headers,\n ...config.headers,\n },\n };\n }, {});\n};\n\nexport const axiosInstance = axios.create(getConfig());\n\nexport const fetch = async <TData, TError = unknown, TVariables = unknown>(\n config: RequestConfig<TVariables>,\n): Promise<ResponseConfig<TData>> => {\n return axiosInstance\n .request<TData, ResponseConfig<TData>>(mergeConfig(getConfig(), config))\n .catch((e: AxiosError<TError>) => {\n throw e;\n });\n};\n\nfetch.getConfig = getConfig;\nfetch.setConfig = setConfig;\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n GetV1BodyMeasurementsQueryResponse,\n GetV1BodyMeasurementsQueryParams,\n GetV1BodyMeasurementsHeaderParams,\n GetV1BodyMeasurements400,\n GetV1BodyMeasurements404,\n} from \"../types/GetV1BodyMeasurements.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getGetV1BodyMeasurementsUrl() {\n const res = { method: \"GET\", url: `/v1/body_measurements` as const };\n return res;\n}\n\n/**\n * @summary Get a paginated list of body measurements for the authenticated user\n * {@link /v1/body_measurements}\n */\nexport async function getV1BodyMeasurements(\n headers: GetV1BodyMeasurementsHeaderParams,\n params?: GetV1BodyMeasurementsQueryParams,\n config: Partial<RequestConfig> & { client?: Client } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1BodyMeasurementsQueryResponse,\n ResponseErrorConfig<GetV1BodyMeasurements400 | GetV1BodyMeasurements404>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1BodyMeasurementsUrl().url.toString(),\n params,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n GetV1BodyMeasurementsDateQueryResponse,\n GetV1BodyMeasurementsDatePathParams,\n GetV1BodyMeasurementsDateHeaderParams,\n GetV1BodyMeasurementsDate404,\n} from \"../types/GetV1BodyMeasurementsDate.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getGetV1BodyMeasurementsDateUrl(\n date: GetV1BodyMeasurementsDatePathParams[\"date\"],\n) {\n const res = { method: \"GET\", url: `/v1/body_measurements/${date}` as const };\n return res;\n}\n\n/**\n * @summary Get a single body measurement by date\n * {@link /v1/body_measurements/:date}\n */\nexport async function getV1BodyMeasurementsDate(\n date: GetV1BodyMeasurementsDatePathParams[\"date\"],\n headers: GetV1BodyMeasurementsDateHeaderParams,\n config: Partial<RequestConfig> & { client?: Client } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1BodyMeasurementsDateQueryResponse,\n ResponseErrorConfig<GetV1BodyMeasurementsDate404>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1BodyMeasurementsDateUrl(date).url.toString(),\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n GetV1ExerciseHistoryExercisetemplateidQueryResponse,\n GetV1ExerciseHistoryExercisetemplateidPathParams,\n GetV1ExerciseHistoryExercisetemplateidQueryParams,\n GetV1ExerciseHistoryExercisetemplateidHeaderParams,\n GetV1ExerciseHistoryExercisetemplateid400,\n} from \"../types/GetV1ExerciseHistoryExercisetemplateid.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getGetV1ExerciseHistoryExercisetemplateidUrl(\n exerciseTemplateId: GetV1ExerciseHistoryExercisetemplateidPathParams[\"exerciseTemplateId\"],\n) {\n const res = {\n method: \"GET\",\n url: `/v1/exercise_history/${exerciseTemplateId}` as const,\n };\n return res;\n}\n\n/**\n * @summary Get exercise history for a specific exercise template\n * {@link /v1/exercise_history/:exerciseTemplateId}\n */\nexport async function getV1ExerciseHistoryExercisetemplateid(\n exerciseTemplateId: GetV1ExerciseHistoryExercisetemplateidPathParams[\"exerciseTemplateId\"],\n headers: GetV1ExerciseHistoryExercisetemplateidHeaderParams,\n params?: GetV1ExerciseHistoryExercisetemplateidQueryParams,\n config: Partial<RequestConfig> & { client?: Client } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1ExerciseHistoryExercisetemplateidQueryResponse,\n ResponseErrorConfig<GetV1ExerciseHistoryExercisetemplateid400>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1ExerciseHistoryExercisetemplateidUrl(\n exerciseTemplateId,\n ).url.toString(),\n params,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n GetV1ExerciseTemplatesQueryResponse,\n GetV1ExerciseTemplatesQueryParams,\n GetV1ExerciseTemplatesHeaderParams,\n GetV1ExerciseTemplates400,\n} from \"../types/GetV1ExerciseTemplates.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getGetV1ExerciseTemplatesUrl() {\n const res = { method: \"GET\", url: `/v1/exercise_templates` as const };\n return res;\n}\n\n/**\n * @summary Get a paginated list of exercise templates available on the account.\n * {@link /v1/exercise_templates}\n */\nexport async function getV1ExerciseTemplates(\n headers: GetV1ExerciseTemplatesHeaderParams,\n params?: GetV1ExerciseTemplatesQueryParams,\n config: Partial<RequestConfig> & { client?: Client } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1ExerciseTemplatesQueryResponse,\n ResponseErrorConfig<GetV1ExerciseTemplates400>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1ExerciseTemplatesUrl().url.toString(),\n params,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n GetV1ExerciseTemplatesExercisetemplateidQueryResponse,\n GetV1ExerciseTemplatesExercisetemplateidPathParams,\n GetV1ExerciseTemplatesExercisetemplateidHeaderParams,\n GetV1ExerciseTemplatesExercisetemplateid404,\n} from \"../types/GetV1ExerciseTemplatesExercisetemplateid.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getGetV1ExerciseTemplatesExercisetemplateidUrl(\n exerciseTemplateId: GetV1ExerciseTemplatesExercisetemplateidPathParams[\"exerciseTemplateId\"],\n) {\n const res = {\n method: \"GET\",\n url: `/v1/exercise_templates/${exerciseTemplateId}` as const,\n };\n return res;\n}\n\n/**\n * @summary Get a single exercise template by id.\n * {@link /v1/exercise_templates/:exerciseTemplateId}\n */\nexport async function getV1ExerciseTemplatesExercisetemplateid(\n exerciseTemplateId: GetV1ExerciseTemplatesExercisetemplateidPathParams[\"exerciseTemplateId\"],\n headers: GetV1ExerciseTemplatesExercisetemplateidHeaderParams,\n config: Partial<RequestConfig> & { client?: Client } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1ExerciseTemplatesExercisetemplateidQueryResponse,\n ResponseErrorConfig<GetV1ExerciseTemplatesExercisetemplateid404>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1ExerciseTemplatesExercisetemplateidUrl(\n exerciseTemplateId,\n ).url.toString(),\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n GetV1RoutineFoldersQueryResponse,\n GetV1RoutineFoldersQueryParams,\n GetV1RoutineFoldersHeaderParams,\n GetV1RoutineFolders400,\n} from \"../types/GetV1RoutineFolders.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getGetV1RoutineFoldersUrl() {\n const res = { method: \"GET\", url: `/v1/routine_folders` as const };\n return res;\n}\n\n/**\n * @summary Get a paginated list of routine folders available on the account.\n * {@link /v1/routine_folders}\n */\nexport async function getV1RoutineFolders(\n headers: GetV1RoutineFoldersHeaderParams,\n params?: GetV1RoutineFoldersQueryParams,\n config: Partial<RequestConfig> & { client?: Client } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1RoutineFoldersQueryResponse,\n ResponseErrorConfig<GetV1RoutineFolders400>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1RoutineFoldersUrl().url.toString(),\n params,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n GetV1RoutineFoldersFolderidQueryResponse,\n GetV1RoutineFoldersFolderidPathParams,\n GetV1RoutineFoldersFolderidHeaderParams,\n GetV1RoutineFoldersFolderid404,\n} from \"../types/GetV1RoutineFoldersFolderid.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getGetV1RoutineFoldersFolderidUrl(\n folderId: GetV1RoutineFoldersFolderidPathParams[\"folderId\"],\n) {\n const res = {\n method: \"GET\",\n url: `/v1/routine_folders/${folderId}` as const,\n };\n return res;\n}\n\n/**\n * @summary Get a single routine folder by id.\n * {@link /v1/routine_folders/:folderId}\n */\nexport async function getV1RoutineFoldersFolderid(\n folderId: GetV1RoutineFoldersFolderidPathParams[\"folderId\"],\n headers: GetV1RoutineFoldersFolderidHeaderParams,\n config: Partial<RequestConfig> & { client?: Client } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1RoutineFoldersFolderidQueryResponse,\n ResponseErrorConfig<GetV1RoutineFoldersFolderid404>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1RoutineFoldersFolderidUrl(folderId).url.toString(),\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n GetV1RoutinesQueryResponse,\n GetV1RoutinesQueryParams,\n GetV1RoutinesHeaderParams,\n GetV1Routines400,\n} from \"../types/GetV1Routines.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getGetV1RoutinesUrl() {\n const res = { method: \"GET\", url: `/v1/routines` as const };\n return res;\n}\n\n/**\n * @summary Get a paginated list of routines\n * {@link /v1/routines}\n */\nexport async function getV1Routines(\n headers: GetV1RoutinesHeaderParams,\n params?: GetV1RoutinesQueryParams,\n config: Partial<RequestConfig> & { client?: Client } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1RoutinesQueryResponse,\n ResponseErrorConfig<GetV1Routines400>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1RoutinesUrl().url.toString(),\n params,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n GetV1RoutinesRoutineidQueryResponse,\n GetV1RoutinesRoutineidPathParams,\n GetV1RoutinesRoutineidHeaderParams,\n GetV1RoutinesRoutineid400,\n} from \"../types/GetV1RoutinesRoutineid.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getGetV1RoutinesRoutineidUrl(\n routineId: GetV1RoutinesRoutineidPathParams[\"routineId\"],\n) {\n const res = { method: \"GET\", url: `/v1/routines/${routineId}` as const };\n return res;\n}\n\n/**\n * @summary Get a routine by its Id\n * {@link /v1/routines/:routineId}\n */\nexport async function getV1RoutinesRoutineid(\n routineId: GetV1RoutinesRoutineidPathParams[\"routineId\"],\n headers: GetV1RoutinesRoutineidHeaderParams,\n config: Partial<RequestConfig> & { client?: Client } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1RoutinesRoutineidQueryResponse,\n ResponseErrorConfig<GetV1RoutinesRoutineid400>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1RoutinesRoutineidUrl(routineId).url.toString(),\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n GetV1UserInfoQueryResponse,\n GetV1UserInfoHeaderParams,\n GetV1UserInfo404,\n} from \"../types/GetV1UserInfo.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getGetV1UserInfoUrl() {\n const res = { method: \"GET\", url: `/v1/user/info` as const };\n return res;\n}\n\n/**\n * @summary Get user info\n * {@link /v1/user/info}\n */\nexport async function getV1UserInfo(\n headers: GetV1UserInfoHeaderParams,\n config: Partial<RequestConfig> & { client?: Client } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1UserInfoQueryResponse,\n ResponseErrorConfig<GetV1UserInfo404>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1UserInfoUrl().url.toString(),\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n GetV1WorkoutsQueryResponse,\n GetV1WorkoutsQueryParams,\n GetV1WorkoutsHeaderParams,\n GetV1Workouts400,\n} from \"../types/GetV1Workouts.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getGetV1WorkoutsUrl() {\n const res = { method: \"GET\", url: `/v1/workouts` as const };\n return res;\n}\n\n/**\n * @summary Get a paginated list of workouts\n * {@link /v1/workouts}\n */\nexport async function getV1Workouts(\n headers: GetV1WorkoutsHeaderParams,\n params?: GetV1WorkoutsQueryParams,\n config: Partial<RequestConfig> & { client?: Client } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1WorkoutsQueryResponse,\n ResponseErrorConfig<GetV1Workouts400>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1WorkoutsUrl().url.toString(),\n params,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n GetV1WorkoutsCountQueryResponse,\n GetV1WorkoutsCountHeaderParams,\n} from \"../types/GetV1WorkoutsCount.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getGetV1WorkoutsCountUrl() {\n const res = { method: \"GET\", url: `/v1/workouts/count` as const };\n return res;\n}\n\n/**\n * @summary Get the total number of workouts on the account\n * {@link /v1/workouts/count}\n */\nexport async function getV1WorkoutsCount(\n headers: GetV1WorkoutsCountHeaderParams,\n config: Partial<RequestConfig> & { client?: Client } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1WorkoutsCountQueryResponse,\n ResponseErrorConfig<Error>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1WorkoutsCountUrl().url.toString(),\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n GetV1WorkoutsEventsQueryResponse,\n GetV1WorkoutsEventsQueryParams,\n GetV1WorkoutsEventsHeaderParams,\n GetV1WorkoutsEvents500,\n} from \"../types/GetV1WorkoutsEvents.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getGetV1WorkoutsEventsUrl() {\n const res = { method: \"GET\", url: `/v1/workouts/events` as const };\n return res;\n}\n\n/**\n * @description Returns a paginated array of workout events, indicating updates or deletions.\n * @summary Retrieve a paged list of workout events (updates or deletes) since a given date. Events are ordered from newest to oldest. The intention is to allow clients to keep their local cache of workouts up to date without having to fetch the entire list of workouts.\n * {@link /v1/workouts/events}\n */\nexport async function getV1WorkoutsEvents(\n headers: GetV1WorkoutsEventsHeaderParams,\n params?: GetV1WorkoutsEventsQueryParams,\n config: Partial<RequestConfig> & { client?: Client } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1WorkoutsEventsQueryResponse,\n ResponseErrorConfig<GetV1WorkoutsEvents500>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1WorkoutsEventsUrl().url.toString(),\n params,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n GetV1WorkoutsWorkoutidQueryResponse,\n GetV1WorkoutsWorkoutidPathParams,\n GetV1WorkoutsWorkoutidHeaderParams,\n GetV1WorkoutsWorkoutid404,\n} from \"../types/GetV1WorkoutsWorkoutid.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getGetV1WorkoutsWorkoutidUrl(\n workoutId: GetV1WorkoutsWorkoutidPathParams[\"workoutId\"],\n) {\n const res = { method: \"GET\", url: `/v1/workouts/${workoutId}` as const };\n return res;\n}\n\n/**\n * @summary Get a single workout’s complete details by the workoutId\n * {@link /v1/workouts/:workoutId}\n */\nexport async function getV1WorkoutsWorkoutid(\n workoutId: GetV1WorkoutsWorkoutidPathParams[\"workoutId\"],\n headers: GetV1WorkoutsWorkoutidHeaderParams,\n config: Partial<RequestConfig> & { client?: Client } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1WorkoutsWorkoutidQueryResponse,\n ResponseErrorConfig<GetV1WorkoutsWorkoutid404>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1WorkoutsWorkoutidUrl(workoutId).url.toString(),\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n PostV1BodyMeasurementsMutationRequest,\n PostV1BodyMeasurementsMutationResponse,\n PostV1BodyMeasurementsHeaderParams,\n PostV1BodyMeasurements400,\n PostV1BodyMeasurements409,\n} from \"../types/PostV1BodyMeasurements.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getPostV1BodyMeasurementsUrl() {\n const res = { method: \"POST\", url: `/v1/body_measurements` as const };\n return res;\n}\n\n/**\n * @summary Create a body measurement entry for a given date. Returns 409 if an entry already exists for that date.\n * {@link /v1/body_measurements}\n */\nexport async function postV1BodyMeasurements(\n data: PostV1BodyMeasurementsMutationRequest,\n headers: PostV1BodyMeasurementsHeaderParams,\n config: Partial<RequestConfig<PostV1BodyMeasurementsMutationRequest>> & {\n client?: Client;\n } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const requestData = data;\n\n const res = await request<\n PostV1BodyMeasurementsMutationResponse,\n ResponseErrorConfig<PostV1BodyMeasurements400 | PostV1BodyMeasurements409>,\n PostV1BodyMeasurementsMutationRequest\n >({\n method: \"POST\",\n url: getPostV1BodyMeasurementsUrl().url.toString(),\n data: requestData,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n PostV1ExerciseTemplatesMutationRequest,\n PostV1ExerciseTemplatesMutationResponse,\n PostV1ExerciseTemplatesHeaderParams,\n PostV1ExerciseTemplates400,\n PostV1ExerciseTemplates403,\n} from \"../types/PostV1ExerciseTemplates.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getPostV1ExerciseTemplatesUrl() {\n const res = { method: \"POST\", url: `/v1/exercise_templates` as const };\n return res;\n}\n\n/**\n * @summary Create a new custom exercise template.\n * {@link /v1/exercise_templates}\n */\nexport async function postV1ExerciseTemplates(\n data: PostV1ExerciseTemplatesMutationRequest,\n headers: PostV1ExerciseTemplatesHeaderParams,\n config: Partial<RequestConfig<PostV1ExerciseTemplatesMutationRequest>> & {\n client?: Client;\n } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const requestData = data;\n\n const res = await request<\n PostV1ExerciseTemplatesMutationResponse,\n ResponseErrorConfig<\n PostV1ExerciseTemplates400 | PostV1ExerciseTemplates403\n >,\n PostV1ExerciseTemplatesMutationRequest\n >({\n method: \"POST\",\n url: getPostV1ExerciseTemplatesUrl().url.toString(),\n data: requestData,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n PostV1RoutineFoldersMutationRequest,\n PostV1RoutineFoldersMutationResponse,\n PostV1RoutineFoldersHeaderParams,\n PostV1RoutineFolders400,\n} from \"../types/PostV1RoutineFolders.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getPostV1RoutineFoldersUrl() {\n const res = { method: \"POST\", url: `/v1/routine_folders` as const };\n return res;\n}\n\n/**\n * @summary Create a new routine folder. The folder will be created at index 0, and all other folders will have their indexes incremented.\n * {@link /v1/routine_folders}\n */\nexport async function postV1RoutineFolders(\n data: PostV1RoutineFoldersMutationRequest,\n headers: PostV1RoutineFoldersHeaderParams,\n config: Partial<RequestConfig<PostV1RoutineFoldersMutationRequest>> & {\n client?: Client;\n } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const requestData = data;\n\n const res = await request<\n PostV1RoutineFoldersMutationResponse,\n ResponseErrorConfig<PostV1RoutineFolders400>,\n PostV1RoutineFoldersMutationRequest\n >({\n method: \"POST\",\n url: getPostV1RoutineFoldersUrl().url.toString(),\n data: requestData,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n PostV1RoutinesMutationRequest,\n PostV1RoutinesMutationResponse,\n PostV1RoutinesHeaderParams,\n PostV1Routines400,\n PostV1Routines403,\n} from \"../types/PostV1Routines.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getPostV1RoutinesUrl() {\n const res = { method: \"POST\", url: `/v1/routines` as const };\n return res;\n}\n\n/**\n * @summary Create a new routine\n * {@link /v1/routines}\n */\nexport async function postV1Routines(\n data: PostV1RoutinesMutationRequest,\n headers: PostV1RoutinesHeaderParams,\n config: Partial<RequestConfig<PostV1RoutinesMutationRequest>> & {\n client?: Client;\n } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const requestData = data;\n\n const res = await request<\n PostV1RoutinesMutationResponse,\n ResponseErrorConfig<PostV1Routines400 | PostV1Routines403>,\n PostV1RoutinesMutationRequest\n >({\n method: \"POST\",\n url: getPostV1RoutinesUrl().url.toString(),\n data: requestData,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n PostV1WorkoutsMutationRequest,\n PostV1WorkoutsMutationResponse,\n PostV1WorkoutsHeaderParams,\n PostV1Workouts400,\n} from \"../types/PostV1Workouts.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getPostV1WorkoutsUrl() {\n const res = { method: \"POST\", url: `/v1/workouts` as const };\n return res;\n}\n\n/**\n * @summary Create a new workout\n * {@link /v1/workouts}\n */\nexport async function postV1Workouts(\n data: PostV1WorkoutsMutationRequest,\n headers: PostV1WorkoutsHeaderParams,\n config: Partial<RequestConfig<PostV1WorkoutsMutationRequest>> & {\n client?: Client;\n } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const requestData = data;\n\n const res = await request<\n PostV1WorkoutsMutationResponse,\n ResponseErrorConfig<PostV1Workouts400>,\n PostV1WorkoutsMutationRequest\n >({\n method: \"POST\",\n url: getPostV1WorkoutsUrl().url.toString(),\n data: requestData,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n PutV1BodyMeasurementsDateMutationRequest,\n PutV1BodyMeasurementsDateMutationResponse,\n PutV1BodyMeasurementsDatePathParams,\n PutV1BodyMeasurementsDateHeaderParams,\n PutV1BodyMeasurementsDate400,\n PutV1BodyMeasurementsDate404,\n} from \"../types/PutV1BodyMeasurementsDate.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getPutV1BodyMeasurementsDateUrl(\n date: PutV1BodyMeasurementsDatePathParams[\"date\"],\n) {\n const res = { method: \"PUT\", url: `/v1/body_measurements/${date}` as const };\n return res;\n}\n\n/**\n * @summary Update an existing body measurement entry for a given date. All fields are overwritten; omitted fields are set to null.\n * {@link /v1/body_measurements/:date}\n */\nexport async function putV1BodyMeasurementsDate(\n date: PutV1BodyMeasurementsDatePathParams[\"date\"],\n data: PutV1BodyMeasurementsDateMutationRequest,\n headers: PutV1BodyMeasurementsDateHeaderParams,\n config: Partial<RequestConfig<PutV1BodyMeasurementsDateMutationRequest>> & {\n client?: Client;\n } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const requestData = data;\n\n const res = await request<\n PutV1BodyMeasurementsDateMutationResponse,\n ResponseErrorConfig<\n PutV1BodyMeasurementsDate400 | PutV1BodyMeasurementsDate404\n >,\n PutV1BodyMeasurementsDateMutationRequest\n >({\n method: \"PUT\",\n url: getPutV1BodyMeasurementsDateUrl(date).url.toString(),\n data: requestData,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n PutV1RoutinesRoutineidMutationRequest,\n PutV1RoutinesRoutineidMutationResponse,\n PutV1RoutinesRoutineidPathParams,\n PutV1RoutinesRoutineidHeaderParams,\n PutV1RoutinesRoutineid400,\n PutV1RoutinesRoutineid404,\n} from \"../types/PutV1RoutinesRoutineid.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getPutV1RoutinesRoutineidUrl(\n routineId: PutV1RoutinesRoutineidPathParams[\"routineId\"],\n) {\n const res = { method: \"PUT\", url: `/v1/routines/${routineId}` as const };\n return res;\n}\n\n/**\n * @summary Update an existing routine\n * {@link /v1/routines/:routineId}\n */\nexport async function putV1RoutinesRoutineid(\n routineId: PutV1RoutinesRoutineidPathParams[\"routineId\"],\n data: PutV1RoutinesRoutineidMutationRequest,\n headers: PutV1RoutinesRoutineidHeaderParams,\n config: Partial<RequestConfig<PutV1RoutinesRoutineidMutationRequest>> & {\n client?: Client;\n } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const requestData = data;\n\n const res = await request<\n PutV1RoutinesRoutineidMutationResponse,\n ResponseErrorConfig<PutV1RoutinesRoutineid400 | PutV1RoutinesRoutineid404>,\n PutV1RoutinesRoutineidMutationRequest\n >({\n method: \"PUT\",\n url: getPutV1RoutinesRoutineidUrl(routineId).url.toString(),\n data: requestData,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n PutV1WorkoutsWorkoutidMutationRequest,\n PutV1WorkoutsWorkoutidMutationResponse,\n PutV1WorkoutsWorkoutidPathParams,\n PutV1WorkoutsWorkoutidHeaderParams,\n PutV1WorkoutsWorkoutid400,\n} from \"../types/PutV1WorkoutsWorkoutid.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getPutV1WorkoutsWorkoutidUrl(\n workoutId: PutV1WorkoutsWorkoutidPathParams[\"workoutId\"],\n) {\n const res = { method: \"PUT\", url: `/v1/workouts/${workoutId}` as const };\n return res;\n}\n\n/**\n * @summary Update an existing workout\n * {@link /v1/workouts/:workoutId}\n */\nexport async function putV1WorkoutsWorkoutid(\n workoutId: PutV1WorkoutsWorkoutidPathParams[\"workoutId\"],\n data: PutV1WorkoutsWorkoutidMutationRequest,\n headers: PutV1WorkoutsWorkoutidHeaderParams,\n config: Partial<RequestConfig<PutV1WorkoutsWorkoutidMutationRequest>> & {\n client?: Client;\n } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const requestData = data;\n\n const res = await request<\n PutV1WorkoutsWorkoutidMutationResponse,\n ResponseErrorConfig<PutV1WorkoutsWorkoutid400>,\n PutV1WorkoutsWorkoutidMutationRequest\n >({\n method: \"PUT\",\n url: getPutV1WorkoutsWorkoutidUrl(workoutId).url.toString(),\n data: requestData,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","import type {\n\tRequestConfig,\n\tResponseConfig,\n} from \"../generated/.kubb/fetch.ts\";\nimport { SpanStatusCode, type Span } from \"@opentelemetry/api\";\nimport axios, {\n\tisAxiosError,\n\ttype AxiosError,\n\ttype AxiosInstance,\n\ttype AxiosRequestConfig,\n\ttype InternalAxiosRequestConfig,\n} from \"axios\";\nimport * as api from \"../generated/client/api\";\nimport { tracer } from \"./telemetry.js\";\nimport { apiCalls, apiDuration } from \"./metrics.js\";\nimport type {\n\tGetV1BodyMeasurementsQueryParams,\n\tGetV1ExerciseHistoryExercisetemplateidQueryParams,\n\tGetV1ExerciseTemplatesQueryParams,\n\tGetV1RoutineFoldersQueryParams,\n\tGetV1RoutinesQueryParams,\n\tGetV1WorkoutsEventsQueryParams,\n\tGetV1WorkoutsQueryParams,\n\tPostV1BodyMeasurementsMutationRequest,\n\tPostV1ExerciseTemplatesMutationRequest,\n\tPostV1RoutineFoldersMutationRequest,\n\tPostV1RoutinesMutationRequest,\n\tPostV1WorkoutsMutationRequest,\n\tPutV1BodyMeasurementsDateMutationRequest,\n\tPutV1RoutinesRoutineidMutationRequest,\n\tPutV1WorkoutsWorkoutidMutationRequest,\n} from \"../generated/client/types\";\n\n// Define a proper client type that matches the Kubb client interface\ntype KubbClient = {\n\t<TData, _TError = unknown, TVariables = unknown>(\n\t\tconfig: RequestConfig<TVariables>,\n\t): Promise<ResponseConfig<TData>>;\n\tgetConfig: () => Partial<RequestConfig<unknown>>;\n\tsetConfig: (config: RequestConfig) => Partial<RequestConfig<unknown>>;\n};\n\n/**\n * Type-safe wrapper helper that enforces parameter types match the generated API.\n * This prevents arg-order regressions by using Parameters<> to extract expected types.\n *\n * Usage: wrapApi(api.postV1ExerciseTemplates)(data, headers, { client })\n * TypeScript will error if arguments don't match the generated signature.\n */\nfunction wrapApi<T extends (...args: Parameters<T>) => ReturnType<T>>(\n\tfn: T,\n): (...args: Parameters<T>) => ReturnType<T> {\n\treturn fn;\n}\n\nexport const DEFAULT_API_TIMEOUT_MS = 30_000;\nexport const MAX_GET_RETRIES = 3;\nexport const RETRY_BACKOFF_BASE_MS = 300;\nconst RETRY_BACKOFF_MAX_MS = 5_000;\n\nexport const HEVY_RETRY_EXHAUSTED_ERROR_CODE = \"HEVY_RETRY_EXHAUSTED\";\n\nconst RETRYABLE_STATUS_CODES = new Set([408, 429, 500, 502, 503, 504]);\n\nconst RETRYABLE_NETWORK_ERROR_CODES = new Set([\n\t\"ECONNABORTED\",\n\t\"ECONNREFUSED\",\n\t\"ECONNRESET\",\n\t\"EAI_AGAIN\",\n\t\"ENETUNREACH\",\n\t\"ENOTFOUND\",\n\t\"ERR_NETWORK\",\n\t\"ERR_SOCKET_TIMEOUT\",\n\t\"ETIMEDOUT\",\n]);\n\ntype RetryAwareAxiosError = AxiosError & {\n\thevyRetryCount?: number;\n\thevyRetryExhausted?: boolean;\n\thevyRetryStatus?: number;\n\thevyRetryOriginalCode?: string;\n};\n\nfunction getApiTimeoutMs(): number {\n\tconst rawValue = process.env.HEVY_MCP_API_TIMEOUT;\n\tif (!rawValue) {\n\t\treturn DEFAULT_API_TIMEOUT_MS;\n\t}\n\n\tconst parsed = Number(rawValue);\n\tif (!Number.isFinite(parsed) || parsed <= 0) {\n\t\treturn DEFAULT_API_TIMEOUT_MS;\n\t}\n\n\treturn Math.trunc(parsed);\n}\n\nfunction sleep(ms: number): Promise<void> {\n\treturn new Promise((resolve) => {\n\t\tsetTimeout(resolve, ms);\n\t});\n}\n\nfunction isGetRequest(config: RequestConfig<unknown>): boolean {\n\treturn config.method?.toUpperCase() === \"GET\";\n}\n\nfunction isRetryableStatus(status: number | undefined): boolean {\n\tif (status === undefined) {\n\t\treturn false;\n\t}\n\n\treturn RETRYABLE_STATUS_CODES.has(status);\n}\n\nfunction isTransientNetworkError(error: AxiosError): boolean {\n\tif (error.code === \"ERR_CANCELED\") {\n\t\treturn false;\n\t}\n\n\tif (error.code && RETRYABLE_NETWORK_ERROR_CODES.has(error.code)) {\n\t\treturn true;\n\t}\n\n\tif (error.response) {\n\t\treturn false;\n\t}\n\n\tconst message = error.message.toLowerCase();\n\treturn (\n\t\tmessage.includes(\"network\") ||\n\t\tmessage.includes(\"socket hang up\") ||\n\t\tmessage.includes(\"timeout\")\n\t);\n}\n\nfunction normalizeHeaderValue(value: unknown): string | undefined {\n\tif (typeof value === \"string\") {\n\t\tconst trimmed = value.trim();\n\t\treturn trimmed.length > 0 ? trimmed : undefined;\n\t}\n\n\tif (typeof value === \"number\" && Number.isFinite(value)) {\n\t\treturn String(value);\n\t}\n\n\tif (Array.isArray(value) && value.length > 0) {\n\t\treturn normalizeHeaderValue(value[0]);\n\t}\n\n\treturn undefined;\n}\n\nfunction getHeaderValue(headers: unknown, key: string): string | undefined {\n\tif (!headers || typeof headers !== \"object\") {\n\t\treturn undefined;\n\t}\n\n\tif (\n\t\t\"get\" in headers &&\n\t\ttypeof (headers as { get?: unknown }).get === \"function\"\n\t) {\n\t\tconst value = (\n\t\t\theaders as {\n\t\t\t\tget: (headerName: string) => unknown;\n\t\t\t}\n\t\t).get(key);\n\t\treturn normalizeHeaderValue(value);\n\t}\n\n\tconst headerRecord = headers as Record<string, unknown>;\n\treturn normalizeHeaderValue(\n\t\theaderRecord[key] ??\n\t\t\theaderRecord[key.toLowerCase()] ??\n\t\t\theaderRecord[key.toUpperCase()],\n\t);\n}\n\nfunction parseRetryAfterMs(value: string): number | undefined {\n\tconst numericSeconds = Number(value);\n\tif (Number.isFinite(numericSeconds) && numericSeconds >= 0) {\n\t\treturn Math.min(RETRY_BACKOFF_MAX_MS, Math.round(numericSeconds * 1000));\n\t}\n\n\tconst dateMillis = Date.parse(value);\n\tif (Number.isNaN(dateMillis)) {\n\t\treturn undefined;\n\t}\n\n\treturn Math.min(RETRY_BACKOFF_MAX_MS, Math.max(0, dateMillis - Date.now()));\n}\n\nfunction getRetryAfterDelayMs(error: AxiosError): number | undefined {\n\tif (error.response?.status !== 429) {\n\t\treturn undefined;\n\t}\n\n\tconst retryAfterHeader = getHeaderValue(\n\t\terror.response.headers,\n\t\t\"retry-after\",\n\t);\n\tif (!retryAfterHeader) {\n\t\treturn undefined;\n\t}\n\n\treturn parseRetryAfterMs(retryAfterHeader);\n}\n\nfunction getExponentialBackoffMs(retryAttempt: number): number {\n\tconst exponent = Math.max(0, retryAttempt - 1);\n\tconst delay = RETRY_BACKOFF_BASE_MS * 2 ** exponent;\n\treturn Math.min(RETRY_BACKOFF_MAX_MS, delay);\n}\n\nfunction getRetryDelayMs(error: AxiosError, retryAttempt: number): number {\n\tconst exponentialDelay = getExponentialBackoffMs(retryAttempt);\n\tconst retryAfterDelay = getRetryAfterDelayMs(error);\n\n\tif (retryAfterDelay === undefined) {\n\t\treturn exponentialDelay;\n\t}\n\n\treturn Math.min(\n\t\tRETRY_BACKOFF_MAX_MS,\n\t\tMath.max(exponentialDelay, retryAfterDelay),\n\t);\n}\n\nfunction shouldRetryRequest(\n\tconfig: RequestConfig<unknown>,\n\terror: AxiosError,\n): boolean {\n\tif (!isGetRequest(config)) {\n\t\treturn false;\n\t}\n\n\treturn (\n\t\tisRetryableStatus(error.response?.status) || isTransientNetworkError(error)\n\t);\n}\n\nfunction markRetryExhausted(error: AxiosError, retryCount: number): void {\n\tconst retryError = error as RetryAwareAxiosError;\n\tretryError.hevyRetryExhausted = true;\n\tretryError.hevyRetryCount = retryCount;\n\tretryError.hevyRetryStatus = error.response?.status;\n\n\tif (retryError.code) {\n\t\tretryError.hevyRetryOriginalCode = retryError.code;\n\t}\n\n\tretryError.code = HEVY_RETRY_EXHAUSTED_ERROR_CODE;\n}\n\nasync function requestWithRetries<TData, TVariables>(\n\taxiosInstance: AxiosInstance,\n\tconfig: RequestConfig<TVariables>,\n): Promise<ResponseConfig<TData>> {\n\tlet retryCount = 0;\n\n\twhile (true) {\n\t\ttry {\n\t\t\treturn await axiosInstance.request<\n\t\t\t\tTData,\n\t\t\t\tResponseConfig<TData>,\n\t\t\t\tTVariables\n\t\t\t>(config as AxiosRequestConfig<TVariables>);\n\t\t} catch (error) {\n\t\t\tif (!isAxiosError(error)) {\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tconst normalizedConfig = config as RequestConfig<unknown>;\n\t\t\tif (!shouldRetryRequest(normalizedConfig, error)) {\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tif (retryCount >= MAX_GET_RETRIES) {\n\t\t\t\tmarkRetryExhausted(error, retryCount);\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tretryCount += 1;\n\t\t\tconst retryDelayMs = getRetryDelayMs(error, retryCount);\n\t\t\tawait sleep(retryDelayMs);\n\t\t}\n\t}\n}\n\nfunction createResilientClient(axiosInstance: AxiosInstance): KubbClient {\n\tlet clientConfig: Partial<RequestConfig<unknown>> = {\n\t\tbaseURL: axiosInstance.defaults.baseURL,\n\t};\n\n\tconst resilientClient = (async <\n\t\tTData,\n\t\t_TError = unknown,\n\t\tTVariables = unknown,\n\t>(\n\t\tconfig: RequestConfig<TVariables>,\n\t): Promise<ResponseConfig<TData>> => {\n\t\treturn requestWithRetries<TData, TVariables>(axiosInstance, config);\n\t}) as KubbClient;\n\n\tresilientClient.getConfig = () => ({\n\t\t...clientConfig,\n\t});\n\n\tresilientClient.setConfig = (config: RequestConfig) => {\n\t\tclientConfig = {\n\t\t\t...clientConfig,\n\t\t\t...config,\n\t\t};\n\n\t\tif (config.baseURL !== undefined) {\n\t\t\taxiosInstance.defaults.baseURL = config.baseURL;\n\t\t}\n\n\t\treturn resilientClient.getConfig();\n\t};\n\n\treturn resilientClient;\n}\n\n// --- Interceptor helpers ---\n\ntype TracedConfig = InternalAxiosRequestConfig & {\n\t_span?: Span;\n\t_startTime?: number;\n};\n\n/**\n * Extract common request metadata from an Axios config.\n * Shared between the success and error response interceptors to avoid\n * duplicating the method/url/endpoint/duration extraction logic.\n */\nfunction extractRequestMeta(config: {\n\tmethod?: string;\n\turl?: string;\n\t_startTime?: number;\n}) {\n\tconst method = (config.method ?? \"get\").toUpperCase();\n\tconst url = config.url ?? \"\";\n\tconst endpoint = url.split(\"?\")[0] ?? url;\n\tconst now = Date.now();\n\tconst durationMs = now - (config._startTime ?? now);\n\treturn { method, url, endpoint, durationMs };\n}\n\n/**\n * Finalize a traced span and record metrics for a completed HTTP request.\n */\nfunction finalizeRequestTrace(opts: {\n\tspan: Span | undefined;\n\tstatusCode: number;\n\tdurationMs: number;\n\tmethod: string;\n\tendpoint: string;\n\terror?: unknown;\n}) {\n\tconst { span, statusCode, durationMs, method, endpoint, error } = opts;\n\n\tif (span) {\n\t\tspan.setAttribute(\"http.status_code\", statusCode);\n\t\tspan.setAttribute(\"http.response.duration_ms\", durationMs);\n\t\tif (error) {\n\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\tspan.recordException(error as Error);\n\t\t} else {\n\t\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\t}\n\t\tspan.end();\n\t}\n\n\tapiCalls.add(1, { method, endpoint, status_code: statusCode });\n\tapiDuration.record(durationMs, { method, endpoint });\n}\n\nexport function createClient(\n\tapiKey: string,\n\tbaseUrl = \"https://api.hevyapp.com\",\n) {\n\t// Create an axios instance with the API key\n\tconst axiosInstance = axios.create({\n\t\tbaseURL: baseUrl,\n\t\ttimeout: getApiTimeoutMs(),\n\t\theaders: {\n\t\t\t\"api-key\": apiKey,\n\t\t},\n\t});\n\n\t// --- Axios interceptors for HTTP tracing and metrics ---\n\taxiosInstance.interceptors.request.use((config) => {\n\t\tconst tracedConfig = config as TracedConfig;\n\t\tconst method = (config.method ?? \"get\").toUpperCase();\n\t\tconst url = config.url ?? \"\";\n\t\t// Extract clean endpoint path without query params for high-cardinality safety\n\t\tconst endpoint = url.split(\"?\")[0] ?? url;\n\t\ttracedConfig._span = tracer.startSpan(`hevy.api.${method}`, {\n\t\t\tattributes: {\n\t\t\t\t\"http.method\": method,\n\t\t\t\t\"http.url\": url,\n\t\t\t\t\"http.base_url\": config.baseURL ?? \"\",\n\t\t\t\t\"hevy.api.endpoint\": endpoint,\n\t\t\t},\n\t\t});\n\t\ttracedConfig._startTime = Date.now();\n\t\treturn config;\n\t});\n\n\taxiosInstance.interceptors.response.use(\n\t\t(response) => {\n\t\t\tconst tracedConfig = response.config as TracedConfig;\n\t\t\tconst { method, endpoint, durationMs } = extractRequestMeta({\n\t\t\t\tmethod: response.config.method,\n\t\t\t\turl: response.config.url,\n\t\t\t\t_startTime: tracedConfig._startTime,\n\t\t\t});\n\n\t\t\tfinalizeRequestTrace({\n\t\t\t\tspan: tracedConfig._span,\n\t\t\t\tstatusCode: response.status,\n\t\t\t\tdurationMs,\n\t\t\t\tmethod,\n\t\t\t\tendpoint,\n\t\t\t});\n\n\t\t\treturn response;\n\t\t},\n\t\t(error) => {\n\t\t\tconst tracedConfig = (error.config ?? {}) as TracedConfig;\n\t\t\tconst { method, endpoint, durationMs } = extractRequestMeta({\n\t\t\t\tmethod: error.config?.method,\n\t\t\t\turl: error.config?.url,\n\t\t\t\t_startTime: tracedConfig._startTime,\n\t\t\t});\n\n\t\t\tfinalizeRequestTrace({\n\t\t\t\tspan: tracedConfig._span,\n\t\t\t\tstatusCode: error.response?.status ?? 0,\n\t\t\t\tdurationMs,\n\t\t\t\tmethod,\n\t\t\t\tendpoint,\n\t\t\t\terror,\n\t\t\t});\n\n\t\t\tthrow error;\n\t\t},\n\t);\n\n\t// Create headers object with API key\n\tconst headers = {\n\t\t\"api-key\": apiKey,\n\t};\n\n\tconst client = createResilientClient(axiosInstance);\n\n\t// Return an object with all the API methods using ReturnType for automatic type inference\n\t// All API calls use wrapApi to ensure TypeScript validates arg order matches generated API\n\treturn {\n\t\t// Workouts\n\t\tgetWorkouts: (\n\t\t\tparams?: GetV1WorkoutsQueryParams,\n\t\t): ReturnType<typeof api.getV1Workouts> =>\n\t\t\twrapApi(api.getV1Workouts)(headers, params, { client }),\n\t\tgetWorkout: (\n\t\t\tworkoutId: string,\n\t\t): ReturnType<typeof api.getV1WorkoutsWorkoutid> =>\n\t\t\twrapApi(api.getV1WorkoutsWorkoutid)(workoutId, headers, { client }),\n\t\tcreateWorkout: (\n\t\t\tdata: PostV1WorkoutsMutationRequest,\n\t\t): ReturnType<typeof api.postV1Workouts> =>\n\t\t\twrapApi(api.postV1Workouts)(data, headers, { client }),\n\t\tupdateWorkout: (\n\t\t\tworkoutId: string,\n\t\t\tdata: PutV1WorkoutsWorkoutidMutationRequest,\n\t\t): ReturnType<typeof api.putV1WorkoutsWorkoutid> =>\n\t\t\twrapApi(api.putV1WorkoutsWorkoutid)(workoutId, data, headers, {\n\t\t\t\tclient,\n\t\t\t}),\n\t\tgetWorkoutCount: (): ReturnType<typeof api.getV1WorkoutsCount> =>\n\t\t\twrapApi(api.getV1WorkoutsCount)(headers, { client }),\n\t\tgetWorkoutEvents: (\n\t\t\tparams?: GetV1WorkoutsEventsQueryParams,\n\t\t): ReturnType<typeof api.getV1WorkoutsEvents> =>\n\t\t\twrapApi(api.getV1WorkoutsEvents)(headers, params, { client }),\n\n\t\t// Routines\n\t\tgetRoutines: (\n\t\t\tparams?: GetV1RoutinesQueryParams,\n\t\t): ReturnType<typeof api.getV1Routines> =>\n\t\t\twrapApi(api.getV1Routines)(headers, params, { client }),\n\t\tgetRoutineById: (\n\t\t\troutineId: string,\n\t\t): ReturnType<typeof api.getV1RoutinesRoutineid> =>\n\t\t\twrapApi(api.getV1RoutinesRoutineid)(routineId, headers, { client }),\n\t\tcreateRoutine: (\n\t\t\tdata: PostV1RoutinesMutationRequest,\n\t\t): ReturnType<typeof api.postV1Routines> =>\n\t\t\twrapApi(api.postV1Routines)(data, headers, { client }),\n\t\tupdateRoutine: (\n\t\t\troutineId: string,\n\t\t\tdata: PutV1RoutinesRoutineidMutationRequest,\n\t\t): ReturnType<typeof api.putV1RoutinesRoutineid> =>\n\t\t\twrapApi(api.putV1RoutinesRoutineid)(routineId, data, headers, {\n\t\t\t\tclient,\n\t\t\t}),\n\n\t\t// Exercise Templates\n\t\tgetExerciseTemplates: (\n\t\t\tparams?: GetV1ExerciseTemplatesQueryParams,\n\t\t): ReturnType<typeof api.getV1ExerciseTemplates> =>\n\t\t\twrapApi(api.getV1ExerciseTemplates)(headers, params, { client }),\n\t\tgetExerciseTemplate: (\n\t\t\ttemplateId: string,\n\t\t): ReturnType<typeof api.getV1ExerciseTemplatesExercisetemplateid> =>\n\t\t\twrapApi(api.getV1ExerciseTemplatesExercisetemplateid)(\n\t\t\t\ttemplateId,\n\t\t\t\theaders,\n\t\t\t\t{\n\t\t\t\t\tclient,\n\t\t\t\t},\n\t\t\t),\n\t\tgetExerciseHistory: (\n\t\t\texerciseTemplateId: string,\n\t\t\tparams?: GetV1ExerciseHistoryExercisetemplateidQueryParams,\n\t\t): ReturnType<typeof api.getV1ExerciseHistoryExercisetemplateid> =>\n\t\t\twrapApi(api.getV1ExerciseHistoryExercisetemplateid)(\n\t\t\t\texerciseTemplateId,\n\t\t\t\theaders,\n\t\t\t\tparams,\n\t\t\t\t{ client },\n\t\t\t),\n\t\tcreateExerciseTemplate: (\n\t\t\tdata: PostV1ExerciseTemplatesMutationRequest,\n\t\t): ReturnType<typeof api.postV1ExerciseTemplates> =>\n\t\t\twrapApi(api.postV1ExerciseTemplates)(data, headers, { client }),\n\n\t\t// Routine Folders\n\t\tgetRoutineFolders: (\n\t\t\tparams?: GetV1RoutineFoldersQueryParams,\n\t\t): ReturnType<typeof api.getV1RoutineFolders> =>\n\t\t\twrapApi(api.getV1RoutineFolders)(headers, params, { client }),\n\t\tcreateRoutineFolder: (\n\t\t\tdata: PostV1RoutineFoldersMutationRequest,\n\t\t): ReturnType<typeof api.postV1RoutineFolders> =>\n\t\t\twrapApi(api.postV1RoutineFolders)(data, headers, { client }),\n\t\tgetRoutineFolder: (\n\t\t\tfolderId: string,\n\t\t): ReturnType<typeof api.getV1RoutineFoldersFolderid> =>\n\t\t\twrapApi(api.getV1RoutineFoldersFolderid)(folderId, headers, {\n\t\t\t\tclient,\n\t\t\t}),\n\n\t\t// Body Measurements\n\t\tgetBodyMeasurements: (\n\t\t\tparams?: GetV1BodyMeasurementsQueryParams,\n\t\t): ReturnType<typeof api.getV1BodyMeasurements> =>\n\t\t\twrapApi(api.getV1BodyMeasurements)(headers, params, { client }),\n\t\tgetBodyMeasurement: (\n\t\t\tdate: string,\n\t\t): ReturnType<typeof api.getV1BodyMeasurementsDate> =>\n\t\t\twrapApi(api.getV1BodyMeasurementsDate)(date, headers, { client }),\n\t\tcreateBodyMeasurement: (\n\t\t\tdata: PostV1BodyMeasurementsMutationRequest,\n\t\t): ReturnType<typeof api.postV1BodyMeasurements> =>\n\t\t\twrapApi(api.postV1BodyMeasurements)(data, headers, { client }),\n\t\tupdateBodyMeasurement: (\n\t\t\tdate: string,\n\t\t\tdata: PutV1BodyMeasurementsDateMutationRequest,\n\t\t): ReturnType<typeof api.putV1BodyMeasurementsDate> =>\n\t\t\twrapApi(api.putV1BodyMeasurementsDate)(date, data, headers, {\n\t\t\t\tclient,\n\t\t\t}),\n\n\t\t// User\n\t\tgetUserInfo: (): ReturnType<typeof api.getV1UserInfo> =>\n\t\t\twrapApi(api.getV1UserInfo)(headers, { client }),\n\t};\n}\n\n/**\n * Type representing the Hevy API client returned by createClient.\n * Useful for typing variables that hold the client instance.\n */\nexport type HevyApiClient = ReturnType<typeof createClient>;\n","// Import the Kubb-based client\nimport { createClient as createKubbClient } from \"./hevyClientKubb.js\";\n\nexport function createClient(apiKey: string, baseUrl: string) {\n\treturn createKubbClient(apiKey, baseUrl);\n}\n\n// Export the HevyClient type for use in other modules\nexport type HevyClient = ReturnType<typeof createClient>;\n","import { SpanStatusCode } from \"@opentelemetry/api\";\nimport type { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { deserializeMessage } from \"@modelcontextprotocol/sdk/shared/stdio.js\";\nimport type { JSONRPCMessage } from \"@modelcontextprotocol/sdk/types.js\";\nimport { Sentry, tracer } from \"./telemetry.js\";\nimport { stdioParseErrors } from \"./metrics.js\";\n\nconst UTF8_BOM = \"\\uFEFF\";\n\nexport interface StdioChunkSnapshot {\n\tlastChunkByteLength: number;\n\tlastChunkStartsWithUtf8Bom: boolean;\n}\n\ninterface MutableReadBuffer {\n\t_buffer?: Buffer;\n\treadMessage: () => JSONRPCMessage | null;\n}\n\ntype MutableStdioServerTransport = {\n\t_readBuffer?: MutableReadBuffer;\n\t_ondata?: (chunk: Buffer) => void;\n};\n\ninterface SdkPrivateStdioAdapter {\n\twrapOnData: (onChunk: (chunk: Buffer) => void) => void;\n\tinstallReadMessageHook: (\n\t\tonReadLine: (line: string) => JSONRPCMessage,\n\t) => boolean;\n}\n\n/**\n * Adapter boundary around MCP SDK stdio internals.\n *\n * MCP SDK v1.29.0 exposes public message-level hooks but does not expose a\n * public raw-chunk hook on `StdioServerTransport`. To capture chunk metadata,\n * we currently rely on private internals (`_ondata`, `_readBuffer`, `_buffer`)\n * in this one place.\n *\n * If those internals change in a future SDK release, this adapter should fail\n * closed and preserve default transport behavior (no instrumentation patching).\n */\nfunction createSdkPrivateStdioAdapter(\n\ttransport: StdioServerTransport,\n): SdkPrivateStdioAdapter {\n\tconst mutableTransport = transport as unknown as MutableStdioServerTransport;\n\n\treturn {\n\t\twrapOnData(onChunk) {\n\t\t\tconst originalOnData = mutableTransport._ondata;\n\t\t\tif (typeof originalOnData !== \"function\") {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tmutableTransport._ondata = (chunk: Buffer) => {\n\t\t\t\tonChunk(chunk);\n\t\t\t\toriginalOnData(chunk);\n\t\t\t};\n\t\t},\n\t\tinstallReadMessageHook(onReadLine) {\n\t\t\tconst readBuffer = mutableTransport._readBuffer;\n\t\t\tif (!readBuffer || typeof readBuffer.readMessage !== \"function\") {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\treadBuffer.readMessage = () => {\n\t\t\t\tconst buffer = readBuffer._buffer;\n\t\t\t\tif (!buffer) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tconst index = buffer.indexOf(\"\\n\");\n\t\t\t\tif (index === -1) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tconst lineBuffer = buffer.subarray(0, index);\n\t\t\t\treadBuffer._buffer = buffer.subarray(index + 1);\n\t\t\t\tconst line = lineBuffer.toString(\"utf8\").replace(/\\r$/, \"\");\n\t\t\t\treturn onReadLine(line);\n\t\t\t};\n\n\t\t\treturn true;\n\t\t},\n\t};\n}\n\nfunction hasUtf8BomPrefix(chunk: Buffer): boolean {\n\treturn (\n\t\tchunk.length >= 3 &&\n\t\tchunk[0] === 0xef &&\n\t\tchunk[1] === 0xbb &&\n\t\tchunk[2] === 0xbf\n\t);\n}\n\nfunction parseFailurePosition(error: unknown): number | null {\n\tif (!(error instanceof Error)) {\n\t\treturn null;\n\t}\n\n\tconst match = error.message.match(/position\\s+(\\d+)/i);\n\tif (!match || !match[1]) {\n\t\treturn null;\n\t}\n\n\tconst position = Number.parseInt(match[1], 10);\n\treturn Number.isFinite(position) ? position : null;\n}\n\nfunction getFailureLocation(\n\tfailurePosition: number | null,\n\tlineHadLeadingBom: boolean,\n): string {\n\tif (lineHadLeadingBom) {\n\t\treturn \"line_start_bom\";\n\t}\n\tif (failurePosition === 0) {\n\t\treturn \"line_start\";\n\t}\n\tif (failurePosition !== null) {\n\t\treturn \"line_body\";\n\t}\n\treturn \"unknown\";\n}\n\nexport function deserializeMessageWithObservability(\n\tline: string,\n\tchunkSnapshot: StdioChunkSnapshot,\n): JSONRPCMessage {\n\tconst lineHadLeadingBom = line.startsWith(UTF8_BOM);\n\tconst normalizedLine = lineHadLeadingBom ? line.slice(1) : line;\n\tconst lineByteLength = Buffer.byteLength(line);\n\n\treturn tracer.startActiveSpan(\n\t\t\"mcp.stdio.deserialize\",\n\t\t{\n\t\t\tattributes: {\n\t\t\t\t\"mcp.transport\": \"stdio\",\n\t\t\t\t\"mcp.stdio.parse.line.char_length\": line.length,\n\t\t\t\t\"mcp.stdio.parse.line.byte_length\": lineByteLength,\n\t\t\t\t\"mcp.stdio.parse.line.had_leading_bom\": lineHadLeadingBom,\n\t\t\t\t\"mcp.stdio.parse.line.bom_stripped\": lineHadLeadingBom,\n\t\t\t\t\"mcp.stdio.parse.chunk.last_byte_length\":\n\t\t\t\t\tchunkSnapshot.lastChunkByteLength,\n\t\t\t\t\"mcp.stdio.parse.chunk.last_had_utf8_bom\":\n\t\t\t\t\tchunkSnapshot.lastChunkStartsWithUtf8Bom,\n\t\t\t},\n\t\t},\n\t\t(span) => {\n\t\t\ttry {\n\t\t\t\tconst message = deserializeMessage(normalizedLine);\n\t\t\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\t\t\tif (message && typeof message === \"object\" && \"method\" in message) {\n\t\t\t\t\tspan.setAttribute(\n\t\t\t\t\t\t\"mcp.method\",\n\t\t\t\t\t\tString((message as { method: unknown }).method),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn message;\n\t\t\t} catch (error) {\n\t\t\t\tconst failurePosition = parseFailurePosition(error);\n\t\t\t\tconst failureLocation = getFailureLocation(\n\t\t\t\t\tfailurePosition,\n\t\t\t\t\tlineHadLeadingBom,\n\t\t\t\t);\n\n\t\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\t\tspan.recordException(error as Error);\n\t\t\t\tspan.setAttribute(\"mcp.stdio.parse.failure.location\", failureLocation);\n\t\t\t\tif (failurePosition !== null) {\n\t\t\t\t\tspan.setAttribute(\n\t\t\t\t\t\t\"mcp.stdio.parse.failure.position\",\n\t\t\t\t\t\tfailurePosition,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tstdioParseErrors.add(1, { failure_location: failureLocation });\n\n\t\t\t\tSentry.withScope((scope) => {\n\t\t\t\t\tscope.setTag(\"mcp.transport\", \"stdio\");\n\t\t\t\t\tscope.setTag(\"mcp.stdio.parse.failure.location\", failureLocation);\n\t\t\t\t\tscope.setContext(\"mcpStdioParse\", {\n\t\t\t\t\t\tlineCharLength: line.length,\n\t\t\t\t\t\tlineByteLength,\n\t\t\t\t\t\tlineHadLeadingBom,\n\t\t\t\t\t\tbomStripped: lineHadLeadingBom,\n\t\t\t\t\t\tlastChunkByteLength: chunkSnapshot.lastChunkByteLength,\n\t\t\t\t\t\tlastChunkStartsWithUtf8Bom:\n\t\t\t\t\t\t\tchunkSnapshot.lastChunkStartsWithUtf8Bom,\n\t\t\t\t\t\tfailureLocation,\n\t\t\t\t\t\tfailurePosition,\n\t\t\t\t\t\tfailureStage: \"deserializeMessage\",\n\t\t\t\t\t\terrorName: error instanceof Error ? error.name : \"UnknownError\",\n\t\t\t\t\t});\n\t\t\t\t\tSentry.captureException(error);\n\t\t\t\t});\n\n\t\t\t\tthrow error;\n\t\t\t} finally {\n\t\t\t\tspan.end();\n\t\t\t}\n\t\t},\n\t);\n}\n\nexport function createInstrumentedStdioTransport<\n\tT extends StdioServerTransport,\n>(transport: T): T {\n\tconst privateAdapter = createSdkPrivateStdioAdapter(transport);\n\tlet lastChunkSnapshot: StdioChunkSnapshot = {\n\t\tlastChunkByteLength: 0,\n\t\tlastChunkStartsWithUtf8Bom: false,\n\t};\n\n\tprivateAdapter.wrapOnData((chunk) => {\n\t\tlastChunkSnapshot = {\n\t\t\tlastChunkByteLength: chunk.byteLength,\n\t\t\tlastChunkStartsWithUtf8Bom: hasUtf8BomPrefix(chunk),\n\t\t};\n\t});\n\n\tconst didInstallReadMessageHook = privateAdapter.installReadMessageHook(\n\t\t(line) => deserializeMessageWithObservability(line, lastChunkSnapshot),\n\t);\n\tif (!didInstallReadMessageHook) {\n\t\treturn transport;\n\t}\n\n\treturn transport;\n}\n","// Telemetry must be initialized before any other imports so that\n// OpenTelemetry and Sentry are ready before application code runs.\nimport {\n\tSentry,\n\ttracer,\n\tserviceName,\n\tserviceVersion,\n\tsetCurrentUserId,\n} from \"./utils/telemetry.js\";\nimport { serverStartups } from \"./utils/metrics.js\";\n\nimport { SpanStatusCode } from \"@opentelemetry/api\";\nimport { createHmac } from \"node:crypto\";\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { z } from \"zod\";\nimport { registerBodyMeasurementTools } from \"./tools/body-measurements.js\";\nimport { registerFolderTools } from \"./tools/folders.js\";\nimport { registerRoutineTools } from \"./tools/routines.js\";\nimport { registerTemplateTools } from \"./tools/templates.js\";\nimport { registerUserTools } from \"./tools/user.js\";\nimport { registerWorkoutTools } from \"./tools/workouts.js\";\nimport { assertApiKey, parseConfig } from \"./utils/config.js\";\nimport { createClient } from \"./utils/hevyClient.js\";\nimport { createInstrumentedStdioTransport } from \"./utils/stdio-observability.js\";\n\nconst name = serviceName;\nconst version = serviceVersion;\n\nconst HELP_TEXT = [\n\t\"Usage:\",\n\t\" hevy-mcp [options]\",\n\t\"\",\n\t\"Options:\",\n\t\" -h, --help Show this help message and exit\",\n\t\" -v, --version Show version and exit\",\n\t\" --hevy-api-key=<api-key> (deprecated, use HEVY_API_KEY env var)\",\n\t\"\",\n\t\"Environment:\",\n\t\" HEVY_API_KEY=<api-key> Hevy API key from Hevy app settings\",\n\t\"\",\n\t\"Examples:\",\n\t\" HEVY_API_KEY=your-key npx hevy-mcp\",\n\t\" npx hevy-mcp --hevy-api-key=your-key\",\n\t\" npm start -- --hevy-api-key=your-key\",\n].join(\"\\n\");\n\nfunction getCliAction(args: string[]): \"start\" | \"version\" | \"help\" {\n\tfor (const arg of args) {\n\t\tif (arg === \"--version\" || arg === \"-v\") {\n\t\t\treturn \"version\";\n\t\t}\n\n\t\tif (arg === \"--help\" || arg === \"-h\") {\n\t\t\treturn \"help\";\n\t\t}\n\t}\n\n\treturn \"start\";\n}\n\nconst HEVY_API_BASEURL = \"https://api.hevyapp.com\";\n\nconst SENTRY_USER_ID_CONTEXT = \"hevy-mcp:sentry-user-id:v1\";\n\nfunction fingerprintApiKey(apiKey: string) {\n\t// HMAC-SHA-256 gives Sentry a deterministic pseudonymous user ID without\n\t// sending, logging, or storing the raw Hevy API key.\n\treturn createHmac(\"sha256\", apiKey)\n\t\t.update(SENTRY_USER_ID_CONTEXT)\n\t\t.digest(\"hex\");\n}\n\nconst serverConfigSchema = z.object({\n\tapiKey: z\n\t\t.string()\n\t\t.min(1, \"Hevy API key is required\")\n\t\t.describe(\"Your Hevy API key (available in the Hevy app settings).\"),\n});\n\nexport const configSchema = serverConfigSchema;\ntype ServerConfig = z.infer<typeof serverConfigSchema>;\n\nfunction buildServer(apiKey: string) {\n\tconst userId = fingerprintApiKey(apiKey);\n\n\treturn tracer.startActiveSpan(\n\t\t\"mcp.server.build\",\n\t\t{\n\t\t\tattributes: {\n\t\t\t\t\"mcp.server.name\": name,\n\t\t\t\t\"mcp.server.version\": version,\n\t\t\t\t\"mcp.transport\": \"stdio\",\n\t\t\t\t\"user.id\": userId,\n\t\t\t},\n\t\t},\n\t\t(span) => {\n\t\t\ttry {\n\t\t\t\tSentry.setUser({ id: userId });\n\t\t\t\tsetCurrentUserId(userId);\n\n\t\t\t\tconst baseServer = new McpServer({\n\t\t\t\t\tname,\n\t\t\t\t\tversion,\n\t\t\t\t});\n\t\t\t\tconst server = Sentry.wrapMcpServerWithSentry(baseServer);\n\n\t\t\t\tconst hevyClient = tracer.startActiveSpan(\n\t\t\t\t\t\"mcp.hevy-client.initialize\",\n\t\t\t\t\t(childSpan) => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\treturn createClient(apiKey, HEVY_API_BASEURL);\n\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\tchildSpan.end();\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tconsole.error(\"Hevy client initialized with API key\");\n\n\t\t\t\ttracer.startActiveSpan(\n\t\t\t\t\t\"mcp.tools.register\",\n\t\t\t\t\t{\n\t\t\t\t\t\tattributes: {\n\t\t\t\t\t\t\t\"mcp.tools.count\": 6,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t(toolsSpan) => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tregisterWorkoutTools(server, hevyClient);\n\t\t\t\t\t\t\tregisterRoutineTools(server, hevyClient);\n\t\t\t\t\t\t\tregisterTemplateTools(server, hevyClient);\n\t\t\t\t\t\t\tregisterFolderTools(server, hevyClient);\n\t\t\t\t\t\t\tregisterBodyMeasurementTools(server, hevyClient);\n\t\t\t\t\t\t\tregisterUserTools(server, hevyClient);\n\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\ttoolsSpan.end();\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\t\t\treturn server;\n\t\t\t} catch (e) {\n\t\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\t\tthrow e;\n\t\t\t} finally {\n\t\t\t\tspan.end();\n\t\t\t}\n\t\t},\n\t);\n}\n\nexport function createServer({ config }: { config: ServerConfig }) {\n\tconst { apiKey } = serverConfigSchema.parse(config);\n\tconst server = buildServer(apiKey);\n\treturn server;\n}\n\nexport default createServer;\n\nexport async function runServer() {\n\tconst args = process.argv.slice(2);\n\tconst cliAction = getCliAction(args);\n\n\tif (cliAction === \"version\") {\n\t\tconsole.log(version);\n\t\treturn;\n\t}\n\n\tif (cliAction === \"help\") {\n\t\tconsole.log(HELP_TEXT);\n\t\treturn;\n\t}\n\n\tserverStartups.add(1, { version });\n\n\tawait tracer.startActiveSpan(\n\t\t\"mcp.server.run\",\n\t\t{\n\t\t\tattributes: {\n\t\t\t\t\"mcp.transport\": \"stdio\",\n\t\t\t},\n\t\t},\n\t\tasync (span) => {\n\t\t\ttry {\n\t\t\t\tconst cfg = parseConfig(args, process.env);\n\t\t\t\tconst apiKey = cfg.apiKey;\n\t\t\t\tassertApiKey(apiKey);\n\n\t\t\t\tconst server = buildServer(apiKey);\n\t\t\t\tconsole.error(\"Starting MCP server in stdio mode\");\n\t\t\t\tconst transport = createInstrumentedStdioTransport(\n\t\t\t\t\tnew StdioServerTransport(),\n\t\t\t\t);\n\n\t\t\t\tawait tracer.startActiveSpan(\n\t\t\t\t\t\"mcp.server.connect\",\n\t\t\t\t\t{\n\t\t\t\t\t\tattributes: {\n\t\t\t\t\t\t\t\"mcp.transport\": \"stdio\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tasync (connectSpan) => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tawait server.connect(transport);\n\t\t\t\t\t\t\tconnectSpan.setStatus({ code: SpanStatusCode.OK });\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\tconnectSpan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\t\t\t\t\tthrow e;\n\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\tconnectSpan.end();\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\t\t} catch (e) {\n\t\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\t\tthrow e;\n\t\t\t} finally {\n\t\t\t\tspan.end();\n\t\t\t}\n\t\t},\n\t);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"src-DSiZLCgu.mjs","names":["name","version","normalizeHeaderValue","getHeaderValue","normalizedConfig","createClient","api.getV1Workouts","api.getV1WorkoutsWorkoutid","api.postV1Workouts","api.putV1WorkoutsWorkoutid","api.getV1WorkoutsCount","api.getV1WorkoutsEvents","api.getV1Routines","api.getV1RoutinesRoutineid","api.postV1Routines","api.putV1RoutinesRoutineid","api.getV1ExerciseTemplates","api.getV1ExerciseTemplatesExercisetemplateid","api.getV1ExerciseHistoryExercisetemplateid","api.postV1ExerciseTemplates","api.getV1RoutineFolders","api.postV1RoutineFolders","api.getV1RoutineFoldersFolderid","api.getV1BodyMeasurements","api.getV1BodyMeasurementsDate","api.postV1BodyMeasurements","api.putV1BodyMeasurementsDate","api.getV1UserInfo","createKubbClient","serviceName","serviceVersion"],"sources":["../src/utils/telemetry.ts","../src/utils/metrics.ts","../src/utils/error-handler.ts","../src/utils/formatters.ts","../src/utils/response-formatter.ts","../src/utils/tool-annotations.ts","../src/utils/tool-helpers.ts","../src/utils/schemas.ts","../src/tools/body-measurements.ts","../src/tools/folders.ts","../src/utils/json-parser.ts","../src/tools/routines.ts","../src/utils/cache.ts","../src/tools/templates.ts","../src/tools/user.ts","../src/tools/workouts.ts","../src/utils/config.ts","../src/generated/.kubb/fetch.ts","../src/generated/client/api/getV1BodyMeasurements.ts","../src/generated/client/api/getV1BodyMeasurementsDate.ts","../src/generated/client/api/getV1ExerciseHistoryExercisetemplateid.ts","../src/generated/client/api/getV1ExerciseTemplates.ts","../src/generated/client/api/getV1ExerciseTemplatesExercisetemplateid.ts","../src/generated/client/api/getV1RoutineFolders.ts","../src/generated/client/api/getV1RoutineFoldersFolderid.ts","../src/generated/client/api/getV1Routines.ts","../src/generated/client/api/getV1RoutinesRoutineid.ts","../src/generated/client/api/getV1UserInfo.ts","../src/generated/client/api/getV1Workouts.ts","../src/generated/client/api/getV1WorkoutsCount.ts","../src/generated/client/api/getV1WorkoutsEvents.ts","../src/generated/client/api/getV1WorkoutsWorkoutid.ts","../src/generated/client/api/postV1BodyMeasurements.ts","../src/generated/client/api/postV1ExerciseTemplates.ts","../src/generated/client/api/postV1RoutineFolders.ts","../src/generated/client/api/postV1Routines.ts","../src/generated/client/api/postV1Workouts.ts","../src/generated/client/api/putV1BodyMeasurementsDate.ts","../src/generated/client/api/putV1RoutinesRoutineid.ts","../src/generated/client/api/putV1WorkoutsWorkoutid.ts","../src/utils/hevyClientKubb.ts","../src/utils/hevyClient.ts","../src/utils/stdio-observability.ts","../src/index.ts"],"sourcesContent":["/**\n * Centralized telemetry initialization.\n *\n * This module MUST be imported before any other application code.\n * It sets up OpenTelemetry with dual export: Sentry (error events +\n * traces) and an OTel Collector (traces + metrics to Honeycomb).\n *\n * Sentry SDK: error events, performance traces, release tracking\n * OTel Collector → Honeycomb: performance traces, metrics\n */\n\nimport * as Sentry from \"@sentry/node\";\nimport {\n\tSentryPropagator,\n\tSentrySampler,\n\tSentrySpanProcessor,\n} from \"@sentry/opentelemetry\";\nimport { trace, metrics } from \"@opentelemetry/api\";\nimport { OTLPTraceExporter } from \"@opentelemetry/exporter-trace-otlp-http\";\nimport { OTLPMetricExporter } from \"@opentelemetry/exporter-metrics-otlp-http\";\nimport { resourceFromAttributes } from \"@opentelemetry/resources\";\nimport { BatchSpanProcessor } from \"@opentelemetry/sdk-trace-base\";\nimport type { SpanProcessor } from \"@opentelemetry/sdk-trace\";\nimport { NodeTracerProvider } from \"@opentelemetry/sdk-trace-node\";\nimport {\n\tMeterProvider,\n\tPeriodicExportingMetricReader,\n} from \"@opentelemetry/sdk-metrics\";\n\ndeclare const __HEVY_MCP_NAME__: string | undefined;\ndeclare const __HEVY_MCP_VERSION__: string | undefined;\ndeclare const __HEVY_MCP_BUILD__: boolean | undefined;\ndeclare const __OTEL_COLLECTOR_TOKEN__: string | undefined;\n\nconst name =\n\ttypeof __HEVY_MCP_NAME__ === \"string\" ? __HEVY_MCP_NAME__ : \"hevy-mcp\";\nconst version =\n\ttypeof __HEVY_MCP_VERSION__ === \"string\" ? __HEVY_MCP_VERSION__ : \"dev\";\n\n// Collector token is injected at build time from the OTEL_COLLECTOR_TOKEN\n// GitHub secret via tsdown.config.ts define. The collector forwards\n// traces and metrics to Honeycomb, keeping the Honeycomb API key off the\n// client. The collector endpoint is public (behind Cloudflare Tunnel).\nconst collectorToken =\n\ttypeof __OTEL_COLLECTOR_TOKEN__ === \"string\" && __OTEL_COLLECTOR_TOKEN__\n\t\t? __OTEL_COLLECTOR_TOKEN__\n\t\t: (process.env.OTEL_COLLECTOR_TOKEN ?? \"\");\n\nconst COLLECTOR_ENDPOINT = \"https://otel.chrisdoc.dev/v1\";\n\nconst sentryRelease = process.env.SENTRY_RELEASE ?? `${name}@${version}`;\n\nconst resource = resourceFromAttributes({\n\t\"service.name\": name,\n\t\"service.version\": version,\n});\n\nconst bakedDsn =\n\t\"https://ce696d8333b507acbf5203eb877bce0f@o4508975499575296.ingest.de.sentry.io/4509049671647312\";\nconst rawDsn = process.env.SENTRY_DSN ?? bakedDsn;\nconst isValidDsn =\n\ttypeof rawDsn === \"string\" && rawDsn.length > 0 && !rawDsn.startsWith(\"*\");\n\n// --- Sentry (error monitoring + traces) ---\nconst sentryClient = Sentry.init({\n\tdsn: isValidDsn ? rawDsn : undefined,\n\trelease: sentryRelease,\n\ttracesSampleRate: 1.0,\n\tsendDefaultPii: false,\n\tskipOpenTelemetrySetup: true,\n\tregisterEsmLoaderHooks: false,\n\tignoreErrors: [\"EPIPE\", \"broken pipe\"],\n});\n\n// --- OpenTelemetry tracer provider (dual export) ---\nconst spanProcessors: SpanProcessor[] = [new SentrySpanProcessor()];\n\n// Span processor 2: OTel Collector → Honeycomb (traces) — only if token is available\nif (collectorToken) {\n\tspanProcessors.push(\n\t\tnew BatchSpanProcessor(\n\t\t\tnew OTLPTraceExporter({\n\t\t\t\turl: `${COLLECTOR_ENDPOINT}/traces`,\n\t\t\t\theaders: {\n\t\t\t\t\tAuthorization: `Bearer ${collectorToken}`,\n\t\t\t\t},\n\t\t\t}),\n\t\t),\n\t);\n}\n\nconst tracerProvider = new NodeTracerProvider({\n\tresource,\n\tsampler: sentryClient ? new SentrySampler(sentryClient) : undefined,\n\tspanProcessors,\n});\n\ntracerProvider.register({\n\tpropagator: new SentryPropagator(),\n\tcontextManager: new Sentry.SentryContextManager(),\n});\n\n// --- OpenTelemetry meter provider (→ Collector → Honeycomb metrics) ---\nif (collectorToken) {\n\tconst meterProvider = new MeterProvider({\n\t\tresource,\n\t\treaders: [\n\t\t\tnew PeriodicExportingMetricReader({\n\t\t\t\texporter: new OTLPMetricExporter({\n\t\t\t\t\turl: `${COLLECTOR_ENDPOINT}/metrics`,\n\t\t\t\t\theaders: {\n\t\t\t\t\t\tAuthorization: `Bearer ${collectorToken}`,\n\t\t\t\t\t},\n\t\t\t\t}),\n\t\t\t\texportIntervalMillis: 10_000,\n\t\t\t}),\n\t\t],\n\t});\n\tmetrics.setGlobalMeterProvider(meterProvider);\n}\n\ntrace.setGlobalTracerProvider(tracerProvider);\n\n// Validate that Sentry + OpenTelemetry are wired correctly\nSentry.validateOpenTelemetrySetup();\n\n// --- Shared instances for the rest of the codebase ---\nexport const tracer = trace.getTracer(name);\nexport const meter = metrics.getMeter(name);\nexport { Sentry };\n\n/**\n * Bundled service identity — avoids passing name and version as\n * separate primitives throughout the codebase (Data Clumps smell).\n */\nexport interface ServiceInfo {\n\treadonly name: string;\n\treadonly version: string;\n}\n\nexport const serviceInfo: ServiceInfo = { name, version } as const;\n\n// Keep individual exports for backward compatibility\nexport { name as serviceName, version as serviceVersion };\n\n// --- User context for span attributes ---\nlet currentUserId: string | undefined;\n\nexport function setCurrentUserId(id: string): void {\n\tcurrentUserId = id;\n}\n\nexport function getCurrentUserId(): string | undefined {\n\treturn currentUserId;\n}\n","/**\n * Metric instruments for Honeycomb.\n *\n * These are created once from the shared meter provider and exported\n * for use throughout the codebase. All instruments are sent to Honeycomb\n * via the OTLP metrics exporter configured in telemetry.ts.\n */\n\nimport { meter } from \"./telemetry.js\";\n\n/** Total MCP tool invocations, grouped by tool name. */\nexport const toolInvocations = meter.createCounter(\"mcp.tool.invocations\", {\n\tdescription: \"Total MCP tool invocations\",\n});\n\n/** Total MCP tool errors, grouped by tool name and error type. */\nexport const toolErrors = meter.createCounter(\"mcp.tool.errors\", {\n\tdescription: \"Total MCP tool errors\",\n});\n\n/** MCP tool execution duration in milliseconds. */\nexport const toolDuration = meter.createHistogram(\"mcp.tool.duration_ms\", {\n\tdescription: \"MCP tool execution duration in milliseconds\",\n\tunit: \"ms\",\n});\n\n/** Total Hevy API calls, grouped by method, endpoint, and status code. */\nexport const apiCalls = meter.createCounter(\"hevy.api.calls\", {\n\tdescription: \"Total Hevy API calls\",\n});\n\n/** Hevy API response time in milliseconds. */\nexport const apiDuration = meter.createHistogram(\"hevy.api.duration_ms\", {\n\tdescription: \"Hevy API response time in milliseconds\",\n\tunit: \"ms\",\n});\n\n/** Total stdio JSON parse errors, grouped by failure location. */\nexport const stdioParseErrors = meter.createCounter(\"mcp.stdio.parse_errors\", {\n\tdescription: \"Total stdio JSON parse errors\",\n});\n\n/** Total server startup count, grouped by version. */\nexport const serverStartups = meter.createCounter(\"mcp.server.startups\", {\n\tdescription: \"Total server startup count\",\n});\n","/**\n * Centralized error handling utility for MCP tools\n */\n\nimport { SpanStatusCode } from \"@opentelemetry/api\";\nimport { isAxiosError } from \"axios\";\nimport { Sentry, tracer, getCurrentUserId } from \"./telemetry.js\";\nimport { toolInvocations, toolErrors, toolDuration } from \"./metrics.js\";\nimport type { McpToolResponse } from \"./response-formatter.js\";\n\n/**\n * Standard error response interface\n */\nexport interface ErrorResponse {\n\tmessage: string;\n\tcode?: string;\n\tdetails?: unknown;\n}\n\n/**\n * Specific error types for better categorization\n */\nexport enum ErrorType {\n\tAPI_ERROR = \"API_ERROR\",\n\tRATE_LIMIT = \"RATE_LIMIT\",\n\tVALIDATION_ERROR = \"VALIDATION_ERROR\",\n\tNOT_FOUND = \"NOT_FOUND\",\n\tNETWORK_ERROR = \"NETWORK_ERROR\",\n\tUNKNOWN_ERROR = \"UNKNOWN_ERROR\",\n}\n\ntype RetryAwareError = {\n\thevyRetryCount?: number;\n\thevyRetryExhausted?: boolean;\n};\n\nfunction normalizeHeaderValue(value: unknown): string | undefined {\n\tif (typeof value === \"string\") {\n\t\tconst trimmed = value.trim();\n\t\treturn trimmed.length > 0 ? trimmed : undefined;\n\t}\n\n\tif (typeof value === \"number\" && Number.isFinite(value)) {\n\t\treturn String(value);\n\t}\n\n\tif (Array.isArray(value) && value.length > 0) {\n\t\treturn normalizeHeaderValue(value[0]);\n\t}\n\n\treturn undefined;\n}\n\nfunction getHeaderValue(headers: unknown, key: string): string | undefined {\n\tif (!headers || typeof headers !== \"object\") {\n\t\treturn undefined;\n\t}\n\n\tif (\n\t\t\"get\" in headers &&\n\t\ttypeof (headers as { get?: unknown }).get === \"function\"\n\t) {\n\t\tconst value = (headers as { get: (headerName: string) => unknown }).get(\n\t\t\tkey,\n\t\t);\n\t\treturn normalizeHeaderValue(value);\n\t}\n\n\tconst headerRecord = headers as Record<string, unknown>;\n\treturn normalizeHeaderValue(\n\t\theaderRecord[key] ??\n\t\t\theaderRecord[key.toLowerCase()] ??\n\t\t\theaderRecord[key.toUpperCase()],\n\t);\n}\n\nfunction formatSecondsLabel(seconds: number): string {\n\tconst roundedSeconds = Math.max(0, Math.round(seconds));\n\tconst suffix = roundedSeconds === 1 ? \"\" : \"s\";\n\treturn `${roundedSeconds} second${suffix}`;\n}\n\nfunction getRateLimitMessage(error: unknown): string {\n\tif (!isAxiosError(error)) {\n\t\treturn \"Rate limited by Hevy. Please wait and retry.\";\n\t}\n\n\tconst retryAfterHeader = getHeaderValue(\n\t\terror.response?.headers,\n\t\t\"retry-after\",\n\t);\n\tif (!retryAfterHeader) {\n\t\treturn \"Rate limited by Hevy (HTTP 429). Please wait and retry your request.\";\n\t}\n\n\tconst seconds = Number(retryAfterHeader);\n\tif (Number.isFinite(seconds) && seconds >= 0) {\n\t\treturn `Rate limited by Hevy (HTTP 429). Please wait about ${formatSecondsLabel(seconds)} before retrying.`;\n\t}\n\n\tconst retryAtMillis = Date.parse(retryAfterHeader);\n\tif (!Number.isNaN(retryAtMillis)) {\n\t\tconst secondsUntilRetry = Math.ceil(\n\t\t\tMath.max(0, retryAtMillis - Date.now()) / 1000,\n\t\t);\n\t\treturn `Rate limited by Hevy (HTTP 429). Please wait about ${formatSecondsLabel(secondsUntilRetry)} before retrying.`;\n\t}\n\n\treturn \"Rate limited by Hevy (HTTP 429). Please wait and retry your request.\";\n}\n\nfunction isRetryExhaustedError(error: unknown): boolean {\n\treturn (\n\t\t!!error &&\n\t\ttypeof error === \"object\" &&\n\t\t(error as RetryAwareError).hevyRetryExhausted === true\n\t);\n}\n\nfunction getRetryExhaustedMessage(error: unknown): string {\n\tconst retryCount =\n\t\ttypeof error === \"object\" && error !== null\n\t\t\t? (error as RetryAwareError).hevyRetryCount\n\t\t\t: undefined;\n\tconst attemptCount =\n\t\ttypeof retryCount === \"number\" && Number.isFinite(retryCount)\n\t\t\t? retryCount + 1\n\t\t\t: undefined;\n\n\tif (attemptCount) {\n\t\treturn `Unable to complete the request after ${attemptCount} attempts to the Hevy API due to transient failures. Please try again shortly.`;\n\t}\n\n\treturn \"Unable to complete the request after multiple attempts to the Hevy API due to transient failures. Please try again shortly.\";\n}\n\nfunction getUserFacingMessage(error: unknown, defaultMessage: string): string {\n\tif (isRetryExhaustedError(error)) {\n\t\treturn getRetryExhaustedMessage(error);\n\t}\n\n\tif (isAxiosError(error) && error.response?.status === 429) {\n\t\treturn getRateLimitMessage(error);\n\t}\n\n\treturn defaultMessage;\n}\n\n/**\n * Enhanced error response with type categorization\n */\nexport interface EnhancedErrorResponse extends ErrorResponse {\n\ttype: ErrorType;\n}\n\n/**\n * Structured debug context that preserves original error details\n */\nexport interface ErrorDebugContext {\n\tsourceContext?: string;\n\toriginalErrorMessage: string;\n\terrorCode?: string;\n\terrorType: ErrorType;\n\taxios?: {\n\t\tstatus?: number;\n\t\tstatusText?: string;\n\t\tdata?: unknown;\n\t\tmethod?: string;\n\t\turl?: string;\n\t};\n}\n\n/**\n * Create a standardized error response for MCP tools\n *\n * @param error - The error object or message\n * @param context - Optional context information about where the error occurred\n * @returns A formatted MCP tool response with error information\n */\nexport function createErrorResponse(\n\terror: unknown,\n\tcontext?: string,\n): McpToolResponse {\n\tconst originalErrorMessage = extractErrorMessage(error);\n\tlet errorMessage = originalErrorMessage;\n\tconst axiosErrorContext = extractAxiosErrorContext(error);\n\tconst mappedHevyErrorMessage = mapHevyErrorMessageByStatus(\n\t\taxiosErrorContext?.status,\n\t);\n\n\tif (mappedHevyErrorMessage) {\n\t\terrorMessage = mappedHevyErrorMessage;\n\t}\n\n\t// Check for axios error with response data\n\tif (!mappedHevyErrorMessage && axiosErrorContext?.data) {\n\t\terrorMessage = stringifyErrorData(axiosErrorContext.data);\n\t}\n\n\terrorMessage = getUserFacingMessage(error, errorMessage);\n\n\t// Extract error code if available (for logging purposes)\n\tconst errorCode =\n\t\terror instanceof Error && \"code\" in error\n\t\t\t? (error as { code?: string }).code\n\t\t\t: undefined;\n\n\t// Determine error type based on error characteristics\n\tconst errorType = determineErrorType(error, errorMessage);\n\tconst errorContext: ErrorDebugContext = {\n\t\tsourceContext: context,\n\t\toriginalErrorMessage,\n\t\terrorCode,\n\t\terrorType,\n\t\taxios: axiosErrorContext ?? undefined,\n\t};\n\n\tconst contextPrefix = context ? `[${context}] ` : \"\";\n\tconst formattedMessage = `${contextPrefix}Error: ${errorMessage}`;\n\tconst errorCodeSuffix = errorCode ? `, Code: ${errorCode}` : \"\";\n\n\t// Log the error for server-side debugging with type information\n\tconsole.error(\n\t\t`${formattedMessage} (Type: ${errorType}${errorCodeSuffix})`,\n\t\terror,\n\t);\n\n\treturn {\n\t\tcontent: [\n\t\t\t{\n\t\t\t\ttype: \"text\" as const,\n\t\t\t\ttext: formattedMessage,\n\t\t\t},\n\t\t],\n\t\tisError: true,\n\t\terrorContext,\n\t};\n}\n\nfunction extractErrorMessage(error: unknown): string {\n\tif (error instanceof Error) {\n\t\treturn error.message;\n\t}\n\n\tif (typeof error === \"string\") {\n\t\treturn error;\n\t}\n\n\tif (\n\t\terror &&\n\t\ttypeof error === \"object\" &&\n\t\t\"message\" in error &&\n\t\ttypeof error.message === \"string\"\n\t) {\n\t\treturn error.message;\n\t}\n\n\tif (error && typeof error === \"object\") {\n\t\ttry {\n\t\t\treturn JSON.stringify(error);\n\t\t} catch (_e) {\n\t\t\treturn \"Unknown error object\";\n\t\t}\n\t}\n\n\treturn String(error);\n}\n\nfunction extractAxiosErrorContext(\n\terror: unknown,\n): ErrorDebugContext[\"axios\"] | null {\n\tif (!isAxiosError(error)) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\tstatus: error.response?.status,\n\t\tstatusText: error.response?.statusText,\n\t\tdata: error.response?.data,\n\t\tmethod: error.config?.method,\n\t\turl: error.config?.url,\n\t};\n}\n\nfunction mapHevyErrorMessageByStatus(status?: number): string | null {\n\tif (status === 401 || status === 403) {\n\t\treturn \"The Hevy API key is invalid or has expired. Check HEVY_API_KEY.\";\n\t}\n\n\tif (status === 404) {\n\t\treturn \"The requested resource was not found in Hevy.\";\n\t}\n\n\tif (status === 409) {\n\t\treturn \"A conflict occurred (e.g., a body measurement already exists for this date). Use the update tool instead.\";\n\t}\n\n\tif (status === 422) {\n\t\treturn \"The request failed Hevy validation. Check the field values and try again.\";\n\t}\n\n\tif (status === 429) {\n\t\treturn \"Rate limited by Hevy. Please wait and retry.\";\n\t}\n\n\tif (status && status >= 500 && status <= 599) {\n\t\treturn \"Hevy API experienced an error. Please retry later.\";\n\t}\n\n\treturn null;\n}\n\nfunction stringifyErrorData(data: unknown): string {\n\tif (typeof data === \"string\") {\n\t\treturn data;\n\t}\n\n\tif (data && typeof data === \"object\") {\n\t\ttry {\n\t\t\treturn JSON.stringify(data);\n\t\t} catch (_e) {\n\t\t\treturn \"Unable to serialize error response data\";\n\t\t}\n\t}\n\n\treturn String(data);\n}\n\n/**\n * Determine the type of error based on error characteristics\n */\nfunction determineErrorType(error: unknown, message: string): ErrorType {\n\tif (isRetryExhaustedError(error)) {\n\t\treturn ErrorType.NETWORK_ERROR;\n\t}\n\n\tif (isAxiosError(error) && error.response?.status === 429) {\n\t\treturn ErrorType.RATE_LIMIT;\n\t}\n\n\tconst messageLower = message.toLowerCase();\n\tconst nameLower = error instanceof Error ? error.name.toLowerCase() : \"\";\n\n\tif (\n\t\tnameLower.includes(\"network\") ||\n\t\tmessageLower.includes(\"network\") ||\n\t\tnameLower.includes(\"fetch\") ||\n\t\tmessageLower.includes(\"fetch\") ||\n\t\tnameLower.includes(\"timeout\") ||\n\t\tmessageLower.includes(\"timeout\")\n\t) {\n\t\treturn ErrorType.NETWORK_ERROR;\n\t}\n\n\tif (\n\t\tnameLower.includes(\"validation\") ||\n\t\tmessageLower.includes(\"validation\") ||\n\t\tmessageLower.includes(\"invalid\") ||\n\t\tmessageLower.includes(\"required\")\n\t) {\n\t\treturn ErrorType.VALIDATION_ERROR;\n\t}\n\n\tif (\n\t\tmessageLower.includes(\"not found\") ||\n\t\tmessageLower.includes(\"404\") ||\n\t\tmessageLower.includes(\"does not exist\")\n\t) {\n\t\treturn ErrorType.NOT_FOUND;\n\t}\n\n\tif (\n\t\tnameLower.includes(\"api\") ||\n\t\tmessageLower.includes(\"api\") ||\n\t\tmessageLower.includes(\"server error\") ||\n\t\tmessageLower.includes(\"500\")\n\t) {\n\t\treturn ErrorType.API_ERROR;\n\t}\n\n\treturn ErrorType.UNKNOWN_ERROR;\n}\n\n/**\n * Wrap an async function with standardized error handling\n *\n * This function preserves the parameter types of the wrapped function while\n * providing error handling. The returned function accepts Record<string, unknown>\n * (as required by MCP SDK) but internally casts to the original parameter type.\n *\n * @param fn - The async function to wrap\n * @param context - Context information for error messages\n * @returns A function that catches errors and returns standardized error responses\n */\nexport function withErrorHandling<TParams extends Record<string, unknown>>(\n\tfn: (args: TParams) => Promise<McpToolResponse>,\n\tcontext: string,\n): (args: Record<string, unknown>) => Promise<McpToolResponse> {\n\treturn async (args: Record<string, unknown>) => {\n\t\tconst argumentKeyCount = Object.keys(args).length;\n\t\tconst startTime = Date.now();\n\n\t\ttoolInvocations.add(1, { tool_name: context });\n\n\t\treturn tracer.startActiveSpan(\n\t\t\t`mcp.tool.${context}`,\n\t\t\t{\n\t\t\t\tattributes: {\n\t\t\t\t\t\"mcp.tool.name\": context,\n\t\t\t\t\t\"mcp.tool.args.key_count\": argumentKeyCount,\n\t\t\t\t\t...(getCurrentUserId() ? { \"user.id\": getCurrentUserId() } : {}),\n\t\t\t\t},\n\t\t\t},\n\t\t\tasync (span) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await fn(args as TParams);\n\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\t\t\t\tspan.setAttribute(\n\t\t\t\t\t\t\"mcp.tool.result.is_error\",\n\t\t\t\t\t\tBoolean(result.isError),\n\t\t\t\t\t);\n\t\t\t\t\treturn result;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\t\t\tspan.recordException(error as Error);\n\n\t\t\t\t\tconst errorType = determineErrorType(\n\t\t\t\t\t\terror,\n\t\t\t\t\t\terror instanceof Error ? error.message : String(error),\n\t\t\t\t\t);\n\n\t\t\t\t\tspan.setAttribute(\"error.type\", errorType);\n\t\t\t\t\ttoolErrors.add(1, {\n\t\t\t\t\t\ttool_name: context,\n\t\t\t\t\t\terror_type: errorType,\n\t\t\t\t\t});\n\n\t\t\t\t\tSentry.withScope((scope) => {\n\t\t\t\t\t\tscope.setTag(\"mcp.tool.context\", context);\n\t\t\t\t\t\tscope.setContext(\"mcpTool\", {\n\t\t\t\t\t\t\tcontext,\n\t\t\t\t\t\t\targumentKeyCount,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tSentry.captureException(error);\n\t\t\t\t\t});\n\n\t\t\t\t\treturn createErrorResponse(error, context);\n\t\t\t\t} finally {\n\t\t\t\t\ttoolDuration.record(Date.now() - startTime, {\n\t\t\t\t\t\ttool_name: context,\n\t\t\t\t\t});\n\t\t\t\t\tspan.end();\n\t\t\t\t}\n\t\t\t},\n\t\t);\n\t};\n}\n","import type {\n\tBodyMeasurement,\n\tExerciseHistoryEntry,\n\tExerciseTemplate,\n\tRoutine,\n\tRoutineFolder,\n\tWorkout,\n} from \"../generated/client/types/index.js\";\n\n/**\n * Formatted workout set interface\n */\nexport interface FormattedWorkoutSet {\n\tindex: number | undefined;\n\ttype: string | undefined;\n\tweight: number | undefined | null;\n\treps: number | undefined | null;\n\tdistance: number | undefined | null;\n\tduration: number | undefined | null;\n\trpe: number | undefined | null;\n\tcustomMetric: number | undefined | null;\n}\n\n/**\n * Formatted workout exercise interface\n */\nexport interface FormattedWorkoutExercise {\n\tindex: number | undefined;\n\tname: string | undefined;\n\texerciseTemplateId: string | undefined;\n\tnotes: string | undefined | null;\n\tsupersetsId: number | undefined | null;\n\tsets: FormattedWorkoutSet[] | undefined;\n}\n\n/**\n * Formatted workout interface\n */\nexport interface FormattedWorkout {\n\tid: string | undefined;\n\ttitle: string | undefined;\n\tdescription: string | undefined | null;\n\tstartTime: string | number | undefined;\n\tendTime: string | number | undefined;\n\tcreatedAt: string | undefined;\n\tupdatedAt: string | undefined;\n\tduration: string;\n\texercises: FormattedWorkoutExercise[] | undefined;\n}\n\n/**\n * Formatted routine set interface\n */\nexport interface FormattedRoutineSet {\n\tindex: number | undefined;\n\ttype: string | undefined;\n\tweight: number | undefined | null;\n\treps: number | undefined | null;\n\tdistance: number | undefined | null;\n\tduration: number | undefined | null;\n\tcustomMetric: number | undefined | null;\n\trepRange?: { start?: number | null; end?: number | null } | undefined | null;\n\trpe?: number | undefined | null;\n}\n\n/**\n * Formatted routine exercise interface\n */\nexport interface FormattedRoutineExercise {\n\tname: string | undefined;\n\tindex: number | undefined;\n\texerciseTemplateId: string | undefined;\n\tnotes: string | undefined | null;\n\tsupersetId: number | undefined | null;\n\trestSeconds: string | undefined;\n\tsets: FormattedRoutineSet[] | undefined;\n}\n\n/**\n * Formatted routine interface\n */\nexport interface FormattedRoutine {\n\tid: string | undefined;\n\ttitle: string | undefined;\n\tfolderId: number | undefined | null;\n\tcreatedAt: string | undefined;\n\tupdatedAt: string | undefined;\n\texercises: FormattedRoutineExercise[] | undefined;\n}\n\n/**\n * Formatted routine folder interface\n */\nexport interface FormattedRoutineFolder {\n\tid: number | undefined;\n\ttitle: string | undefined;\n\tcreatedAt: string | undefined;\n\tupdatedAt: string | undefined;\n}\n\n/**\n * Formatted exercise template interface\n */\nexport interface FormattedExerciseTemplate {\n\tid: string | undefined;\n\ttitle: string | undefined;\n\ttype: string | undefined;\n\tprimaryMuscleGroup: string | undefined;\n\tsecondaryMuscleGroups: string[] | undefined;\n\tisCustom: boolean | undefined;\n}\n\nexport interface FormattedExerciseHistoryEntry {\n\tworkoutId: string | undefined;\n\tworkoutTitle: string | undefined;\n\tworkoutStartTime: string | undefined;\n\tworkoutEndTime: string | undefined;\n\texerciseTemplateId: string | undefined;\n\tweight: number | undefined | null;\n\treps: number | undefined | null;\n\tdistance: number | undefined | null;\n\tduration: number | undefined | null;\n\trpe: number | undefined | null;\n\tcustomMetric: number | undefined | null;\n\tsetType: string | undefined;\n}\n\ntype ExerciseWithSupersetVariants = {\n\tsupersets_id?: number | null;\n\tsuperset_id?: number | null;\n};\n\nfunction getSupersetId(exercise: ExerciseWithSupersetVariants): number | null {\n\tif (exercise.superset_id !== undefined) {\n\t\treturn exercise.superset_id;\n\t}\n\n\tif (exercise.supersets_id !== undefined) {\n\t\treturn exercise.supersets_id;\n\t}\n\n\treturn null;\n}\n\n/**\n * Format a workout object for consistent presentation\n *\n * @param workout - The workout object from the API\n * @returns A formatted workout object with standardized properties\n */\nexport function formatWorkout(workout: Workout): FormattedWorkout {\n\treturn {\n\t\tid: workout.id,\n\t\ttitle: workout.title,\n\t\tdescription: workout.description,\n\t\tstartTime: workout.start_time,\n\t\tendTime: workout.end_time,\n\t\tcreatedAt: workout.created_at,\n\t\tupdatedAt: workout.updated_at,\n\t\tduration: calculateDuration(workout.start_time, workout.end_time),\n\t\texercises: workout.exercises?.map((exercise) => {\n\t\t\treturn {\n\t\t\t\tindex: exercise.index,\n\t\t\t\tname: exercise.title,\n\t\t\t\texerciseTemplateId: exercise.exercise_template_id,\n\t\t\t\tnotes: exercise.notes,\n\t\t\t\tsupersetsId: getSupersetId(exercise),\n\t\t\t\tsets: exercise.sets?.map((set) => ({\n\t\t\t\t\tindex: set.index,\n\t\t\t\t\ttype: set.type,\n\t\t\t\t\tweight: set.weight_kg,\n\t\t\t\t\treps: set.reps,\n\t\t\t\t\tdistance: set.distance_meters,\n\t\t\t\t\tduration: set.duration_seconds,\n\t\t\t\t\trpe: set.rpe,\n\t\t\t\t\tcustomMetric: set.custom_metric,\n\t\t\t\t})),\n\t\t\t};\n\t\t}),\n\t};\n}\n\n/**\n * Format a routine object for consistent presentation\n *\n * @param routine - The routine object from the API\n * @returns A formatted routine object with standardized properties\n */\nexport function formatRoutine(routine: Routine): FormattedRoutine {\n\treturn {\n\t\tid: routine.id,\n\t\ttitle: routine.title,\n\t\tfolderId: routine.folder_id,\n\t\tcreatedAt: routine.created_at,\n\t\tupdatedAt: routine.updated_at,\n\t\texercises: routine.exercises?.map((exercise) => {\n\t\t\treturn {\n\t\t\t\tname: exercise.title,\n\t\t\t\tindex: exercise.index,\n\t\t\t\texerciseTemplateId: exercise.exercise_template_id,\n\t\t\t\tnotes: exercise.notes,\n\t\t\t\tsupersetId: getSupersetId(exercise),\n\t\t\t\trestSeconds: exercise.rest_seconds,\n\t\t\t\tsets: exercise.sets?.map((set) => ({\n\t\t\t\t\tindex: set.index,\n\t\t\t\t\ttype: set.type,\n\t\t\t\t\tweight: set.weight_kg,\n\t\t\t\t\treps: set.reps,\n\t\t\t\t\t...(set.rep_range !== undefined && { repRange: set.rep_range }),\n\t\t\t\t\tdistance: set.distance_meters,\n\t\t\t\t\tduration: set.duration_seconds,\n\t\t\t\t\t...(set.rpe !== undefined && { rpe: set.rpe }),\n\t\t\t\t\tcustomMetric: set.custom_metric,\n\t\t\t\t})),\n\t\t\t};\n\t\t}),\n\t};\n}\n\n/**\n * Format a routine folder object for consistent presentation\n *\n * @param folder - The routine folder object from the API\n * @returns A formatted routine folder object with standardized properties\n */\nexport function formatRoutineFolder(\n\tfolder: RoutineFolder,\n): FormattedRoutineFolder {\n\treturn {\n\t\tid: folder.id,\n\t\ttitle: folder.title,\n\t\tcreatedAt: folder.created_at,\n\t\tupdatedAt: folder.updated_at,\n\t};\n}\n\n/**\n * Calculate duration between two ISO timestamp strings\n *\n * @param startTime - The start time as ISO string or timestamp\n * @param endTime - The end time as ISO string or timestamp\n * @returns A formatted duration string (e.g. \"1h 30m 45s\") or \"Unknown duration\" if inputs are invalid\n */\nexport function calculateDuration(\n\tstartTime: string | number | null | undefined,\n\tendTime: string | number | null | undefined,\n): string {\n\tif (!startTime || !endTime) return \"Unknown duration\";\n\n\ttry {\n\t\tconst start = new Date(startTime);\n\t\tconst end = new Date(endTime);\n\n\t\t// Validate dates\n\t\tif (Number.isNaN(start.getTime()) || Number.isNaN(end.getTime())) {\n\t\t\treturn \"Unknown duration\";\n\t\t}\n\n\t\tconst durationMs = end.getTime() - start.getTime();\n\n\t\t// Handle negative durations\n\t\tif (durationMs < 0) {\n\t\t\treturn \"Invalid duration (end time before start time)\";\n\t\t}\n\n\t\tconst hours = Math.floor(durationMs / (1000 * 60 * 60));\n\t\tconst minutes = Math.floor((durationMs % (1000 * 60 * 60)) / (1000 * 60));\n\t\tconst seconds = Math.floor((durationMs % (1000 * 60)) / 1000);\n\n\t\treturn `${hours}h ${minutes}m ${seconds}s`;\n\t} catch (error) {\n\t\tconsole.error(\"Error calculating duration:\", error);\n\t\treturn \"Unknown duration\";\n\t}\n}\n\n/**\n * Format an exercise template object for consistent presentation\n *\n * @param template - The exercise template object from the API\n * @returns A formatted exercise template object with standardized properties\n */\nexport function formatExerciseTemplate(\n\ttemplate: ExerciseTemplate,\n): FormattedExerciseTemplate {\n\treturn {\n\t\tid: template.id,\n\t\ttitle: template.title,\n\t\ttype: template.type,\n\t\tprimaryMuscleGroup: template.primary_muscle_group,\n\t\tsecondaryMuscleGroups: template.secondary_muscle_groups,\n\t\tisCustom: template.is_custom,\n\t};\n}\n\nexport function formatExerciseHistoryEntry(\n\tentry: ExerciseHistoryEntry,\n): FormattedExerciseHistoryEntry {\n\treturn {\n\t\tworkoutId: entry.workout_id,\n\t\tworkoutTitle: entry.workout_title,\n\t\tworkoutStartTime: entry.workout_start_time,\n\t\tworkoutEndTime: entry.workout_end_time,\n\t\texerciseTemplateId: entry.exercise_template_id,\n\t\tweight: entry.weight_kg,\n\t\treps: entry.reps,\n\t\tdistance: entry.distance_meters,\n\t\tduration: entry.duration_seconds,\n\t\trpe: entry.rpe,\n\t\tcustomMetric: entry.custom_metric,\n\t\tsetType: entry.set_type,\n\t};\n}\n\nexport interface FormattedBodyMeasurement {\n\tdate: string;\n\tweightKg: number | null;\n\tleanMassKg: number | null;\n\tfatPercent: number | null;\n\tneckCm: number | null;\n\tshoulderCm: number | null;\n\tchestCm: number | null;\n\tleftBicepCm: number | null;\n\trightBicepCm: number | null;\n\tleftForearmCm: number | null;\n\trightForearmCm: number | null;\n\tabdomen: number | null;\n\twaist: number | null;\n\thips: number | null;\n\tleftThigh: number | null;\n\trightThigh: number | null;\n\tleftCalf: number | null;\n\trightCalf: number | null;\n}\n\nexport function formatBodyMeasurement(\n\tmeasurement: BodyMeasurement,\n): FormattedBodyMeasurement {\n\treturn {\n\t\tdate: measurement.date,\n\t\tweightKg: measurement.weight_kg ?? null,\n\t\tleanMassKg: measurement.lean_mass_kg ?? null,\n\t\tfatPercent: measurement.fat_percent ?? null,\n\t\tneckCm: measurement.neck_cm ?? null,\n\t\tshoulderCm: measurement.shoulder_cm ?? null,\n\t\tchestCm: measurement.chest_cm ?? null,\n\t\tleftBicepCm: measurement.left_bicep_cm ?? null,\n\t\trightBicepCm: measurement.right_bicep_cm ?? null,\n\t\tleftForearmCm: measurement.left_forearm_cm ?? null,\n\t\trightForearmCm: measurement.right_forearm_cm ?? null,\n\t\tabdomen: measurement.abdomen ?? null,\n\t\twaist: measurement.waist ?? null,\n\t\thips: measurement.hips ?? null,\n\t\tleftThigh: measurement.left_thigh ?? null,\n\t\trightThigh: measurement.right_thigh ?? null,\n\t\tleftCalf: measurement.left_calf ?? null,\n\t\trightCalf: measurement.right_calf ?? null,\n\t};\n}\n","import type {\n\tCallToolResult,\n\tTextContent,\n} from \"@modelcontextprotocol/sdk/types.js\";\n\n/**\n * MCP tool response type aligned with MCP SDK CallToolResult while keeping\n * content narrowed to text blocks for this server.\n */\nexport type McpToolResponse = Omit<CallToolResult, \"content\"> & {\n\tcontent: TextContent[];\n};\n\n/**\n * Format options for JSON responses\n */\nexport interface JsonFormatOptions {\n\t/** Whether to pretty-print the JSON with indentation */\n\tpretty?: boolean;\n\t/** Indentation spaces for pretty-printing (default: 2) */\n\tindent?: number;\n}\n\n/**\n * Create a standardized success response with JSON data\n *\n * @param data - The data to include in the response\n * @param options - Formatting options\n * @returns A formatted MCP tool response with the data as JSON\n */\nexport function createJsonResponse(\n\tdata: unknown,\n\toptions: JsonFormatOptions = { pretty: true, indent: 2 },\n): McpToolResponse {\n\tconst jsonString =\n\t\t(options.pretty\n\t\t\t? JSON.stringify(data, null, options.indent)\n\t\t\t: JSON.stringify(data)) ?? \"null\";\n\n\treturn {\n\t\tcontent: [\n\t\t\t{\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: jsonString,\n\t\t\t},\n\t\t],\n\t};\n}\n\n/**\n * Create a standardized success response with text data\n *\n * @param message - The text message to include in the response\n * @returns A formatted MCP tool response with the text message\n */\nexport function createTextResponse(message: string): McpToolResponse {\n\treturn {\n\t\tcontent: [\n\t\t\t{\n\t\t\t\ttype: \"text\",\n\t\t\t\ttext: message,\n\t\t\t},\n\t\t],\n\t};\n}\n\n/**\n * Create a standardized success response for empty or null results\n *\n * @param message - Optional message to include (default: \"No data found\")\n * @returns A formatted MCP tool response for empty results\n */\nexport function createEmptyResponse(\n\tmessage = \"No data found\",\n): McpToolResponse {\n\treturn createTextResponse(message);\n}\n","/**\n * Shared MCP tool annotation factories.\n *\n * All hevy-mcp tools talk to the Hevy API, a closed, fully specified domain\n * limited to the authenticated user's own data, so openWorldHint is false\n * across the board.\n */\n\nimport type { ToolAnnotations } from \"@modelcontextprotocol/sdk/types.js\";\n\n/** Read-only tools (get-*, search-*): no side effects. */\nexport function readOnlyAnnotations(title: string): ToolAnnotations {\n\treturn { title, readOnlyHint: true, openWorldHint: false };\n}\n\n/** Create tools (create-*): additive writes, repeating creates duplicates. */\nexport function createAnnotations(title: string): ToolAnnotations {\n\treturn {\n\t\ttitle,\n\t\treadOnlyHint: false,\n\t\tdestructiveHint: false,\n\t\tidempotentHint: false,\n\t\topenWorldHint: false,\n\t};\n}\n\n/**\n * Update tools (update-*): PUT-style overwrites that replace prior data,\n * hence destructive; repeating the same call yields the same state.\n */\nexport function updateAnnotations(title: string): ToolAnnotations {\n\treturn {\n\t\ttitle,\n\t\treadOnlyHint: false,\n\t\tdestructiveHint: true,\n\t\tidempotentHint: true,\n\t\topenWorldHint: false,\n\t};\n}\n\n/** Delete tools (delete-*): destructive and idempotent. */\nexport function destructiveAnnotations(title: string): ToolAnnotations {\n\treturn {\n\t\ttitle,\n\t\treadOnlyHint: false,\n\t\tdestructiveHint: true,\n\t\tidempotentHint: true,\n\t\topenWorldHint: false,\n\t};\n}\n","/**\n * Type-safe utilities for MCP tool handlers\n */\n\nimport { z } from \"zod\";\nimport type { McpToolResponse } from \"./response-formatter.js\";\n\nexport const HEVY_CLIENT_NOT_INITIALIZED_ERROR =\n\t\"API client not initialized. Please provide HEVY_API_KEY.\";\n\n/**\n * Assert that the Hevy API client is initialized before running a tool.\n */\nexport function requireClient<TClient>(client: TClient | null): TClient {\n\tif (!client) {\n\t\tthrow new Error(HEVY_CLIENT_NOT_INITIALIZED_ERROR);\n\t}\n\n\treturn client;\n}\n\n/**\n * Infer TypeScript types from Zod schema objects\n *\n * @example\n * ```typescript\n * const schema = {\n * page: z.number(),\n * pageSize: z.number(),\n * } as const;\n *\n * type Params = InferToolParams<typeof schema>; // { page: number; pageSize: number }\n * ```\n */\nexport type InferToolParams<T extends Record<string, z.ZodTypeAny>> = z.infer<\n\tz.ZodObject<T>\n>;\n\n/**\n * Create a type-safe tool handler that validates and narrows args to inferred types\n *\n * This function wraps a handler with automatic Zod validation, ensuring runtime\n * type safety while maintaining compile-time type inference.\n *\n * @param schema - Zod schema object (e.g., { page: z.number(), ... })\n * @param handler - Handler function that receives validated, typed parameters\n * @returns A handler function that accepts Record<string, unknown> and validates it\n *\n * @example\n * ```typescript\n * const schema = {\n * page: z.coerce.number().int().gte(1).default(1),\n * pageSize: z.coerce.number().int().gte(1).lte(10).default(5),\n * } as const;\n *\n * const handler = createTypedToolHandler(schema, async (args) => {\n * // args is fully typed as { page: number; pageSize: number }\n * const { page, pageSize } = args;\n * // ...\n * });\n * ```\n */\nexport function createTypedToolHandler<T extends Record<string, z.ZodTypeAny>>(\n\tschema: T,\n\thandler: (args: InferToolParams<T>) => Promise<McpToolResponse>,\n): (args: Record<string, unknown>) => Promise<McpToolResponse> {\n\tconst zodSchema = z.object(schema);\n\treturn async (args: Record<string, unknown>) => {\n\t\tconst validated = zodSchema.parse(args);\n\t\treturn handler(validated);\n\t};\n}\n","import { z } from \"zod\";\n\nfunction coerceNullishNumberInput(value: unknown): unknown {\n\tif (value === null || value === undefined) {\n\t\treturn value;\n\t}\n\n\tif (typeof value !== \"string\") {\n\t\treturn value;\n\t}\n\n\tconst trimmed = value.trim();\n\tif (trimmed === \"\") {\n\t\treturn undefined;\n\t}\n\n\tconst lowered = trimmed.toLowerCase();\n\tif (lowered === \"null\") {\n\t\treturn null;\n\t}\n\tif (lowered === \"undefined\") {\n\t\treturn undefined;\n\t}\n\n\tconst asNumber = Number(trimmed);\n\tif (Number.isNaN(asNumber)) {\n\t\treturn value;\n\t}\n\n\treturn asNumber;\n}\n\nexport const zNullableInt = z.preprocess(\n\tcoerceNullishNumberInput,\n\tz.number().int().nullable().optional(),\n);\n\nexport const zNullableNumber = z.preprocess(\n\t(value) => (value === \"\" ? undefined : value),\n\tz.coerce.number().nullable().optional(),\n);\n\nexport const zOptionalRepRange = z.preprocess(\n\t(value) => (value === null ? undefined : value),\n\tz\n\t\t.object({\n\t\t\tstart: zNullableInt,\n\t\t\tend: zNullableInt,\n\t\t})\n\t\t.optional(),\n);\n\nconst setTypeValues = [\"warmup\", \"normal\", \"failure\", \"dropset\"] as const;\nexport const setTypeEnum = z.enum(setTypeValues).default(\"normal\");\n\nconst muscleGroupValues = [\n\t\"abdominals\",\n\t\"shoulders\",\n\t\"biceps\",\n\t\"triceps\",\n\t\"forearms\",\n\t\"quadriceps\",\n\t\"hamstrings\",\n\t\"calves\",\n\t\"glutes\",\n\t\"abductors\",\n\t\"adductors\",\n\t\"lats\",\n\t\"upper_back\",\n\t\"traps\",\n\t\"lower_back\",\n\t\"chest\",\n\t\"cardio\",\n\t\"neck\",\n\t\"full_body\",\n\t\"other\",\n] as const;\nexport const muscleGroupEnum = z.enum(muscleGroupValues);\n\nconst exerciseTypeValues = [\n\t\"weight_reps\",\n\t\"reps_only\",\n\t\"bodyweight_reps\",\n\t\"bodyweight_assisted_reps\",\n\t\"duration\",\n\t\"weight_duration\",\n\t\"distance_duration\",\n\t\"short_distance_weight\",\n] as const;\nexport const exerciseTypeEnum = z.enum(exerciseTypeValues);\n\nconst equipmentCategoryValues = [\n\t\"none\",\n\t\"barbell\",\n\t\"dumbbell\",\n\t\"kettlebell\",\n\t\"machine\",\n\t\"plate\",\n\t\"resistance_band\",\n\t\"suspension\",\n\t\"other\",\n] as const;\nexport const equipmentCategoryEnum = z.enum(equipmentCategoryValues);\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type {\n\tBodyMeasurement,\n\tGetV1BodyMeasurements200,\n\tGetV1BodyMeasurementsDate200,\n} from \"../generated/client/types/index.js\";\nimport { withErrorHandling } from \"../utils/error-handler.js\";\nimport { formatBodyMeasurement } from \"../utils/formatters.js\";\nimport {\n\tcreateEmptyResponse,\n\tcreateJsonResponse,\n\tcreateTextResponse,\n} from \"../utils/response-formatter.js\";\nimport {\n\tcreateAnnotations,\n\treadOnlyAnnotations,\n\tupdateAnnotations,\n} from \"../utils/tool-annotations.js\";\nimport { requireClient, type InferToolParams } from \"../utils/tool-helpers.js\";\nimport { zNullableNumber } from \"../utils/schemas.js\";\n\ntype HevyClient = ReturnType<\n\ttypeof import(\"../utils/hevyClientKubb.js\").createClient\n>;\n\nconst bodyMeasurementFieldsSchema = {\n\tweightKg: zNullableNumber.describe(\"Body weight in kilograms\"),\n\tleanMassKg: zNullableNumber.describe(\"Lean body mass in kilograms\"),\n\tfatPercent: zNullableNumber.describe(\"Body fat percentage\"),\n\tneckCm: zNullableNumber.describe(\"Neck circumference in centimeters\"),\n\tshoulderCm: zNullableNumber.describe(\"Shoulder circumference in centimeters\"),\n\tchestCm: zNullableNumber.describe(\"Chest circumference in centimeters\"),\n\tleftBicepCm: zNullableNumber.describe(\n\t\t\"Left bicep circumference in centimeters\",\n\t),\n\trightBicepCm: zNullableNumber.describe(\n\t\t\"Right bicep circumference in centimeters\",\n\t),\n\tleftForearmCm: zNullableNumber.describe(\n\t\t\"Left forearm circumference in centimeters\",\n\t),\n\trightForearmCm: zNullableNumber.describe(\n\t\t\"Right forearm circumference in centimeters\",\n\t),\n\tabdomen: zNullableNumber.describe(\"Abdomen circumference in centimeters\"),\n\twaist: zNullableNumber.describe(\"Waist circumference in centimeters\"),\n\thips: zNullableNumber.describe(\"Hips circumference in centimeters\"),\n\tleftThigh: zNullableNumber.describe(\n\t\t\"Left thigh circumference in centimeters\",\n\t),\n\trightThigh: zNullableNumber.describe(\n\t\t\"Right thigh circumference in centimeters\",\n\t),\n\tleftCalf: zNullableNumber.describe(\"Left calf circumference in centimeters\"),\n\trightCalf: zNullableNumber.describe(\n\t\t\"Right calf circumference in centimeters\",\n\t),\n} as const;\n\nconst MEASUREMENT_FIELD_TO_API_KEY = {\n\tweightKg: \"weight_kg\",\n\tleanMassKg: \"lean_mass_kg\",\n\tfatPercent: \"fat_percent\",\n\tneckCm: \"neck_cm\",\n\tshoulderCm: \"shoulder_cm\",\n\tchestCm: \"chest_cm\",\n\tleftBicepCm: \"left_bicep_cm\",\n\trightBicepCm: \"right_bicep_cm\",\n\tleftForearmCm: \"left_forearm_cm\",\n\trightForearmCm: \"right_forearm_cm\",\n\tabdomen: \"abdomen\",\n\twaist: \"waist\",\n\thips: \"hips\",\n\tleftThigh: \"left_thigh\",\n\trightThigh: \"right_thigh\",\n\tleftCalf: \"left_calf\",\n\trightCalf: \"right_calf\",\n} as const satisfies Record<\n\tkeyof typeof bodyMeasurementFieldsSchema,\n\tkeyof Omit<BodyMeasurement, \"date\">\n>;\n\ntype MeasurementFieldArgs = Partial<\n\tRecord<keyof typeof MEASUREMENT_FIELD_TO_API_KEY, number | null>\n>;\n\n// The Hevy API rejects null for omitted fields, so only fields with actual\n// values are included in the payload (#341).\nfunction buildMeasurementPayload(\n\targs: MeasurementFieldArgs,\n): Omit<BodyMeasurement, \"date\"> {\n\tconst payload: Omit<BodyMeasurement, \"date\"> = {};\n\tfor (const [camelKey, apiKey] of Object.entries(\n\t\tMEASUREMENT_FIELD_TO_API_KEY,\n\t) as [keyof MeasurementFieldArgs, keyof Omit<BodyMeasurement, \"date\">][]) {\n\t\tconst value = args[camelKey];\n\t\tif (value != null) {\n\t\t\tpayload[apiKey] = value;\n\t\t}\n\t}\n\treturn payload;\n}\n\nexport function registerBodyMeasurementTools(\n\tserver: McpServer,\n\thevyClient: HevyClient | null,\n) {\n\t// Get body measurements (paginated list)\n\tconst getBodyMeasurementsSchema = {\n\t\tpage: z.coerce.number().int().gte(1).default(1),\n\t\tpageSize: z.coerce.number().int().gte(1).lte(10).default(10),\n\t} as const;\n\ttype GetBodyMeasurementsParams = InferToolParams<\n\t\ttypeof getBodyMeasurementsSchema\n\t>;\n\n\tserver.tool(\n\t\t\"get-body-measurements\",\n\t\t\"Get a paginated list of body measurements for the authenticated user. Returns measurements including weight, body fat, and various circumference measurements.\",\n\t\tgetBodyMeasurementsSchema,\n\t\treadOnlyAnnotations(\"Get Body Measurements\"),\n\t\twithErrorHandling(async (args: GetBodyMeasurementsParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { page, pageSize } = args;\n\t\t\tconst data: GetV1BodyMeasurements200 = await client.getBodyMeasurements({\n\t\t\t\tpage,\n\t\t\t\tpageSize,\n\t\t\t});\n\n\t\t\tconst measurements =\n\t\t\t\tdata?.body_measurements?.map((measurement: BodyMeasurement) =>\n\t\t\t\t\tformatBodyMeasurement(measurement),\n\t\t\t\t) || [];\n\n\t\t\tif (measurements.length === 0) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"No body measurements found for the specified parameters\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createJsonResponse(measurements);\n\t\t}, \"get-body-measurements\"),\n\t);\n\n\t// Get single body measurement by date\n\tconst getBodyMeasurementSchema = {\n\t\tdate: z\n\t\t\t.string()\n\t\t\t.regex(/^\\d{4}-\\d{2}-\\d{2}$/, \"Date must be in YYYY-MM-DD format\")\n\t\t\t.describe(\"The date of the body measurement (YYYY-MM-DD)\"),\n\t} as const;\n\ttype GetBodyMeasurementParams = InferToolParams<\n\t\ttypeof getBodyMeasurementSchema\n\t>;\n\n\tserver.tool(\n\t\t\"get-body-measurement\",\n\t\t\"Get a single body measurement by date. Returns all measurement fields for the specified date.\",\n\t\tgetBodyMeasurementSchema,\n\t\treadOnlyAnnotations(\"Get Body Measurement\"),\n\t\twithErrorHandling(async (args: GetBodyMeasurementParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { date } = args;\n\t\t\tconst data: GetV1BodyMeasurementsDate200 =\n\t\t\t\tawait client.getBodyMeasurement(date);\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t`No body measurement found for date ${date}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createJsonResponse(formatBodyMeasurement(data));\n\t\t}, \"get-body-measurement\"),\n\t);\n\n\t// Create body measurement\n\tconst createBodyMeasurementSchema = {\n\t\tdate: z\n\t\t\t.string()\n\t\t\t.regex(/^\\d{4}-\\d{2}-\\d{2}$/, \"Date must be in YYYY-MM-DD format\")\n\t\t\t.describe(\n\t\t\t\t\"The date of the body measurement (YYYY-MM-DD). Must be unique — returns 409 if an entry already exists for this date.\",\n\t\t\t),\n\t\t...bodyMeasurementFieldsSchema,\n\t} as const;\n\ttype CreateBodyMeasurementParams = InferToolParams<\n\t\ttypeof createBodyMeasurementSchema\n\t>;\n\n\tserver.tool(\n\t\t\"create-body-measurement\",\n\t\t\"Create a body measurement entry for a given date. All measurement fields are optional; null values are treated as omitted, since the Hevy API does not support clearing individual fields. Returns 409 if an entry already exists for that date — use update-body-measurement instead.\",\n\t\tcreateBodyMeasurementSchema,\n\t\tcreateAnnotations(\"Create Body Measurement\"),\n\t\twithErrorHandling(async (args: CreateBodyMeasurementParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { date, ...fields } = args;\n\t\t\tawait client.createBodyMeasurement({\n\t\t\t\tdate,\n\t\t\t\t...buildMeasurementPayload(fields),\n\t\t\t});\n\n\t\t\treturn createTextResponse(\n\t\t\t\t`Body measurement for ${date} created successfully.`,\n\t\t\t);\n\t\t}, \"create-body-measurement\"),\n\t);\n\n\t// Update body measurement\n\tconst updateBodyMeasurementSchema = {\n\t\tdate: z\n\t\t\t.string()\n\t\t\t.regex(/^\\d{4}-\\d{2}-\\d{2}$/, \"Date must be in YYYY-MM-DD format\")\n\t\t\t.describe(\n\t\t\t\t\"The date of the body measurement to update (YYYY-MM-DD). Must already exist — returns 404 otherwise.\",\n\t\t\t),\n\t\t...bodyMeasurementFieldsSchema,\n\t} as const;\n\ttype UpdateBodyMeasurementParams = InferToolParams<\n\t\ttypeof updateBodyMeasurementSchema\n\t>;\n\n\tserver.tool(\n\t\t\"update-body-measurement\",\n\t\t\"Update an existing body measurement entry for a given date. Only the fields you provide are sent and updated; null values are treated as omitted, since the Hevy API does not support clearing individual fields. Requires at least one measurement field. Returns 404 if no entry exists for the date.\",\n\t\tupdateBodyMeasurementSchema,\n\t\tupdateAnnotations(\"Update Body Measurement\"),\n\t\twithErrorHandling(async (args: UpdateBodyMeasurementParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { date, ...fields } = args;\n\t\t\tconst payload = buildMeasurementPayload(fields);\n\t\t\tif (Object.keys(payload).length === 0) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"No measurement fields provided. Include at least one numeric measurement field (e.g. weightKg) to update.\",\n\t\t\t\t);\n\t\t\t}\n\t\t\tawait client.updateBodyMeasurement(date, payload);\n\n\t\t\treturn createTextResponse(\n\t\t\t\t`Body measurement for ${date} updated successfully.`,\n\t\t\t);\n\t\t}, \"update-body-measurement\"),\n\t);\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n// Import types from generated client\nimport type {\n\tGetV1RoutineFolders200,\n\tGetV1RoutineFoldersFolderid200,\n\tPostV1RoutineFolders201,\n\tRoutineFolder,\n} from \"../generated/client/types/index.js\";\nimport { withErrorHandling } from \"../utils/error-handler.js\";\nimport { formatRoutineFolder } from \"../utils/formatters.js\";\nimport {\n\tcreateEmptyResponse,\n\tcreateJsonResponse,\n} from \"../utils/response-formatter.js\";\nimport {\n\tcreateAnnotations,\n\treadOnlyAnnotations,\n} from \"../utils/tool-annotations.js\";\nimport { requireClient, type InferToolParams } from \"../utils/tool-helpers.js\";\n\n// Type definitions for the folder operations\ntype HevyClient = ReturnType<\n\ttypeof import(\"../utils/hevyClientKubb.js\").createClient\n>;\n\n/**\n * Register all routine folder-related tools with the MCP server\n */\nexport function registerFolderTools(\n\tserver: McpServer,\n\thevyClient: HevyClient | null,\n) {\n\t// Get routine folders\n\tconst getRoutineFoldersSchema = {\n\t\tpage: z.coerce.number().int().gte(1).default(1),\n\t\tpageSize: z.coerce.number().int().gte(1).lte(10).default(5),\n\t} as const;\n\ttype GetRoutineFoldersParams = InferToolParams<\n\t\ttypeof getRoutineFoldersSchema\n\t>;\n\n\tserver.tool(\n\t\t\"get-routine-folders\",\n\t\t\"Get a paginated list of your routine folders, including both default and custom folders. Useful for organizing and browsing your workout routines.\",\n\t\tgetRoutineFoldersSchema,\n\t\treadOnlyAnnotations(\"Get Routine Folders\"),\n\t\twithErrorHandling(async (args: GetRoutineFoldersParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { page, pageSize } = args;\n\t\t\tconst data: GetV1RoutineFolders200 = await client.getRoutineFolders({\n\t\t\t\tpage,\n\t\t\t\tpageSize,\n\t\t\t});\n\n\t\t\t// Process routine folders to extract relevant information\n\t\t\tconst folders =\n\t\t\t\tdata?.routine_folders?.map((folder: RoutineFolder) =>\n\t\t\t\t\tformatRoutineFolder(folder),\n\t\t\t\t) || [];\n\n\t\t\tif (folders.length === 0) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"No routine folders found for the specified parameters\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createJsonResponse(folders);\n\t\t}, \"get-routine-folders\"),\n\t);\n\n\t// Get single routine folder by ID\n\tconst getRoutineFolderSchema = {\n\t\tfolderId: z.string().min(1),\n\t} as const;\n\ttype GetRoutineFolderParams = InferToolParams<typeof getRoutineFolderSchema>;\n\n\tserver.tool(\n\t\t\"get-routine-folder\",\n\t\t\"Get complete details of a specific routine folder by its ID, including name, creation date, and associated routines.\",\n\t\tgetRoutineFolderSchema,\n\t\treadOnlyAnnotations(\"Get Routine Folder\"),\n\t\twithErrorHandling(async (args: GetRoutineFolderParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { folderId } = args;\n\t\t\tconst data: GetV1RoutineFoldersFolderid200 =\n\t\t\t\tawait client.getRoutineFolder(folderId);\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t`Routine folder with ID ${folderId} not found`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst folder = formatRoutineFolder(data);\n\t\t\treturn createJsonResponse(folder);\n\t\t}, \"get-routine-folder\"),\n\t);\n\n\t// Create new routine folder\n\tconst createRoutineFolderSchema = {\n\t\tname: z.string().min(1),\n\t} as const;\n\ttype CreateRoutineFolderParams = InferToolParams<\n\t\ttypeof createRoutineFolderSchema\n\t>;\n\n\tserver.tool(\n\t\t\"create-routine-folder\",\n\t\t\"Create a new routine folder in your Hevy account. Requires a name for the folder. Returns the full folder details including the new folder ID.\",\n\t\tcreateRoutineFolderSchema,\n\t\tcreateAnnotations(\"Create Routine Folder\"),\n\t\twithErrorHandling(async (args: CreateRoutineFolderParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { name } = args;\n\t\t\tconst data: PostV1RoutineFolders201 = await client.createRoutineFolder({\n\t\t\t\troutine_folder: {\n\t\t\t\t\ttitle: name,\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"Failed to create routine folder: Server returned no data\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst folder = formatRoutineFolder(data);\n\t\t\treturn createJsonResponse(folder, {\n\t\t\t\tpretty: true,\n\t\t\t\tindent: 2,\n\t\t\t});\n\t\t}, \"create-routine-folder\"),\n\t);\n}\n","/**\n * Preprocessor to handle MCP clients that send JSON-stringified arrays\n * instead of native arrays for complex parameters.\n *\n * This is used with Zod's z.preprocess to handle cases where MCP clients\n * serialize complex nested structures as JSON strings.\n *\n * @param val - The value to potentially parse\n * @returns The parsed array if val is a valid JSON string, otherwise returns val unchanged\n */\nexport function parseJsonArray(val: unknown): unknown {\n\t// Handle case where MCP client sends JSON string instead of array\n\tif (typeof val === \"string\") {\n\t\ttry {\n\t\t\treturn JSON.parse(val);\n\t\t} catch {\n\t\t\t// Let Zod validation handle the error\n\t\t\treturn val;\n\t\t}\n\t}\n\treturn val;\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n// Import types from generated client\nimport type {\n\tGetV1Routines200,\n\tGetV1RoutinesRoutineid200,\n\tPostRoutinesRequestExercise,\n\tPostRoutinesRequestSet,\n\tPostRoutinesRequestSetTypeEnumKey,\n\tPostV1Routines201,\n\tPutRoutinesRequestExercise,\n\tPutRoutinesRequestSet,\n\tPutRoutinesRequestSetTypeEnumKey,\n\tPutV1RoutinesRoutineid200,\n\tRoutine,\n} from \"../generated/client/types/index.js\";\nimport { withErrorHandling } from \"../utils/error-handler.js\";\nimport { formatRoutine } from \"../utils/formatters.js\";\nimport { parseJsonArray } from \"../utils/json-parser.js\";\nimport {\n\tcreateEmptyResponse,\n\tcreateJsonResponse,\n} from \"../utils/response-formatter.js\";\nimport {\n\tcreateAnnotations,\n\treadOnlyAnnotations,\n\tupdateAnnotations,\n} from \"../utils/tool-annotations.js\";\nimport { requireClient, type InferToolParams } from \"../utils/tool-helpers.js\";\nimport {\n\tsetTypeEnum,\n\tzNullableInt,\n\tzOptionalRepRange,\n} from \"../utils/schemas.js\";\n\n// Type definitions for the routine operations\ntype HevyClient = ReturnType<\n\ttypeof import(\"../utils/hevyClientKubb.js\").createClient\n>;\n\nfunction buildRepRange(repRange?: {\n\tstart?: number | null;\n\tend?: number | null;\n}): { start?: number; end?: number } | null {\n\tif (!repRange) {\n\t\treturn null;\n\t}\n\n\tconst start = repRange.start ?? undefined;\n\tconst end = repRange.end ?? undefined;\n\tif (start === undefined && end === undefined) {\n\t\treturn null;\n\t}\n\n\treturn { start, end };\n}\n\n/**\n * Returns a fixed rep count when `repRange` is a fixed range (start and end are\n * both non-null and equal). Otherwise returns null.\n */\nfunction getFixedRepsFromRepRange(\n\trepRange:\n\t\t| {\n\t\t\t\tstart?: number | null;\n\t\t\t\tend?: number | null;\n\t\t }\n\t\t| null\n\t\t| undefined,\n): number | null {\n\tif (!repRange) {\n\t\treturn null;\n\t}\n\n\tconst start = repRange.start ?? null;\n\tconst end = repRange.end ?? null;\n\tif (start === null || end === null) {\n\t\treturn null;\n\t}\n\tif (start !== end) {\n\t\treturn null;\n\t}\n\n\treturn start;\n}\n\nconst repRangeDisplayWarningText =\n\t\"Note: Hevy's public API stores rep ranges (rep_range), but the Hevy apps may \" +\n\t\"not display them because they rely on an internal-only exercise field \" +\n\t\"(input_modifier). See https://github.com/chrisdoc/hevy-mcp/issues/261 for \" +\n\t\"details/workarounds.\";\n\n/**\n * Register all routine-related tools with the MCP server\n */\nexport function registerRoutineTools(\n\tserver: McpServer,\n\thevyClient: HevyClient | null,\n) {\n\t// Get routines\n\tconst getRoutinesSchema = {\n\t\tpage: z.coerce.number().int().gte(1).default(1),\n\t\tpageSize: z.coerce.number().int().gte(1).lte(10).default(5),\n\t} as const;\n\ttype GetRoutinesParams = InferToolParams<typeof getRoutinesSchema>;\n\n\tserver.tool(\n\t\t\"get-routines\",\n\t\t\"Get a paginated list of your workout routines, including custom and default routines. Useful for browsing or searching your available routines.\",\n\t\tgetRoutinesSchema,\n\t\treadOnlyAnnotations(\"Get Routines\"),\n\t\twithErrorHandling(async (args: GetRoutinesParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { page, pageSize } = args;\n\t\t\tconst data: GetV1Routines200 = await client.getRoutines({\n\t\t\t\tpage,\n\t\t\t\tpageSize,\n\t\t\t});\n\n\t\t\t// Process routines to extract relevant information\n\t\t\tconst routines =\n\t\t\t\tdata?.routines?.map((routine: Routine) => formatRoutine(routine)) || [];\n\n\t\t\tif (routines.length === 0) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"No routines found for the specified parameters\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createJsonResponse(routines);\n\t\t}, \"get-routines\"),\n\t);\n\n\t// Get single routine by ID (new, direct endpoint)\n\tconst getRoutineSchema = {\n\t\troutineId: z.string().min(1),\n\t} as const;\n\ttype GetRoutineParams = InferToolParams<typeof getRoutineSchema>;\n\n\tserver.tool(\n\t\t\"get-routine\",\n\t\t\"Get a routine by its ID using the direct endpoint. Returns all details for the specified routine.\",\n\t\tgetRoutineSchema,\n\t\treadOnlyAnnotations(\"Get Routine\"),\n\t\twithErrorHandling(async (args: GetRoutineParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { routineId } = args;\n\t\t\tconst data: GetV1RoutinesRoutineid200 = await client.getRoutineById(\n\t\t\t\tString(routineId),\n\t\t\t);\n\t\t\tif (!data || !data.routine) {\n\t\t\t\treturn createEmptyResponse(`Routine with ID ${routineId} not found`);\n\t\t\t}\n\t\t\tconst routine = formatRoutine(data.routine);\n\t\t\treturn createJsonResponse(routine);\n\t\t}, \"get-routine\"),\n\t);\n\n\t// Create new routine\n\tconst createRoutineSchema = {\n\t\ttitle: z.string().min(1),\n\t\tfolderId: z.coerce.number().nullable().optional(),\n\t\tnotes: z.string().optional(),\n\t\texercises: z.preprocess(\n\t\t\tparseJsonArray,\n\t\t\tz.array(\n\t\t\t\tz.object({\n\t\t\t\t\texerciseTemplateId: z.string().min(1),\n\t\t\t\t\tsupersetId: z.coerce.number().nullable().optional(),\n\t\t\t\t\trestSeconds: z.coerce.number().int().min(0).optional(),\n\t\t\t\t\tnotes: z.string().optional(),\n\t\t\t\t\tsets: z.array(\n\t\t\t\t\t\tz.object({\n\t\t\t\t\t\t\ttype: setTypeEnum,\n\t\t\t\t\t\t\tweight: z.coerce.number().optional(),\n\t\t\t\t\t\t\tweightKg: z.coerce.number().optional(),\n\t\t\t\t\t\t\treps: zNullableInt,\n\t\t\t\t\t\t\tdistance: z.coerce.number().int().optional(),\n\t\t\t\t\t\t\tdistanceMeters: z.coerce.number().int().optional(),\n\t\t\t\t\t\t\tduration: z.coerce.number().int().optional(),\n\t\t\t\t\t\t\tdurationSeconds: z.coerce.number().int().optional(),\n\t\t\t\t\t\t\tcustomMetric: z.coerce.number().optional(),\n\t\t\t\t\t\t\trepRange: zOptionalRepRange,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t),\n\t\t),\n\t} as const;\n\ttype CreateRoutineParams = InferToolParams<typeof createRoutineSchema>;\n\n\tserver.tool(\n\t\t\"create-routine\",\n\t\t\"Create a new workout routine in your Hevy account. Requires a title and at least one exercise with sets. Optionally assign to a folder. Returns the full routine details including the new routine ID.\",\n\t\tcreateRoutineSchema,\n\t\tcreateAnnotations(\"Create Routine\"),\n\t\twithErrorHandling(async (args: CreateRoutineParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { title, folderId, notes, exercises } = args;\n\t\t\tlet usesRepRanges = false;\n\t\t\tconst data: PostV1Routines201 = await client.createRoutine({\n\t\t\t\troutine: {\n\t\t\t\t\ttitle,\n\t\t\t\t\tfolder_id: folderId ?? null,\n\t\t\t\t\tnotes: notes ?? \"\",\n\t\t\t\t\texercises: exercises.map((exercise): PostRoutinesRequestExercise => {\n\t\t\t\t\t\tconst sets = exercise.sets.map((set): PostRoutinesRequestSet => {\n\t\t\t\t\t\t\tconst repRange = buildRepRange(set.repRange);\n\t\t\t\t\t\t\tconst fixedReps = getFixedRepsFromRepRange(repRange);\n\t\t\t\t\t\t\tconst reps = typeof set.reps === \"number\" ? set.reps : fixedReps;\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\ttype: set.type as PostRoutinesRequestSetTypeEnumKey,\n\t\t\t\t\t\t\t\tweight_kg: set.weight ?? set.weightKg ?? null,\n\t\t\t\t\t\t\t\treps: reps ?? null,\n\t\t\t\t\t\t\t\tdistance_meters: set.distance ?? set.distanceMeters ?? null,\n\t\t\t\t\t\t\t\tduration_seconds: set.duration ?? set.durationSeconds ?? null,\n\t\t\t\t\t\t\t\tcustom_metric: set.customMetric ?? null,\n\t\t\t\t\t\t\t\trep_range: repRange,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t});\n\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\tsets.some(\n\t\t\t\t\t\t\t\t(set) =>\n\t\t\t\t\t\t\t\t\tset.rep_range != null &&\n\t\t\t\t\t\t\t\t\tgetFixedRepsFromRepRange(set.rep_range) === null,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tusesRepRanges = true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\texercise_template_id: exercise.exerciseTemplateId,\n\t\t\t\t\t\t\tsuperset_id: exercise.supersetId ?? null,\n\t\t\t\t\t\t\trest_seconds: exercise.restSeconds ?? null,\n\t\t\t\t\t\t\tnotes: exercise.notes ?? null,\n\t\t\t\t\t\t\tsets,\n\t\t\t\t\t\t};\n\t\t\t\t\t}),\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"Failed to create routine: Server returned no data\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst routine = formatRoutine(data);\n\t\t\tconst response = createJsonResponse(routine, {\n\t\t\t\tpretty: true,\n\t\t\t\tindent: 2,\n\t\t\t});\n\n\t\t\tif (usesRepRanges) {\n\t\t\t\tresponse.content.push({\n\t\t\t\t\ttype: \"text\",\n\t\t\t\t\ttext: repRangeDisplayWarningText,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn response;\n\t\t}, \"create-routine\"),\n\t);\n\n\t// Update existing routine\n\tconst updateRoutineSchema = {\n\t\troutineId: z.string().min(1),\n\t\ttitle: z.string().min(1),\n\t\tnotes: z.string().optional(),\n\t\texercises: z.preprocess(\n\t\t\tparseJsonArray,\n\t\t\tz.array(\n\t\t\t\tz.object({\n\t\t\t\t\texerciseTemplateId: z.string().min(1),\n\t\t\t\t\tsupersetId: z.coerce.number().nullable().optional(),\n\t\t\t\t\trestSeconds: z.coerce.number().int().min(0).optional(),\n\t\t\t\t\tnotes: z.string().optional(),\n\t\t\t\t\tsets: z.array(\n\t\t\t\t\t\tz.object({\n\t\t\t\t\t\t\ttype: setTypeEnum,\n\t\t\t\t\t\t\tweight: z.coerce.number().optional(),\n\t\t\t\t\t\t\tweightKg: z.coerce.number().optional(),\n\t\t\t\t\t\t\treps: zNullableInt,\n\t\t\t\t\t\t\tdistance: z.coerce.number().int().optional(),\n\t\t\t\t\t\t\tdistanceMeters: z.coerce.number().int().optional(),\n\t\t\t\t\t\t\tduration: z.coerce.number().int().optional(),\n\t\t\t\t\t\t\tdurationSeconds: z.coerce.number().int().optional(),\n\t\t\t\t\t\t\tcustomMetric: z.coerce.number().optional(),\n\t\t\t\t\t\t\trepRange: zOptionalRepRange,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t),\n\t\t),\n\t} as const;\n\ttype UpdateRoutineParams = InferToolParams<typeof updateRoutineSchema>;\n\n\tserver.tool(\n\t\t\"update-routine\",\n\t\t\"Update an existing routine by ID. You can modify the title, notes, and exercise configurations. Returns the updated routine with all changes applied.\",\n\t\tupdateRoutineSchema,\n\t\tupdateAnnotations(\"Update Routine\"),\n\t\twithErrorHandling(async (args: UpdateRoutineParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { routineId, title, notes, exercises } = args;\n\t\t\tlet usesRepRanges = false;\n\t\t\tconst data: PutV1RoutinesRoutineid200 = await client.updateRoutine(\n\t\t\t\troutineId,\n\t\t\t\t{\n\t\t\t\t\troutine: {\n\t\t\t\t\t\ttitle,\n\t\t\t\t\t\tnotes: notes ?? null,\n\t\t\t\t\t\texercises: exercises.map((exercise): PutRoutinesRequestExercise => {\n\t\t\t\t\t\t\tconst sets = exercise.sets.map((set): PutRoutinesRequestSet => {\n\t\t\t\t\t\t\t\tconst repRange = buildRepRange(set.repRange);\n\t\t\t\t\t\t\t\tconst fixedReps = getFixedRepsFromRepRange(repRange);\n\t\t\t\t\t\t\t\tconst reps =\n\t\t\t\t\t\t\t\t\ttypeof set.reps === \"number\" ? set.reps : fixedReps;\n\t\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\t\ttype: set.type as PutRoutinesRequestSetTypeEnumKey,\n\t\t\t\t\t\t\t\t\tweight_kg: set.weight ?? set.weightKg ?? null,\n\t\t\t\t\t\t\t\t\treps: reps ?? null,\n\t\t\t\t\t\t\t\t\tdistance_meters: set.distance ?? set.distanceMeters ?? null,\n\t\t\t\t\t\t\t\t\tduration_seconds: set.duration ?? set.durationSeconds ?? null,\n\t\t\t\t\t\t\t\t\tcustom_metric: set.customMetric ?? null,\n\t\t\t\t\t\t\t\t\t...(repRange ? { rep_range: repRange } : {}),\n\t\t\t\t\t\t\t\t};\n\t\t\t\t\t\t\t});\n\n\t\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t\tsets.some(\n\t\t\t\t\t\t\t\t\t(set) =>\n\t\t\t\t\t\t\t\t\t\tset.rep_range != null &&\n\t\t\t\t\t\t\t\t\t\tgetFixedRepsFromRepRange(set.rep_range) === null,\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t) {\n\t\t\t\t\t\t\t\tusesRepRanges = true;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn {\n\t\t\t\t\t\t\t\texercise_template_id: exercise.exerciseTemplateId,\n\t\t\t\t\t\t\t\tsuperset_id: exercise.supersetId ?? null,\n\t\t\t\t\t\t\t\trest_seconds: exercise.restSeconds ?? null,\n\t\t\t\t\t\t\t\tnotes: exercise.notes ?? null,\n\t\t\t\t\t\t\t\tsets,\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t}),\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t`Failed to update routine with ID ${routineId}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst routine = formatRoutine(data);\n\t\t\tconst response = createJsonResponse(routine, {\n\t\t\t\tpretty: true,\n\t\t\t\tindent: 2,\n\t\t\t});\n\n\t\t\tif (usesRepRanges) {\n\t\t\t\tresponse.content.push({\n\t\t\t\t\ttype: \"text\",\n\t\t\t\t\ttext: repRangeDisplayWarningText,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn response;\n\t\t}, \"update-routine\"),\n\t);\n}\n","export interface AsyncCacheOptions {\n\tttlMs: number;\n\tmaxSize: number;\n}\n\nexport interface CacheGetOptions {\n\trefresh?: boolean;\n}\n\ninterface CacheEntry<TValue> {\n\tvalue: TValue;\n\texpiresAt: number;\n}\n\ninterface InFlightEntry<TValue> {\n\tpromise: Promise<TValue>;\n\trequestId: number;\n}\n\n/**\n * Shared in-memory cache for async fetches with TTL, LRU eviction,\n * in-flight de-duplication, and explicit refresh/invalidation support.\n */\nexport class AsyncTtlCache<TKey, TValue> {\n\tprivate readonly ttlMs: number;\n\tprivate readonly maxSize: number;\n\tprivate readonly now: () => number;\n\tprivate readonly entries = new Map<TKey, CacheEntry<TValue>>();\n\tprivate readonly inFlight = new Map<TKey, InFlightEntry<TValue>>();\n\tprivate requestCounter = 0;\n\n\tconstructor(options: AsyncCacheOptions, now: () => number = Date.now) {\n\t\tconst { ttlMs, maxSize } = options;\n\t\tif (ttlMs <= 0) {\n\t\t\tthrow new Error(\"Cache ttlMs must be greater than 0.\");\n\t\t}\n\t\tif (maxSize <= 0) {\n\t\t\tthrow new Error(\"Cache maxSize must be greater than 0.\");\n\t\t}\n\n\t\tthis.ttlMs = ttlMs;\n\t\tthis.maxSize = maxSize;\n\t\tthis.now = now;\n\t}\n\n\tasync getOrFetch(\n\t\tkey: TKey,\n\t\tfetcher: () => Promise<TValue>,\n\t\toptions: CacheGetOptions = {},\n\t): Promise<TValue> {\n\t\tconst { refresh = false } = options;\n\n\t\tif (refresh) {\n\t\t\tthis.invalidate(key);\n\t\t} else {\n\t\t\tconst cachedEntry = this.entries.get(key);\n\t\t\tif (cachedEntry !== undefined) {\n\t\t\t\tif (cachedEntry.expiresAt > this.now()) {\n\t\t\t\t\tthis.markAsRecentlyUsed(key, cachedEntry);\n\t\t\t\t\treturn cachedEntry.value;\n\t\t\t\t}\n\n\t\t\t\tthis.entries.delete(key);\n\t\t\t}\n\n\t\t\tconst inFlightEntry = this.inFlight.get(key);\n\t\t\tif (inFlightEntry !== undefined) {\n\t\t\t\treturn inFlightEntry.promise;\n\t\t\t}\n\t\t}\n\n\t\tconst requestId = ++this.requestCounter;\n\t\tconst request = (async () => {\n\t\t\ttry {\n\t\t\t\tconst value = await fetcher();\n\n\t\t\t\tif (this.isCurrentRequest(key, requestId)) {\n\t\t\t\t\tthis.setValue(key, value);\n\t\t\t\t}\n\n\t\t\t\treturn value;\n\t\t\t} finally {\n\t\t\t\tconst inFlightEntry = this.inFlight.get(key);\n\t\t\t\tif (inFlightEntry?.requestId === requestId) {\n\t\t\t\t\tthis.inFlight.delete(key);\n\t\t\t\t}\n\t\t\t}\n\t\t})();\n\n\t\tthis.inFlight.set(key, { promise: request, requestId });\n\t\treturn request;\n\t}\n\n\tinvalidate(key: TKey): void {\n\t\tthis.entries.delete(key);\n\t\tthis.inFlight.delete(key);\n\t}\n\n\tclear(): void {\n\t\tthis.entries.clear();\n\t\tthis.inFlight.clear();\n\t}\n\n\tget size(): number {\n\t\treturn this.entries.size;\n\t}\n\n\tprivate isCurrentRequest(key: TKey, requestId: number): boolean {\n\t\treturn this.inFlight.get(key)?.requestId === requestId;\n\t}\n\n\tprivate markAsRecentlyUsed(key: TKey, entry: CacheEntry<TValue>): void {\n\t\tthis.entries.delete(key);\n\t\tthis.entries.set(key, entry);\n\t}\n\n\tprivate setValue(key: TKey, value: TValue): void {\n\t\tthis.entries.delete(key);\n\t\tthis.entries.set(key, {\n\t\t\tvalue,\n\t\t\texpiresAt: this.now() + this.ttlMs,\n\t\t});\n\n\t\tthis.evictLeastRecentlyUsed();\n\t}\n\n\tprivate evictLeastRecentlyUsed(): void {\n\t\twhile (this.entries.size > this.maxSize) {\n\t\t\tconst oldestKey = this.entries.keys().next().value;\n\t\t\tif (oldestKey === undefined) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tthis.entries.delete(oldestKey);\n\t\t}\n\t}\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\n// Import types from generated client\nimport type {\n\tExerciseTemplate,\n\tGetV1ExerciseHistoryExercisetemplateid200,\n\tGetV1ExerciseTemplates200,\n\tGetV1ExerciseTemplatesExercisetemplateid200,\n\tPostV1ExerciseTemplates200,\n} from \"../generated/client/types/index.js\";\nimport { AsyncTtlCache } from \"../utils/cache.js\";\nimport { withErrorHandling } from \"../utils/error-handler.js\";\nimport {\n\tformatExerciseHistoryEntry,\n\tformatExerciseTemplate,\n} from \"../utils/formatters.js\";\nimport {\n\tcreateEmptyResponse,\n\tcreateJsonResponse,\n} from \"../utils/response-formatter.js\";\nimport {\n\tcreateAnnotations,\n\treadOnlyAnnotations,\n} from \"../utils/tool-annotations.js\";\nimport { requireClient, type InferToolParams } from \"../utils/tool-helpers.js\";\nimport {\n\tequipmentCategoryEnum,\n\texerciseTypeEnum,\n\tmuscleGroupEnum,\n} from \"../utils/schemas.js\";\n\n// Type definitions for the template operations\ntype HevyClient = ReturnType<\n\ttypeof import(\"../utils/hevyClientKubb.js\").createClient\n>;\n\nconst EXERCISE_TEMPLATE_CATALOG_CACHE_KEY = \"exercise-template-catalog\";\nconst EXERCISE_TEMPLATE_CATALOG_CACHE_TTL_MS = 5 * 60 * 1000;\nconst EXERCISE_TEMPLATE_CATALOG_CACHE_MAX_SIZE = 1;\n\nconst exerciseTemplateCatalogCache = new AsyncTtlCache<\n\tstring,\n\tExerciseTemplate[]\n>({\n\tttlMs: EXERCISE_TEMPLATE_CATALOG_CACHE_TTL_MS,\n\tmaxSize: EXERCISE_TEMPLATE_CATALOG_CACHE_MAX_SIZE,\n});\n\nasync function fetchExerciseTemplateCatalog(\n\thevyClient: HevyClient,\n): Promise<ExerciseTemplate[]> {\n\tconst allTemplates: ExerciseTemplate[] = [];\n\tlet page = 1;\n\tlet pageCount = 1;\n\n\tdo {\n\t\tconst data: GetV1ExerciseTemplates200 =\n\t\t\tawait hevyClient.getExerciseTemplates({\n\t\t\t\tpage,\n\t\t\t\tpageSize: 100,\n\t\t\t});\n\n\t\tconst templates = data?.exercise_templates ?? [];\n\t\tallTemplates.push(...templates);\n\t\tpageCount = data?.page_count ?? 1;\n\t\tpage++;\n\t} while (page <= pageCount);\n\n\treturn allTemplates;\n}\n\n/** Reset the exercise template cache (exposed for testing). */\nexport function resetExerciseTemplateCache(): void {\n\texerciseTemplateCatalogCache.clear();\n}\n\n/**\n * Register all exercise template-related tools with the MCP server\n */\nexport function registerTemplateTools(\n\tserver: McpServer,\n\thevyClient: HevyClient | null,\n) {\n\t// Get exercise templates\n\tconst getExerciseTemplatesSchema = {\n\t\tpage: z.coerce.number().int().gte(1).default(1),\n\t\tpageSize: z.coerce.number().int().gte(1).lte(100).default(5),\n\t} as const;\n\ttype GetExerciseTemplatesParams = InferToolParams<\n\t\ttypeof getExerciseTemplatesSchema\n\t>;\n\n\tserver.tool(\n\t\t\"get-exercise-templates\",\n\t\t\"Get a paginated list of exercise templates (default and custom) with details like name, category, equipment, and muscle groups. Useful for browsing or searching available exercises.\",\n\t\tgetExerciseTemplatesSchema,\n\t\treadOnlyAnnotations(\"Get Exercise Templates\"),\n\t\twithErrorHandling(async (args: GetExerciseTemplatesParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { page, pageSize } = args;\n\t\t\tconst data: GetV1ExerciseTemplates200 = await client.getExerciseTemplates(\n\t\t\t\t{\n\t\t\t\t\tpage,\n\t\t\t\t\tpageSize,\n\t\t\t\t},\n\t\t\t);\n\n\t\t\t// Process exercise templates to extract relevant information\n\t\t\tconst templates =\n\t\t\t\tdata?.exercise_templates?.map((template: ExerciseTemplate) =>\n\t\t\t\t\tformatExerciseTemplate(template),\n\t\t\t\t) || [];\n\n\t\t\tif (templates.length === 0) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"No exercise templates found for the specified parameters\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createJsonResponse(templates);\n\t\t}, \"get-exercise-templates\"),\n\t);\n\n\t// Get single exercise template by ID\n\tconst getExerciseTemplateSchema = {\n\t\texerciseTemplateId: z.string().min(1),\n\t} as const;\n\ttype GetExerciseTemplateParams = InferToolParams<\n\t\ttypeof getExerciseTemplateSchema\n\t>;\n\n\tserver.tool(\n\t\t\"get-exercise-template\",\n\t\t\"Get complete details of a specific exercise template by its ID, including name, category, equipment, muscle groups, and notes.\",\n\t\tgetExerciseTemplateSchema,\n\t\treadOnlyAnnotations(\"Get Exercise Template\"),\n\t\twithErrorHandling(async (args: GetExerciseTemplateParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { exerciseTemplateId } = args;\n\t\t\tconst data: GetV1ExerciseTemplatesExercisetemplateid200 =\n\t\t\t\tawait client.getExerciseTemplate(exerciseTemplateId);\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t`Exercise template with ID ${exerciseTemplateId} not found`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst template = formatExerciseTemplate(data);\n\t\t\treturn createJsonResponse(template);\n\t\t}, \"get-exercise-template\"),\n\t);\n\n\t// Get exercise history for a template\n\tconst getExerciseHistorySchema = {\n\t\texerciseTemplateId: z.string().min(1),\n\t\tstartDate: z\n\t\t\t.string()\n\t\t\t.datetime({ offset: true })\n\t\t\t.describe(\"ISO 8601 start date for filtering history\")\n\t\t\t.optional(),\n\t\tendDate: z\n\t\t\t.string()\n\t\t\t.datetime({ offset: true })\n\t\t\t.describe(\"ISO 8601 end date for filtering history\")\n\t\t\t.optional(),\n\t} as const;\n\ttype GetExerciseHistoryParams = InferToolParams<\n\t\ttypeof getExerciseHistorySchema\n\t>;\n\n\tserver.tool(\n\t\t\"get-exercise-history\",\n\t\t\"Get past sets for a specific exercise template, optionally filtered by start and end dates.\",\n\t\tgetExerciseHistorySchema,\n\t\treadOnlyAnnotations(\"Get Exercise History\"),\n\t\twithErrorHandling(async (args: GetExerciseHistoryParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { exerciseTemplateId, startDate, endDate } = args;\n\t\t\tconst data: GetV1ExerciseHistoryExercisetemplateid200 =\n\t\t\t\tawait client.getExerciseHistory(exerciseTemplateId, {\n\t\t\t\t\t...(startDate ? { start_date: startDate } : {}),\n\t\t\t\t\t...(endDate ? { end_date: endDate } : {}),\n\t\t\t\t});\n\n\t\t\tconst history =\n\t\t\t\tdata?.exercise_history?.map((entry) =>\n\t\t\t\t\tformatExerciseHistoryEntry(entry),\n\t\t\t\t) || [];\n\n\t\t\tif (history.length === 0) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t`No exercise history found for template ${exerciseTemplateId}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createJsonResponse(history);\n\t\t}, \"get-exercise-history\"),\n\t);\n\n\t// Create a custom exercise template\n\tconst createExerciseTemplateSchema = {\n\t\ttitle: z.string().min(1),\n\t\texerciseType: exerciseTypeEnum,\n\t\tequipmentCategory: equipmentCategoryEnum,\n\t\tmuscleGroup: muscleGroupEnum,\n\t\totherMuscles: z.array(muscleGroupEnum).default([]),\n\t} as const;\n\ttype CreateExerciseTemplateParams = InferToolParams<\n\t\ttypeof createExerciseTemplateSchema\n\t>;\n\n\tserver.tool(\n\t\t\"create-exercise-template\",\n\t\t\"Create a custom exercise template with title, type, equipment, and muscle groups.\",\n\t\tcreateExerciseTemplateSchema,\n\t\tcreateAnnotations(\"Create Exercise Template\"),\n\t\twithErrorHandling(async (args: CreateExerciseTemplateParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst {\n\t\t\t\ttitle,\n\t\t\t\texerciseType,\n\t\t\t\tequipmentCategory,\n\t\t\t\tmuscleGroup,\n\t\t\t\totherMuscles,\n\t\t\t} = args;\n\n\t\t\tconst response: PostV1ExerciseTemplates200 =\n\t\t\t\tawait client.createExerciseTemplate({\n\t\t\t\t\texercise: {\n\t\t\t\t\t\ttitle,\n\t\t\t\t\t\texercise_type: exerciseType,\n\t\t\t\t\t\tequipment_category: equipmentCategory,\n\t\t\t\t\t\tmuscle_group: muscleGroup,\n\t\t\t\t\t\tother_muscles: otherMuscles,\n\t\t\t\t\t},\n\t\t\t\t});\n\n\t\t\treturn createJsonResponse({\n\t\t\t\tid: response?.id,\n\t\t\t\tmessage: \"Exercise template created successfully\",\n\t\t\t});\n\t\t}, \"create-exercise-template\"),\n\t);\n\n\t// Search exercise templates (cached)\n\tconst searchExerciseTemplatesSchema = {\n\t\tquery: z\n\t\t\t.string()\n\t\t\t.min(1)\n\t\t\t.describe(\n\t\t\t\t\"Case-insensitive substring to match against exercise template titles\",\n\t\t\t),\n\t\tprimaryMuscleGroup: muscleGroupEnum\n\t\t\t.optional()\n\t\t\t.describe(\n\t\t\t\t\"Optional filter to restrict results to a specific primary muscle group\",\n\t\t\t),\n\t\trefresh: z\n\t\t\t.boolean()\n\t\t\t.optional()\n\t\t\t.default(false)\n\t\t\t.describe(\n\t\t\t\t\"Set to true to invalidate the catalog cache and re-fetch all templates from the API\",\n\t\t\t),\n\t} as const;\n\ttype SearchExerciseTemplatesParams = InferToolParams<\n\t\ttypeof searchExerciseTemplatesSchema\n\t>;\n\n\tserver.tool(\n\t\t\"search-exercise-templates\",\n\t\t\"Search exercise templates by name with optional muscle group filter. Fetches all templates from the Hevy API on first call, caches the catalog in memory with a bounded TTL cache, and reuses it for subsequent searches. Use refresh:true to force a re-fetch.\",\n\t\tsearchExerciseTemplatesSchema,\n\t\treadOnlyAnnotations(\"Search Exercise Templates\"),\n\t\twithErrorHandling(async (args: SearchExerciseTemplatesParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { query, primaryMuscleGroup, refresh } = args;\n\t\t\tconst catalog = await exerciseTemplateCatalogCache.getOrFetch(\n\t\t\t\tEXERCISE_TEMPLATE_CATALOG_CACHE_KEY,\n\t\t\t\t() => fetchExerciseTemplateCatalog(client),\n\t\t\t\t{ refresh },\n\t\t\t);\n\n\t\t\t// Filter by query (case-insensitive title substring match)\n\t\t\tconst queryLower = query.toLowerCase();\n\t\t\tlet results = catalog.filter((t) =>\n\t\t\t\t(t.title ?? \"\").toLowerCase().includes(queryLower),\n\t\t\t);\n\n\t\t\t// Optional primary muscle group filter\n\t\t\tif (primaryMuscleGroup !== undefined) {\n\t\t\t\tresults = results.filter(\n\t\t\t\t\t(t) => t.primary_muscle_group === primaryMuscleGroup,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (results.length === 0) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t`No exercise templates found matching \"${query}\"${primaryMuscleGroup ? ` with primary muscle group \"${primaryMuscleGroup}\"` : \"\"}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createJsonResponse(results.map(formatExerciseTemplate));\n\t\t}, \"search-exercise-templates\"),\n\t);\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport type { UserInfoResponse } from \"../generated/client/types/index.js\";\nimport { withErrorHandling } from \"../utils/error-handler.js\";\nimport {\n\tcreateEmptyResponse,\n\tcreateJsonResponse,\n} from \"../utils/response-formatter.js\";\nimport { readOnlyAnnotations } from \"../utils/tool-annotations.js\";\nimport { requireClient, type InferToolParams } from \"../utils/tool-helpers.js\";\n\ntype HevyClient = ReturnType<\n\ttypeof import(\"../utils/hevyClientKubb.js\").createClient\n>;\n\nexport function registerUserTools(\n\tserver: McpServer,\n\thevyClient: HevyClient | null,\n) {\n\t// Get user info\n\tconst getUserInfoSchema = {} as const;\n\ttype GetUserInfoParams = InferToolParams<typeof getUserInfoSchema>;\n\n\tserver.tool(\n\t\t\"get-user-info\",\n\t\t\"Get the authenticated user's account info, including user ID, display name, and public profile URL. Useful for verifying which account the API key belongs to.\",\n\t\tgetUserInfoSchema,\n\t\treadOnlyAnnotations(\"Get User Info\"),\n\t\twithErrorHandling(async (_args: GetUserInfoParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst data: UserInfoResponse = await client.getUserInfo();\n\t\t\tif (!data?.data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"No user info found for the authenticated user\",\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn createJsonResponse(data.data);\n\t\t}, \"get-user-info\"),\n\t);\n}\n","import type { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { z } from \"zod\";\nimport type {\n\tGetV1Workouts200,\n\tGetV1WorkoutsCount200,\n\tGetV1WorkoutsEvents200,\n\tGetV1WorkoutsWorkoutid200,\n\tPostV1Workouts201,\n\tPostWorkoutsRequestBody,\n\tPostWorkoutsRequestExercise,\n\tPostWorkoutsRequestSetRpeEnumKey,\n\tPostWorkoutsRequestSetTypeEnumKey,\n\tPutV1WorkoutsWorkoutid200,\n} from \"../generated/client/types/index.js\";\nimport { withErrorHandling } from \"../utils/error-handler.js\";\nimport { formatWorkout } from \"../utils/formatters.js\";\nimport type { HevyClient } from \"../utils/hevyClient.js\";\nimport { parseJsonArray } from \"../utils/json-parser.js\";\nimport {\n\tcreateEmptyResponse,\n\tcreateJsonResponse,\n} from \"../utils/response-formatter.js\";\nimport {\n\tcreateAnnotations,\n\treadOnlyAnnotations,\n\tupdateAnnotations,\n} from \"../utils/tool-annotations.js\";\nimport { requireClient, type InferToolParams } from \"../utils/tool-helpers.js\";\nimport { setTypeEnum } from \"../utils/schemas.js\";\n\n/**\n * Register all workout-related tools with the MCP server\n */\nexport function registerWorkoutTools(\n\tserver: McpServer,\n\thevyClient: HevyClient | null,\n) {\n\t// Get workouts\n\tconst getWorkoutsSchema = {\n\t\tpage: z.coerce.number().gte(1).default(1),\n\t\tpageSize: z.coerce.number().int().gte(1).lte(10).default(5),\n\t} as const;\n\ttype GetWorkoutsParams = InferToolParams<typeof getWorkoutsSchema>;\n\n\tserver.tool(\n\t\t\"get-workouts\",\n\t\t\"Get a paginated list of workouts. Returns workout details including title, description, start/end times, and exercises performed. Results are ordered from newest to oldest.\",\n\t\tgetWorkoutsSchema,\n\t\treadOnlyAnnotations(\"Get Workouts\"),\n\t\twithErrorHandling(async (args: GetWorkoutsParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { page, pageSize } = args;\n\t\t\tconst data: GetV1Workouts200 = await client.getWorkouts({\n\t\t\t\tpage,\n\t\t\t\tpageSize,\n\t\t\t});\n\n\t\t\tconst workouts =\n\t\t\t\tdata?.workouts?.map((workout) => formatWorkout(workout)) || [];\n\n\t\t\tif (workouts.length === 0) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"No workouts found for the specified parameters\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createJsonResponse(workouts);\n\t\t}, \"get-workouts\"),\n\t);\n\n\t// Get single workout by ID\n\tconst getWorkoutSchema = {\n\t\tworkoutId: z.string().min(1),\n\t} as const;\n\ttype GetWorkoutParams = InferToolParams<typeof getWorkoutSchema>;\n\n\tserver.tool(\n\t\t\"get-workout\",\n\t\t\"Get complete details of a specific workout by ID. Returns all workout information including title, description, start/end times, and detailed exercise data.\",\n\t\tgetWorkoutSchema,\n\t\treadOnlyAnnotations(\"Get Workout\"),\n\t\twithErrorHandling(async (args: GetWorkoutParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { workoutId } = args;\n\t\t\tconst data: GetV1WorkoutsWorkoutid200 =\n\t\t\t\tawait client.getWorkout(workoutId);\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(`Workout with ID ${workoutId} not found`);\n\t\t\t}\n\n\t\t\tconst workout = formatWorkout(data);\n\t\t\treturn createJsonResponse(workout);\n\t\t}, \"get-workout\"),\n\t);\n\n\t// Get workout count\n\tserver.tool(\n\t\t\"get-workout-count\",\n\t\t\"Get the total number of workouts on the account. Useful for pagination or statistics.\",\n\t\t{},\n\t\treadOnlyAnnotations(\"Get Workout Count\"),\n\t\twithErrorHandling(async () => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst data: GetV1WorkoutsCount200 = await client.getWorkoutCount();\n\t\t\tconst count = data?.workout_count ?? 0;\n\t\t\treturn createJsonResponse({ count });\n\t\t}, \"get-workout-count\"),\n\t);\n\n\t// Get workout events (updates/deletes)\n\tconst getWorkoutEventsSchema = {\n\t\tpage: z.coerce.number().int().gte(1).default(1),\n\t\tpageSize: z.coerce.number().int().gte(1).lte(10).default(5),\n\t\tsince: z.string().default(\"1970-01-01T00:00:00Z\"),\n\t} as const;\n\ttype GetWorkoutEventsParams = InferToolParams<typeof getWorkoutEventsSchema>;\n\n\tserver.tool(\n\t\t\"get-workout-events\",\n\t\t\"Retrieve a paged list of workout events (updates or deletes) since a given date. Events are ordered from newest to oldest. The intention is to allow clients to keep their local cache of workouts up to date without having to fetch the entire list of workouts.\",\n\t\tgetWorkoutEventsSchema,\n\t\treadOnlyAnnotations(\"Get Workout Events\"),\n\t\twithErrorHandling(async (args: GetWorkoutEventsParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { page, pageSize, since } = args;\n\t\t\tconst data: GetV1WorkoutsEvents200 = await client.getWorkoutEvents({\n\t\t\t\tpage,\n\t\t\t\tpageSize,\n\t\t\t\tsince,\n\t\t\t});\n\n\t\t\tconst events = data?.events || [];\n\n\t\t\tif (events.length === 0) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t`No workout events found for the specified parameters since ${since}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn createJsonResponse(events);\n\t\t}, \"get-workout-events\"),\n\t);\n\n\t// Create workout\n\tconst createWorkoutSchema = {\n\t\ttitle: z.string().min(1),\n\t\tdescription: z.string().optional().nullable(),\n\t\tstartTime: z.string().regex(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$/),\n\t\tendTime: z.string().regex(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$/),\n\t\tisPrivate: z.boolean().default(false),\n\t\texercises: z.preprocess(\n\t\t\tparseJsonArray,\n\t\t\tz.array(\n\t\t\t\tz.object({\n\t\t\t\t\texerciseTemplateId: z.string().min(1),\n\t\t\t\t\tsupersetId: z.coerce.number().nullable().optional(),\n\t\t\t\t\tnotes: z.string().optional().nullable(),\n\t\t\t\t\tsets: z.array(\n\t\t\t\t\t\tz.object({\n\t\t\t\t\t\t\ttype: setTypeEnum,\n\t\t\t\t\t\t\tweight: z.coerce.number().optional().nullable(),\n\t\t\t\t\t\t\tweightKg: z.coerce.number().optional().nullable(),\n\t\t\t\t\t\t\treps: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\tdistance: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\tdistanceMeters: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\tduration: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\tdurationSeconds: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\trpe: z.coerce.number().optional().nullable(),\n\t\t\t\t\t\t\tcustomMetric: z.coerce.number().optional().nullable(),\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t),\n\t\t),\n\t} as const;\n\ttype CreateWorkoutParams = InferToolParams<typeof createWorkoutSchema>;\n\n\tserver.tool(\n\t\t\"create-workout\",\n\t\t\"Create a new workout in your Hevy account. Requires title, start/end times, and at least one exercise with sets. Returns the complete workout details upon successful creation including the newly assigned workout ID.\",\n\t\tcreateWorkoutSchema,\n\t\tcreateAnnotations(\"Create Workout\"),\n\t\twithErrorHandling(async (args: CreateWorkoutParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst { title, description, startTime, endTime, isPrivate, exercises } =\n\t\t\t\targs;\n\t\t\tconst workoutPayload: NonNullable<PostWorkoutsRequestBody[\"workout\"]> = {\n\t\t\t\ttitle,\n\t\t\t\tdescription: description ?? null,\n\t\t\t\tstart_time: startTime,\n\t\t\t\tend_time: endTime,\n\t\t\t\tis_private: isPrivate,\n\t\t\t\texercises: exercises.map(\n\t\t\t\t\t(exercise): PostWorkoutsRequestExercise => ({\n\t\t\t\t\t\texercise_template_id: exercise.exerciseTemplateId,\n\t\t\t\t\t\tsuperset_id: exercise.supersetId ?? null,\n\t\t\t\t\t\tnotes: exercise.notes ?? null,\n\t\t\t\t\t\tsets: exercise.sets.map((set) => ({\n\t\t\t\t\t\t\ttype: set.type as PostWorkoutsRequestSetTypeEnumKey,\n\t\t\t\t\t\t\tweight_kg: set.weight ?? set.weightKg ?? null,\n\t\t\t\t\t\t\treps: set.reps ?? null,\n\t\t\t\t\t\t\tdistance_meters: set.distance ?? set.distanceMeters ?? null,\n\t\t\t\t\t\t\tduration_seconds: set.duration ?? set.durationSeconds ?? null,\n\t\t\t\t\t\t\trpe: (set.rpe as PostWorkoutsRequestSetRpeEnumKey | null) ?? null,\n\t\t\t\t\t\t\tcustom_metric: set.customMetric ?? null,\n\t\t\t\t\t\t})),\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t};\n\t\t\tconst requestBody: PostWorkoutsRequestBody = { workout: workoutPayload };\n\n\t\t\tconst data: PostV1Workouts201 = await client.createWorkout(requestBody);\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t\"Failed to create workout: Server returned no data\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst workout = formatWorkout(data);\n\t\t\treturn createJsonResponse(workout, {\n\t\t\t\tpretty: true,\n\t\t\t\tindent: 2,\n\t\t\t});\n\t\t}, \"create-workout\"),\n\t);\n\n\t// Update workout\n\tconst updateWorkoutSchema = {\n\t\tworkoutId: z.string().min(1),\n\t\ttitle: z.string().min(1),\n\t\tdescription: z.string().optional().nullable(),\n\t\tstartTime: z.string().regex(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$/),\n\t\tendTime: z.string().regex(/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z$/),\n\t\tisPrivate: z.boolean().default(false),\n\t\texercises: z.preprocess(\n\t\t\tparseJsonArray,\n\t\t\tz.array(\n\t\t\t\tz.object({\n\t\t\t\t\texerciseTemplateId: z.string().min(1),\n\t\t\t\t\tsupersetId: z.coerce.number().nullable().optional(),\n\t\t\t\t\tnotes: z.string().optional().nullable(),\n\t\t\t\t\tsets: z.array(\n\t\t\t\t\t\tz.object({\n\t\t\t\t\t\t\ttype: setTypeEnum,\n\t\t\t\t\t\t\tweight: z.coerce.number().optional().nullable(),\n\t\t\t\t\t\t\tweightKg: z.coerce.number().optional().nullable(),\n\t\t\t\t\t\t\treps: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\tdistance: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\tdistanceMeters: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\tduration: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\tdurationSeconds: z.coerce.number().int().optional().nullable(),\n\t\t\t\t\t\t\trpe: z.coerce.number().optional().nullable(),\n\t\t\t\t\t\t\tcustomMetric: z.coerce.number().optional().nullable(),\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t}),\n\t\t\t),\n\t\t),\n\t} as const;\n\ttype UpdateWorkoutParams = InferToolParams<typeof updateWorkoutSchema>;\n\n\tserver.tool(\n\t\t\"update-workout\",\n\t\t\"Update an existing workout by ID. You can modify the title, description, start/end times, privacy setting, and exercise data. Returns the updated workout with all changes applied.\",\n\t\tupdateWorkoutSchema,\n\t\tupdateAnnotations(\"Update Workout\"),\n\t\twithErrorHandling(async (args: UpdateWorkoutParams) => {\n\t\t\tconst client = requireClient(hevyClient);\n\t\t\tconst {\n\t\t\t\tworkoutId,\n\t\t\t\ttitle,\n\t\t\t\tdescription,\n\t\t\t\tstartTime,\n\t\t\t\tendTime,\n\t\t\t\tisPrivate,\n\t\t\t\texercises,\n\t\t\t} = args;\n\t\t\tconst workoutPayload: NonNullable<PostWorkoutsRequestBody[\"workout\"]> = {\n\t\t\t\ttitle,\n\t\t\t\tdescription: description ?? null,\n\t\t\t\tstart_time: startTime,\n\t\t\t\tend_time: endTime,\n\t\t\t\tis_private: isPrivate,\n\t\t\t\texercises: exercises.map(\n\t\t\t\t\t(exercise): PostWorkoutsRequestExercise => ({\n\t\t\t\t\t\texercise_template_id: exercise.exerciseTemplateId,\n\t\t\t\t\t\tsuperset_id: exercise.supersetId ?? null,\n\t\t\t\t\t\tnotes: exercise.notes ?? null,\n\t\t\t\t\t\tsets: exercise.sets.map((set) => ({\n\t\t\t\t\t\t\ttype: set.type as PostWorkoutsRequestSetTypeEnumKey,\n\t\t\t\t\t\t\tweight_kg: set.weight ?? set.weightKg ?? null,\n\t\t\t\t\t\t\treps: set.reps ?? null,\n\t\t\t\t\t\t\tdistance_meters: set.distance ?? set.distanceMeters ?? null,\n\t\t\t\t\t\t\tduration_seconds: set.duration ?? set.durationSeconds ?? null,\n\t\t\t\t\t\t\trpe: (set.rpe as PostWorkoutsRequestSetRpeEnumKey | null) ?? null,\n\t\t\t\t\t\t\tcustom_metric: set.customMetric ?? null,\n\t\t\t\t\t\t})),\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t};\n\t\t\tconst requestBody: PostWorkoutsRequestBody = { workout: workoutPayload };\n\n\t\t\tconst data: PutV1WorkoutsWorkoutid200 = await client.updateWorkout(\n\t\t\t\tworkoutId,\n\t\t\t\trequestBody,\n\t\t\t);\n\n\t\t\tif (!data) {\n\t\t\t\treturn createEmptyResponse(\n\t\t\t\t\t`Failed to update workout with ID ${workoutId}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst workout = formatWorkout(data);\n\t\t\treturn createJsonResponse(workout, {\n\t\t\t\tpretty: true,\n\t\t\t\tindent: 2,\n\t\t\t});\n\t\t}, \"update-workout-operation\"),\n\t);\n}\n","export interface HevyConfig {\n\tapiKey?: string;\n}\n\nconst DEPRECATED_CLI_ARGUMENT_WARNING = [\n\t\"DEPRECATION WARNING: Passing the Hevy API key via CLI arguments\",\n\t\"(--hevy-api-key=..., --hevyApiKey=..., hevy-api-key=...) is\",\n\t\"deprecated and insecure. Use the HEVY_API_KEY environment\",\n\t\"variable instead.\",\n].join(\" \");\n\n/**\n * Parse CLI arguments and environment to derive configuration.\n * Priority order for API key: deprecated CLI flag forms > environment variable.\n * Supported deprecated CLI arg forms:\n * --hevy-api-key=KEY\n * --hevyApiKey=KEY\n * hevy-api-key=KEY (bare, e.g. when passed after npm start -- )\n */\nexport function parseConfig(\n\targv: string[],\n\tenv: NodeJS.ProcessEnv,\n): HevyConfig {\n\tlet apiKey = \"\";\n\tlet usedDeprecatedApiKeyArg = false;\n\tconst apiKeyArgPatterns = [\n\t\t/^--hevy-api-key=(.+)$/i,\n\t\t/^--hevyApiKey=(.+)$/i,\n\t\t/^hevy-api-key=(.+)$/i,\n\t];\n\tfor (const raw of argv) {\n\t\tfor (const pattern of apiKeyArgPatterns) {\n\t\t\tconst m = raw.match(pattern);\n\t\t\tif (m) {\n\t\t\t\tapiKey = m[1];\n\t\t\t\tusedDeprecatedApiKeyArg = true;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (apiKey) break;\n\t}\n\tif (usedDeprecatedApiKeyArg) {\n\t\tconsole.error(DEPRECATED_CLI_ARGUMENT_WARNING);\n\t}\n\tif (!apiKey) {\n\t\tapiKey = env.HEVY_API_KEY || \"\";\n\t}\n\n\treturn {\n\t\tapiKey,\n\t};\n}\n\nexport function assertApiKey(\n\tapiKey: string | undefined,\n): asserts apiKey is string {\n\tif (!apiKey) {\n\t\tconsole.error(\n\t\t\t\"Hevy API key is required. Provide it via the HEVY_API_KEY environment variable.\",\n\t\t);\n\t\tprocess.exit(1);\n\t}\n}\n","import type { AxiosError, AxiosRequestConfig, AxiosResponse } from \"axios\";\nimport axios from \"axios\";\n\ndeclare const AXIOS_BASE: string;\ndeclare const AXIOS_HEADERS: string;\n\n/**\n * Subset of AxiosRequestConfig\n */\nexport type RequestConfig<TData = unknown> = {\n baseURL?: string;\n url?: string;\n method?: \"GET\" | \"PUT\" | \"PATCH\" | \"POST\" | \"DELETE\" | \"OPTIONS\" | \"HEAD\";\n params?: unknown;\n data?: TData | FormData;\n responseType?:\n | \"arraybuffer\"\n | \"blob\"\n | \"document\"\n | \"json\"\n | \"text\"\n | \"stream\";\n signal?: AbortSignal;\n validateStatus?: (status: number) => boolean;\n headers?: AxiosRequestConfig[\"headers\"];\n};\n\n/**\n * Subset of AxiosResponse\n */\nexport type ResponseConfig<TData = unknown> = {\n data: TData;\n status: number;\n statusText: string;\n headers: AxiosResponse[\"headers\"];\n};\n\nexport type ResponseErrorConfig<TError = unknown> = AxiosError<TError>;\n\nexport type Client = <TData, _TError = unknown, TVariables = unknown>(\n config: RequestConfig<TVariables>,\n) => Promise<ResponseConfig<TData>>;\n\nlet _config: Partial<RequestConfig> = {\n baseURL: typeof AXIOS_BASE !== \"undefined\" ? AXIOS_BASE : undefined,\n headers:\n typeof AXIOS_HEADERS !== \"undefined\"\n ? JSON.parse(AXIOS_HEADERS)\n : undefined,\n};\n\nexport const getConfig = () => _config;\n\nexport const setConfig = (config: RequestConfig) => {\n _config = config;\n return getConfig();\n};\n\nexport const mergeConfig = <T extends RequestConfig>(\n ...configs: Array<Partial<T>>\n): Partial<T> => {\n return configs.reduce<Partial<T>>((merged, config) => {\n return {\n ...merged,\n ...config,\n headers: {\n ...merged.headers,\n ...config.headers,\n },\n };\n }, {});\n};\n\nexport const axiosInstance = axios.create(getConfig());\n\nexport const fetch = async <TData, TError = unknown, TVariables = unknown>(\n config: RequestConfig<TVariables>,\n): Promise<ResponseConfig<TData>> => {\n return axiosInstance\n .request<TData, ResponseConfig<TData>>(mergeConfig(getConfig(), config))\n .catch((e: AxiosError<TError>) => {\n throw e;\n });\n};\n\nfetch.getConfig = getConfig;\nfetch.setConfig = setConfig;\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n GetV1BodyMeasurementsQueryResponse,\n GetV1BodyMeasurementsQueryParams,\n GetV1BodyMeasurementsHeaderParams,\n GetV1BodyMeasurements400,\n GetV1BodyMeasurements404,\n} from \"../types/GetV1BodyMeasurements.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getGetV1BodyMeasurementsUrl() {\n const res = { method: \"GET\", url: `/v1/body_measurements` as const };\n return res;\n}\n\n/**\n * @summary Get a paginated list of body measurements for the authenticated user\n * {@link /v1/body_measurements}\n */\nexport async function getV1BodyMeasurements(\n headers: GetV1BodyMeasurementsHeaderParams,\n params?: GetV1BodyMeasurementsQueryParams,\n config: Partial<RequestConfig> & { client?: Client } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1BodyMeasurementsQueryResponse,\n ResponseErrorConfig<GetV1BodyMeasurements400 | GetV1BodyMeasurements404>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1BodyMeasurementsUrl().url.toString(),\n params,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n GetV1BodyMeasurementsDateQueryResponse,\n GetV1BodyMeasurementsDatePathParams,\n GetV1BodyMeasurementsDateHeaderParams,\n GetV1BodyMeasurementsDate404,\n} from \"../types/GetV1BodyMeasurementsDate.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getGetV1BodyMeasurementsDateUrl(\n date: GetV1BodyMeasurementsDatePathParams[\"date\"],\n) {\n const res = { method: \"GET\", url: `/v1/body_measurements/${date}` as const };\n return res;\n}\n\n/**\n * @summary Get a single body measurement by date\n * {@link /v1/body_measurements/:date}\n */\nexport async function getV1BodyMeasurementsDate(\n date: GetV1BodyMeasurementsDatePathParams[\"date\"],\n headers: GetV1BodyMeasurementsDateHeaderParams,\n config: Partial<RequestConfig> & { client?: Client } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1BodyMeasurementsDateQueryResponse,\n ResponseErrorConfig<GetV1BodyMeasurementsDate404>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1BodyMeasurementsDateUrl(date).url.toString(),\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n GetV1ExerciseHistoryExercisetemplateidQueryResponse,\n GetV1ExerciseHistoryExercisetemplateidPathParams,\n GetV1ExerciseHistoryExercisetemplateidQueryParams,\n GetV1ExerciseHistoryExercisetemplateidHeaderParams,\n GetV1ExerciseHistoryExercisetemplateid400,\n} from \"../types/GetV1ExerciseHistoryExercisetemplateid.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getGetV1ExerciseHistoryExercisetemplateidUrl(\n exerciseTemplateId: GetV1ExerciseHistoryExercisetemplateidPathParams[\"exerciseTemplateId\"],\n) {\n const res = {\n method: \"GET\",\n url: `/v1/exercise_history/${exerciseTemplateId}` as const,\n };\n return res;\n}\n\n/**\n * @summary Get exercise history for a specific exercise template\n * {@link /v1/exercise_history/:exerciseTemplateId}\n */\nexport async function getV1ExerciseHistoryExercisetemplateid(\n exerciseTemplateId: GetV1ExerciseHistoryExercisetemplateidPathParams[\"exerciseTemplateId\"],\n headers: GetV1ExerciseHistoryExercisetemplateidHeaderParams,\n params?: GetV1ExerciseHistoryExercisetemplateidQueryParams,\n config: Partial<RequestConfig> & { client?: Client } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1ExerciseHistoryExercisetemplateidQueryResponse,\n ResponseErrorConfig<GetV1ExerciseHistoryExercisetemplateid400>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1ExerciseHistoryExercisetemplateidUrl(\n exerciseTemplateId,\n ).url.toString(),\n params,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n GetV1ExerciseTemplatesQueryResponse,\n GetV1ExerciseTemplatesQueryParams,\n GetV1ExerciseTemplatesHeaderParams,\n GetV1ExerciseTemplates400,\n} from \"../types/GetV1ExerciseTemplates.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getGetV1ExerciseTemplatesUrl() {\n const res = { method: \"GET\", url: `/v1/exercise_templates` as const };\n return res;\n}\n\n/**\n * @summary Get a paginated list of exercise templates available on the account.\n * {@link /v1/exercise_templates}\n */\nexport async function getV1ExerciseTemplates(\n headers: GetV1ExerciseTemplatesHeaderParams,\n params?: GetV1ExerciseTemplatesQueryParams,\n config: Partial<RequestConfig> & { client?: Client } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1ExerciseTemplatesQueryResponse,\n ResponseErrorConfig<GetV1ExerciseTemplates400>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1ExerciseTemplatesUrl().url.toString(),\n params,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n GetV1ExerciseTemplatesExercisetemplateidQueryResponse,\n GetV1ExerciseTemplatesExercisetemplateidPathParams,\n GetV1ExerciseTemplatesExercisetemplateidHeaderParams,\n GetV1ExerciseTemplatesExercisetemplateid404,\n} from \"../types/GetV1ExerciseTemplatesExercisetemplateid.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getGetV1ExerciseTemplatesExercisetemplateidUrl(\n exerciseTemplateId: GetV1ExerciseTemplatesExercisetemplateidPathParams[\"exerciseTemplateId\"],\n) {\n const res = {\n method: \"GET\",\n url: `/v1/exercise_templates/${exerciseTemplateId}` as const,\n };\n return res;\n}\n\n/**\n * @summary Get a single exercise template by id.\n * {@link /v1/exercise_templates/:exerciseTemplateId}\n */\nexport async function getV1ExerciseTemplatesExercisetemplateid(\n exerciseTemplateId: GetV1ExerciseTemplatesExercisetemplateidPathParams[\"exerciseTemplateId\"],\n headers: GetV1ExerciseTemplatesExercisetemplateidHeaderParams,\n config: Partial<RequestConfig> & { client?: Client } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1ExerciseTemplatesExercisetemplateidQueryResponse,\n ResponseErrorConfig<GetV1ExerciseTemplatesExercisetemplateid404>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1ExerciseTemplatesExercisetemplateidUrl(\n exerciseTemplateId,\n ).url.toString(),\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n GetV1RoutineFoldersQueryResponse,\n GetV1RoutineFoldersQueryParams,\n GetV1RoutineFoldersHeaderParams,\n GetV1RoutineFolders400,\n} from \"../types/GetV1RoutineFolders.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getGetV1RoutineFoldersUrl() {\n const res = { method: \"GET\", url: `/v1/routine_folders` as const };\n return res;\n}\n\n/**\n * @summary Get a paginated list of routine folders available on the account.\n * {@link /v1/routine_folders}\n */\nexport async function getV1RoutineFolders(\n headers: GetV1RoutineFoldersHeaderParams,\n params?: GetV1RoutineFoldersQueryParams,\n config: Partial<RequestConfig> & { client?: Client } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1RoutineFoldersQueryResponse,\n ResponseErrorConfig<GetV1RoutineFolders400>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1RoutineFoldersUrl().url.toString(),\n params,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n GetV1RoutineFoldersFolderidQueryResponse,\n GetV1RoutineFoldersFolderidPathParams,\n GetV1RoutineFoldersFolderidHeaderParams,\n GetV1RoutineFoldersFolderid404,\n} from \"../types/GetV1RoutineFoldersFolderid.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getGetV1RoutineFoldersFolderidUrl(\n folderId: GetV1RoutineFoldersFolderidPathParams[\"folderId\"],\n) {\n const res = {\n method: \"GET\",\n url: `/v1/routine_folders/${folderId}` as const,\n };\n return res;\n}\n\n/**\n * @summary Get a single routine folder by id.\n * {@link /v1/routine_folders/:folderId}\n */\nexport async function getV1RoutineFoldersFolderid(\n folderId: GetV1RoutineFoldersFolderidPathParams[\"folderId\"],\n headers: GetV1RoutineFoldersFolderidHeaderParams,\n config: Partial<RequestConfig> & { client?: Client } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1RoutineFoldersFolderidQueryResponse,\n ResponseErrorConfig<GetV1RoutineFoldersFolderid404>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1RoutineFoldersFolderidUrl(folderId).url.toString(),\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n GetV1RoutinesQueryResponse,\n GetV1RoutinesQueryParams,\n GetV1RoutinesHeaderParams,\n GetV1Routines400,\n} from \"../types/GetV1Routines.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getGetV1RoutinesUrl() {\n const res = { method: \"GET\", url: `/v1/routines` as const };\n return res;\n}\n\n/**\n * @summary Get a paginated list of routines\n * {@link /v1/routines}\n */\nexport async function getV1Routines(\n headers: GetV1RoutinesHeaderParams,\n params?: GetV1RoutinesQueryParams,\n config: Partial<RequestConfig> & { client?: Client } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1RoutinesQueryResponse,\n ResponseErrorConfig<GetV1Routines400>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1RoutinesUrl().url.toString(),\n params,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n GetV1RoutinesRoutineidQueryResponse,\n GetV1RoutinesRoutineidPathParams,\n GetV1RoutinesRoutineidHeaderParams,\n GetV1RoutinesRoutineid400,\n} from \"../types/GetV1RoutinesRoutineid.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getGetV1RoutinesRoutineidUrl(\n routineId: GetV1RoutinesRoutineidPathParams[\"routineId\"],\n) {\n const res = { method: \"GET\", url: `/v1/routines/${routineId}` as const };\n return res;\n}\n\n/**\n * @summary Get a routine by its Id\n * {@link /v1/routines/:routineId}\n */\nexport async function getV1RoutinesRoutineid(\n routineId: GetV1RoutinesRoutineidPathParams[\"routineId\"],\n headers: GetV1RoutinesRoutineidHeaderParams,\n config: Partial<RequestConfig> & { client?: Client } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1RoutinesRoutineidQueryResponse,\n ResponseErrorConfig<GetV1RoutinesRoutineid400>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1RoutinesRoutineidUrl(routineId).url.toString(),\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n GetV1UserInfoQueryResponse,\n GetV1UserInfoHeaderParams,\n GetV1UserInfo404,\n} from \"../types/GetV1UserInfo.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getGetV1UserInfoUrl() {\n const res = { method: \"GET\", url: `/v1/user/info` as const };\n return res;\n}\n\n/**\n * @summary Get user info\n * {@link /v1/user/info}\n */\nexport async function getV1UserInfo(\n headers: GetV1UserInfoHeaderParams,\n config: Partial<RequestConfig> & { client?: Client } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1UserInfoQueryResponse,\n ResponseErrorConfig<GetV1UserInfo404>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1UserInfoUrl().url.toString(),\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n GetV1WorkoutsQueryResponse,\n GetV1WorkoutsQueryParams,\n GetV1WorkoutsHeaderParams,\n GetV1Workouts400,\n} from \"../types/GetV1Workouts.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getGetV1WorkoutsUrl() {\n const res = { method: \"GET\", url: `/v1/workouts` as const };\n return res;\n}\n\n/**\n * @summary Get a paginated list of workouts\n * {@link /v1/workouts}\n */\nexport async function getV1Workouts(\n headers: GetV1WorkoutsHeaderParams,\n params?: GetV1WorkoutsQueryParams,\n config: Partial<RequestConfig> & { client?: Client } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1WorkoutsQueryResponse,\n ResponseErrorConfig<GetV1Workouts400>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1WorkoutsUrl().url.toString(),\n params,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n GetV1WorkoutsCountQueryResponse,\n GetV1WorkoutsCountHeaderParams,\n} from \"../types/GetV1WorkoutsCount.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getGetV1WorkoutsCountUrl() {\n const res = { method: \"GET\", url: `/v1/workouts/count` as const };\n return res;\n}\n\n/**\n * @summary Get the total number of workouts on the account\n * {@link /v1/workouts/count}\n */\nexport async function getV1WorkoutsCount(\n headers: GetV1WorkoutsCountHeaderParams,\n config: Partial<RequestConfig> & { client?: Client } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1WorkoutsCountQueryResponse,\n ResponseErrorConfig<Error>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1WorkoutsCountUrl().url.toString(),\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n GetV1WorkoutsEventsQueryResponse,\n GetV1WorkoutsEventsQueryParams,\n GetV1WorkoutsEventsHeaderParams,\n GetV1WorkoutsEvents500,\n} from \"../types/GetV1WorkoutsEvents.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getGetV1WorkoutsEventsUrl() {\n const res = { method: \"GET\", url: `/v1/workouts/events` as const };\n return res;\n}\n\n/**\n * @description Returns a paginated array of workout events, indicating updates or deletions.\n * @summary Retrieve a paged list of workout events (updates or deletes) since a given date. Events are ordered from newest to oldest. The intention is to allow clients to keep their local cache of workouts up to date without having to fetch the entire list of workouts.\n * {@link /v1/workouts/events}\n */\nexport async function getV1WorkoutsEvents(\n headers: GetV1WorkoutsEventsHeaderParams,\n params?: GetV1WorkoutsEventsQueryParams,\n config: Partial<RequestConfig> & { client?: Client } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1WorkoutsEventsQueryResponse,\n ResponseErrorConfig<GetV1WorkoutsEvents500>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1WorkoutsEventsUrl().url.toString(),\n params,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n GetV1WorkoutsWorkoutidQueryResponse,\n GetV1WorkoutsWorkoutidPathParams,\n GetV1WorkoutsWorkoutidHeaderParams,\n GetV1WorkoutsWorkoutid404,\n} from \"../types/GetV1WorkoutsWorkoutid.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getGetV1WorkoutsWorkoutidUrl(\n workoutId: GetV1WorkoutsWorkoutidPathParams[\"workoutId\"],\n) {\n const res = { method: \"GET\", url: `/v1/workouts/${workoutId}` as const };\n return res;\n}\n\n/**\n * @summary Get a single workout’s complete details by the workoutId\n * {@link /v1/workouts/:workoutId}\n */\nexport async function getV1WorkoutsWorkoutid(\n workoutId: GetV1WorkoutsWorkoutidPathParams[\"workoutId\"],\n headers: GetV1WorkoutsWorkoutidHeaderParams,\n config: Partial<RequestConfig> & { client?: Client } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const res = await request<\n GetV1WorkoutsWorkoutidQueryResponse,\n ResponseErrorConfig<GetV1WorkoutsWorkoutid404>,\n unknown\n >({\n method: \"GET\",\n url: getGetV1WorkoutsWorkoutidUrl(workoutId).url.toString(),\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n PostV1BodyMeasurementsMutationRequest,\n PostV1BodyMeasurementsMutationResponse,\n PostV1BodyMeasurementsHeaderParams,\n PostV1BodyMeasurements400,\n PostV1BodyMeasurements409,\n} from \"../types/PostV1BodyMeasurements.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getPostV1BodyMeasurementsUrl() {\n const res = { method: \"POST\", url: `/v1/body_measurements` as const };\n return res;\n}\n\n/**\n * @summary Create a body measurement entry for a given date. Returns 409 if an entry already exists for that date.\n * {@link /v1/body_measurements}\n */\nexport async function postV1BodyMeasurements(\n data: PostV1BodyMeasurementsMutationRequest,\n headers: PostV1BodyMeasurementsHeaderParams,\n config: Partial<RequestConfig<PostV1BodyMeasurementsMutationRequest>> & {\n client?: Client;\n } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const requestData = data;\n\n const res = await request<\n PostV1BodyMeasurementsMutationResponse,\n ResponseErrorConfig<PostV1BodyMeasurements400 | PostV1BodyMeasurements409>,\n PostV1BodyMeasurementsMutationRequest\n >({\n method: \"POST\",\n url: getPostV1BodyMeasurementsUrl().url.toString(),\n data: requestData,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n PostV1ExerciseTemplatesMutationRequest,\n PostV1ExerciseTemplatesMutationResponse,\n PostV1ExerciseTemplatesHeaderParams,\n PostV1ExerciseTemplates400,\n PostV1ExerciseTemplates403,\n} from \"../types/PostV1ExerciseTemplates.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getPostV1ExerciseTemplatesUrl() {\n const res = { method: \"POST\", url: `/v1/exercise_templates` as const };\n return res;\n}\n\n/**\n * @summary Create a new custom exercise template.\n * {@link /v1/exercise_templates}\n */\nexport async function postV1ExerciseTemplates(\n data: PostV1ExerciseTemplatesMutationRequest,\n headers: PostV1ExerciseTemplatesHeaderParams,\n config: Partial<RequestConfig<PostV1ExerciseTemplatesMutationRequest>> & {\n client?: Client;\n } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const requestData = data;\n\n const res = await request<\n PostV1ExerciseTemplatesMutationResponse,\n ResponseErrorConfig<\n PostV1ExerciseTemplates400 | PostV1ExerciseTemplates403\n >,\n PostV1ExerciseTemplatesMutationRequest\n >({\n method: \"POST\",\n url: getPostV1ExerciseTemplatesUrl().url.toString(),\n data: requestData,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n PostV1RoutineFoldersMutationRequest,\n PostV1RoutineFoldersMutationResponse,\n PostV1RoutineFoldersHeaderParams,\n PostV1RoutineFolders400,\n} from \"../types/PostV1RoutineFolders.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getPostV1RoutineFoldersUrl() {\n const res = { method: \"POST\", url: `/v1/routine_folders` as const };\n return res;\n}\n\n/**\n * @summary Create a new routine folder. The folder will be created at index 0, and all other folders will have their indexes incremented.\n * {@link /v1/routine_folders}\n */\nexport async function postV1RoutineFolders(\n data: PostV1RoutineFoldersMutationRequest,\n headers: PostV1RoutineFoldersHeaderParams,\n config: Partial<RequestConfig<PostV1RoutineFoldersMutationRequest>> & {\n client?: Client;\n } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const requestData = data;\n\n const res = await request<\n PostV1RoutineFoldersMutationResponse,\n ResponseErrorConfig<PostV1RoutineFolders400>,\n PostV1RoutineFoldersMutationRequest\n >({\n method: \"POST\",\n url: getPostV1RoutineFoldersUrl().url.toString(),\n data: requestData,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n PostV1RoutinesMutationRequest,\n PostV1RoutinesMutationResponse,\n PostV1RoutinesHeaderParams,\n PostV1Routines400,\n PostV1Routines403,\n} from \"../types/PostV1Routines.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getPostV1RoutinesUrl() {\n const res = { method: \"POST\", url: `/v1/routines` as const };\n return res;\n}\n\n/**\n * @summary Create a new routine\n * {@link /v1/routines}\n */\nexport async function postV1Routines(\n data: PostV1RoutinesMutationRequest,\n headers: PostV1RoutinesHeaderParams,\n config: Partial<RequestConfig<PostV1RoutinesMutationRequest>> & {\n client?: Client;\n } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const requestData = data;\n\n const res = await request<\n PostV1RoutinesMutationResponse,\n ResponseErrorConfig<PostV1Routines400 | PostV1Routines403>,\n PostV1RoutinesMutationRequest\n >({\n method: \"POST\",\n url: getPostV1RoutinesUrl().url.toString(),\n data: requestData,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n PostV1WorkoutsMutationRequest,\n PostV1WorkoutsMutationResponse,\n PostV1WorkoutsHeaderParams,\n PostV1Workouts400,\n} from \"../types/PostV1Workouts.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getPostV1WorkoutsUrl() {\n const res = { method: \"POST\", url: `/v1/workouts` as const };\n return res;\n}\n\n/**\n * @summary Create a new workout\n * {@link /v1/workouts}\n */\nexport async function postV1Workouts(\n data: PostV1WorkoutsMutationRequest,\n headers: PostV1WorkoutsHeaderParams,\n config: Partial<RequestConfig<PostV1WorkoutsMutationRequest>> & {\n client?: Client;\n } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const requestData = data;\n\n const res = await request<\n PostV1WorkoutsMutationResponse,\n ResponseErrorConfig<PostV1Workouts400>,\n PostV1WorkoutsMutationRequest\n >({\n method: \"POST\",\n url: getPostV1WorkoutsUrl().url.toString(),\n data: requestData,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n PutV1BodyMeasurementsDateMutationRequest,\n PutV1BodyMeasurementsDateMutationResponse,\n PutV1BodyMeasurementsDatePathParams,\n PutV1BodyMeasurementsDateHeaderParams,\n PutV1BodyMeasurementsDate400,\n PutV1BodyMeasurementsDate404,\n} from \"../types/PutV1BodyMeasurementsDate.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getPutV1BodyMeasurementsDateUrl(\n date: PutV1BodyMeasurementsDatePathParams[\"date\"],\n) {\n const res = { method: \"PUT\", url: `/v1/body_measurements/${date}` as const };\n return res;\n}\n\n/**\n * @summary Update an existing body measurement entry for a given date. All fields are overwritten; omitted fields are set to null.\n * {@link /v1/body_measurements/:date}\n */\nexport async function putV1BodyMeasurementsDate(\n date: PutV1BodyMeasurementsDatePathParams[\"date\"],\n data: PutV1BodyMeasurementsDateMutationRequest,\n headers: PutV1BodyMeasurementsDateHeaderParams,\n config: Partial<RequestConfig<PutV1BodyMeasurementsDateMutationRequest>> & {\n client?: Client;\n } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const requestData = data;\n\n const res = await request<\n PutV1BodyMeasurementsDateMutationResponse,\n ResponseErrorConfig<\n PutV1BodyMeasurementsDate400 | PutV1BodyMeasurementsDate404\n >,\n PutV1BodyMeasurementsDateMutationRequest\n >({\n method: \"PUT\",\n url: getPutV1BodyMeasurementsDateUrl(date).url.toString(),\n data: requestData,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n PutV1RoutinesRoutineidMutationRequest,\n PutV1RoutinesRoutineidMutationResponse,\n PutV1RoutinesRoutineidPathParams,\n PutV1RoutinesRoutineidHeaderParams,\n PutV1RoutinesRoutineid400,\n PutV1RoutinesRoutineid404,\n} from \"../types/PutV1RoutinesRoutineid.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getPutV1RoutinesRoutineidUrl(\n routineId: PutV1RoutinesRoutineidPathParams[\"routineId\"],\n) {\n const res = { method: \"PUT\", url: `/v1/routines/${routineId}` as const };\n return res;\n}\n\n/**\n * @summary Update an existing routine\n * {@link /v1/routines/:routineId}\n */\nexport async function putV1RoutinesRoutineid(\n routineId: PutV1RoutinesRoutineidPathParams[\"routineId\"],\n data: PutV1RoutinesRoutineidMutationRequest,\n headers: PutV1RoutinesRoutineidHeaderParams,\n config: Partial<RequestConfig<PutV1RoutinesRoutineidMutationRequest>> & {\n client?: Client;\n } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const requestData = data;\n\n const res = await request<\n PutV1RoutinesRoutineidMutationResponse,\n ResponseErrorConfig<PutV1RoutinesRoutineid400 | PutV1RoutinesRoutineid404>,\n PutV1RoutinesRoutineidMutationRequest\n >({\n method: \"PUT\",\n url: getPutV1RoutinesRoutineidUrl(routineId).url.toString(),\n data: requestData,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","/**\n * Generated by Kubb (https://kubb.dev/).\n * Do not edit manually.\n */\n\nimport type {\n Client,\n RequestConfig,\n ResponseErrorConfig,\n} from \"../../.kubb/fetch.ts\";\nimport type {\n PutV1WorkoutsWorkoutidMutationRequest,\n PutV1WorkoutsWorkoutidMutationResponse,\n PutV1WorkoutsWorkoutidPathParams,\n PutV1WorkoutsWorkoutidHeaderParams,\n PutV1WorkoutsWorkoutid400,\n} from \"../types/PutV1WorkoutsWorkoutid.ts\";\nimport { fetch } from \"../../.kubb/fetch.ts\";\n\nfunction getPutV1WorkoutsWorkoutidUrl(\n workoutId: PutV1WorkoutsWorkoutidPathParams[\"workoutId\"],\n) {\n const res = { method: \"PUT\", url: `/v1/workouts/${workoutId}` as const };\n return res;\n}\n\n/**\n * @summary Update an existing workout\n * {@link /v1/workouts/:workoutId}\n */\nexport async function putV1WorkoutsWorkoutid(\n workoutId: PutV1WorkoutsWorkoutidPathParams[\"workoutId\"],\n data: PutV1WorkoutsWorkoutidMutationRequest,\n headers: PutV1WorkoutsWorkoutidHeaderParams,\n config: Partial<RequestConfig<PutV1WorkoutsWorkoutidMutationRequest>> & {\n client?: Client;\n } = {},\n) {\n const { client: request = fetch, ...requestConfig } = config;\n\n const requestData = data;\n\n const res = await request<\n PutV1WorkoutsWorkoutidMutationResponse,\n ResponseErrorConfig<PutV1WorkoutsWorkoutid400>,\n PutV1WorkoutsWorkoutidMutationRequest\n >({\n method: \"PUT\",\n url: getPutV1WorkoutsWorkoutidUrl(workoutId).url.toString(),\n data: requestData,\n ...requestConfig,\n headers: { ...headers, ...requestConfig.headers },\n });\n return res.data;\n}\n","import type {\n\tRequestConfig,\n\tResponseConfig,\n} from \"../generated/.kubb/fetch.ts\";\nimport { SpanStatusCode, type Span } from \"@opentelemetry/api\";\nimport axios, {\n\tisAxiosError,\n\ttype AxiosError,\n\ttype AxiosInstance,\n\ttype AxiosRequestConfig,\n\ttype InternalAxiosRequestConfig,\n} from \"axios\";\nimport * as api from \"../generated/client/api\";\nimport { tracer } from \"./telemetry.js\";\nimport { apiCalls, apiDuration } from \"./metrics.js\";\nimport type {\n\tGetV1BodyMeasurementsQueryParams,\n\tGetV1ExerciseHistoryExercisetemplateidQueryParams,\n\tGetV1ExerciseTemplatesQueryParams,\n\tGetV1RoutineFoldersQueryParams,\n\tGetV1RoutinesQueryParams,\n\tGetV1WorkoutsEventsQueryParams,\n\tGetV1WorkoutsQueryParams,\n\tPostV1BodyMeasurementsMutationRequest,\n\tPostV1ExerciseTemplatesMutationRequest,\n\tPostV1RoutineFoldersMutationRequest,\n\tPostV1RoutinesMutationRequest,\n\tPostV1WorkoutsMutationRequest,\n\tPutV1BodyMeasurementsDateMutationRequest,\n\tPutV1RoutinesRoutineidMutationRequest,\n\tPutV1WorkoutsWorkoutidMutationRequest,\n} from \"../generated/client/types\";\n\n// Define a proper client type that matches the Kubb client interface\ntype KubbClient = {\n\t<TData, _TError = unknown, TVariables = unknown>(\n\t\tconfig: RequestConfig<TVariables>,\n\t): Promise<ResponseConfig<TData>>;\n\tgetConfig: () => Partial<RequestConfig<unknown>>;\n\tsetConfig: (config: RequestConfig) => Partial<RequestConfig<unknown>>;\n};\n\n/**\n * Type-safe wrapper helper that enforces parameter types match the generated API.\n * This prevents arg-order regressions by using Parameters<> to extract expected types.\n *\n * Usage: wrapApi(api.postV1ExerciseTemplates)(data, headers, { client })\n * TypeScript will error if arguments don't match the generated signature.\n */\nfunction wrapApi<T extends (...args: Parameters<T>) => ReturnType<T>>(\n\tfn: T,\n): (...args: Parameters<T>) => ReturnType<T> {\n\treturn fn;\n}\n\nexport const DEFAULT_API_TIMEOUT_MS = 30_000;\nexport const MAX_GET_RETRIES = 3;\nexport const RETRY_BACKOFF_BASE_MS = 300;\nconst RETRY_BACKOFF_MAX_MS = 5_000;\n\nexport const HEVY_RETRY_EXHAUSTED_ERROR_CODE = \"HEVY_RETRY_EXHAUSTED\";\n\nconst RETRYABLE_STATUS_CODES = new Set([408, 429, 500, 502, 503, 504]);\n\nconst RETRYABLE_NETWORK_ERROR_CODES = new Set([\n\t\"ECONNABORTED\",\n\t\"ECONNREFUSED\",\n\t\"ECONNRESET\",\n\t\"EAI_AGAIN\",\n\t\"ENETUNREACH\",\n\t\"ENOTFOUND\",\n\t\"ERR_NETWORK\",\n\t\"ERR_SOCKET_TIMEOUT\",\n\t\"ETIMEDOUT\",\n]);\n\ntype RetryAwareAxiosError = AxiosError & {\n\thevyRetryCount?: number;\n\thevyRetryExhausted?: boolean;\n\thevyRetryStatus?: number;\n\thevyRetryOriginalCode?: string;\n};\n\nfunction getApiTimeoutMs(): number {\n\tconst rawValue = process.env.HEVY_MCP_API_TIMEOUT;\n\tif (!rawValue) {\n\t\treturn DEFAULT_API_TIMEOUT_MS;\n\t}\n\n\tconst parsed = Number(rawValue);\n\tif (!Number.isFinite(parsed) || parsed <= 0) {\n\t\treturn DEFAULT_API_TIMEOUT_MS;\n\t}\n\n\treturn Math.trunc(parsed);\n}\n\nfunction sleep(ms: number): Promise<void> {\n\treturn new Promise((resolve) => {\n\t\tsetTimeout(resolve, ms);\n\t});\n}\n\nfunction isGetRequest(config: RequestConfig<unknown>): boolean {\n\treturn config.method?.toUpperCase() === \"GET\";\n}\n\nfunction isRetryableStatus(status: number | undefined): boolean {\n\tif (status === undefined) {\n\t\treturn false;\n\t}\n\n\treturn RETRYABLE_STATUS_CODES.has(status);\n}\n\nfunction isTransientNetworkError(error: AxiosError): boolean {\n\tif (error.code === \"ERR_CANCELED\") {\n\t\treturn false;\n\t}\n\n\tif (error.code && RETRYABLE_NETWORK_ERROR_CODES.has(error.code)) {\n\t\treturn true;\n\t}\n\n\tif (error.response) {\n\t\treturn false;\n\t}\n\n\tconst message = error.message.toLowerCase();\n\treturn (\n\t\tmessage.includes(\"network\") ||\n\t\tmessage.includes(\"socket hang up\") ||\n\t\tmessage.includes(\"timeout\")\n\t);\n}\n\nfunction normalizeHeaderValue(value: unknown): string | undefined {\n\tif (typeof value === \"string\") {\n\t\tconst trimmed = value.trim();\n\t\treturn trimmed.length > 0 ? trimmed : undefined;\n\t}\n\n\tif (typeof value === \"number\" && Number.isFinite(value)) {\n\t\treturn String(value);\n\t}\n\n\tif (Array.isArray(value) && value.length > 0) {\n\t\treturn normalizeHeaderValue(value[0]);\n\t}\n\n\treturn undefined;\n}\n\nfunction getHeaderValue(headers: unknown, key: string): string | undefined {\n\tif (!headers || typeof headers !== \"object\") {\n\t\treturn undefined;\n\t}\n\n\tif (\n\t\t\"get\" in headers &&\n\t\ttypeof (headers as { get?: unknown }).get === \"function\"\n\t) {\n\t\tconst value = (\n\t\t\theaders as {\n\t\t\t\tget: (headerName: string) => unknown;\n\t\t\t}\n\t\t).get(key);\n\t\treturn normalizeHeaderValue(value);\n\t}\n\n\tconst headerRecord = headers as Record<string, unknown>;\n\treturn normalizeHeaderValue(\n\t\theaderRecord[key] ??\n\t\t\theaderRecord[key.toLowerCase()] ??\n\t\t\theaderRecord[key.toUpperCase()],\n\t);\n}\n\nfunction parseRetryAfterMs(value: string): number | undefined {\n\tconst numericSeconds = Number(value);\n\tif (Number.isFinite(numericSeconds) && numericSeconds >= 0) {\n\t\treturn Math.min(RETRY_BACKOFF_MAX_MS, Math.round(numericSeconds * 1000));\n\t}\n\n\tconst dateMillis = Date.parse(value);\n\tif (Number.isNaN(dateMillis)) {\n\t\treturn undefined;\n\t}\n\n\treturn Math.min(RETRY_BACKOFF_MAX_MS, Math.max(0, dateMillis - Date.now()));\n}\n\nfunction getRetryAfterDelayMs(error: AxiosError): number | undefined {\n\tif (error.response?.status !== 429) {\n\t\treturn undefined;\n\t}\n\n\tconst retryAfterHeader = getHeaderValue(\n\t\terror.response.headers,\n\t\t\"retry-after\",\n\t);\n\tif (!retryAfterHeader) {\n\t\treturn undefined;\n\t}\n\n\treturn parseRetryAfterMs(retryAfterHeader);\n}\n\nfunction getExponentialBackoffMs(retryAttempt: number): number {\n\tconst exponent = Math.max(0, retryAttempt - 1);\n\tconst delay = RETRY_BACKOFF_BASE_MS * 2 ** exponent;\n\treturn Math.min(RETRY_BACKOFF_MAX_MS, delay);\n}\n\nfunction getRetryDelayMs(error: AxiosError, retryAttempt: number): number {\n\tconst exponentialDelay = getExponentialBackoffMs(retryAttempt);\n\tconst retryAfterDelay = getRetryAfterDelayMs(error);\n\n\tif (retryAfterDelay === undefined) {\n\t\treturn exponentialDelay;\n\t}\n\n\treturn Math.min(\n\t\tRETRY_BACKOFF_MAX_MS,\n\t\tMath.max(exponentialDelay, retryAfterDelay),\n\t);\n}\n\nfunction shouldRetryRequest(\n\tconfig: RequestConfig<unknown>,\n\terror: AxiosError,\n): boolean {\n\tif (!isGetRequest(config)) {\n\t\treturn false;\n\t}\n\n\treturn (\n\t\tisRetryableStatus(error.response?.status) || isTransientNetworkError(error)\n\t);\n}\n\nfunction markRetryExhausted(error: AxiosError, retryCount: number): void {\n\tconst retryError = error as RetryAwareAxiosError;\n\tretryError.hevyRetryExhausted = true;\n\tretryError.hevyRetryCount = retryCount;\n\tretryError.hevyRetryStatus = error.response?.status;\n\n\tif (retryError.code) {\n\t\tretryError.hevyRetryOriginalCode = retryError.code;\n\t}\n\n\tretryError.code = HEVY_RETRY_EXHAUSTED_ERROR_CODE;\n}\n\nasync function requestWithRetries<TData, TVariables>(\n\taxiosInstance: AxiosInstance,\n\tconfig: RequestConfig<TVariables>,\n): Promise<ResponseConfig<TData>> {\n\tlet retryCount = 0;\n\n\twhile (true) {\n\t\ttry {\n\t\t\treturn await axiosInstance.request<\n\t\t\t\tTData,\n\t\t\t\tResponseConfig<TData>,\n\t\t\t\tTVariables\n\t\t\t>(config as AxiosRequestConfig<TVariables>);\n\t\t} catch (error) {\n\t\t\tif (!isAxiosError(error)) {\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tconst normalizedConfig = config as RequestConfig<unknown>;\n\t\t\tif (!shouldRetryRequest(normalizedConfig, error)) {\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tif (retryCount >= MAX_GET_RETRIES) {\n\t\t\t\tmarkRetryExhausted(error, retryCount);\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tretryCount += 1;\n\t\t\tconst retryDelayMs = getRetryDelayMs(error, retryCount);\n\t\t\tawait sleep(retryDelayMs);\n\t\t}\n\t}\n}\n\nfunction createResilientClient(axiosInstance: AxiosInstance): KubbClient {\n\tlet clientConfig: Partial<RequestConfig<unknown>> = {\n\t\tbaseURL: axiosInstance.defaults.baseURL,\n\t};\n\n\tconst resilientClient = (async <\n\t\tTData,\n\t\t_TError = unknown,\n\t\tTVariables = unknown,\n\t>(\n\t\tconfig: RequestConfig<TVariables>,\n\t): Promise<ResponseConfig<TData>> => {\n\t\treturn requestWithRetries<TData, TVariables>(axiosInstance, config);\n\t}) as KubbClient;\n\n\tresilientClient.getConfig = () => ({\n\t\t...clientConfig,\n\t});\n\n\tresilientClient.setConfig = (config: RequestConfig) => {\n\t\tclientConfig = {\n\t\t\t...clientConfig,\n\t\t\t...config,\n\t\t};\n\n\t\tif (config.baseURL !== undefined) {\n\t\t\taxiosInstance.defaults.baseURL = config.baseURL;\n\t\t}\n\n\t\treturn resilientClient.getConfig();\n\t};\n\n\treturn resilientClient;\n}\n\n// --- Interceptor helpers ---\n\ntype TracedConfig = InternalAxiosRequestConfig & {\n\t_span?: Span;\n\t_startTime?: number;\n};\n\n/**\n * Extract common request metadata from an Axios config.\n * Shared between the success and error response interceptors to avoid\n * duplicating the method/url/endpoint/duration extraction logic.\n */\nfunction extractRequestMeta(config: {\n\tmethod?: string;\n\turl?: string;\n\t_startTime?: number;\n}) {\n\tconst method = (config.method ?? \"get\").toUpperCase();\n\tconst url = config.url ?? \"\";\n\tconst endpoint = url.split(\"?\")[0] ?? url;\n\tconst now = Date.now();\n\tconst durationMs = now - (config._startTime ?? now);\n\treturn { method, url, endpoint, durationMs };\n}\n\n/**\n * Finalize a traced span and record metrics for a completed HTTP request.\n */\nfunction finalizeRequestTrace(opts: {\n\tspan: Span | undefined;\n\tstatusCode: number;\n\tdurationMs: number;\n\tmethod: string;\n\tendpoint: string;\n\terror?: unknown;\n}) {\n\tconst { span, statusCode, durationMs, method, endpoint, error } = opts;\n\n\tif (span) {\n\t\tspan.setAttribute(\"http.status_code\", statusCode);\n\t\tspan.setAttribute(\"http.response.duration_ms\", durationMs);\n\t\tif (error) {\n\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\tspan.recordException(error as Error);\n\t\t} else {\n\t\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\t}\n\t\tspan.end();\n\t}\n\n\tapiCalls.add(1, { method, endpoint, status_code: statusCode });\n\tapiDuration.record(durationMs, { method, endpoint });\n}\n\nexport function createClient(\n\tapiKey: string,\n\tbaseUrl = \"https://api.hevyapp.com\",\n) {\n\t// Create an axios instance with the API key\n\tconst axiosInstance = axios.create({\n\t\tbaseURL: baseUrl,\n\t\ttimeout: getApiTimeoutMs(),\n\t\theaders: {\n\t\t\t\"api-key\": apiKey,\n\t\t},\n\t});\n\n\t// --- Axios interceptors for HTTP tracing and metrics ---\n\taxiosInstance.interceptors.request.use((config) => {\n\t\tconst tracedConfig = config as TracedConfig;\n\t\tconst method = (config.method ?? \"get\").toUpperCase();\n\t\tconst url = config.url ?? \"\";\n\t\t// Extract clean endpoint path without query params for high-cardinality safety\n\t\tconst endpoint = url.split(\"?\")[0] ?? url;\n\t\ttracedConfig._span = tracer.startSpan(`hevy.api.${method}`, {\n\t\t\tattributes: {\n\t\t\t\t\"http.method\": method,\n\t\t\t\t\"http.url\": url,\n\t\t\t\t\"http.base_url\": config.baseURL ?? \"\",\n\t\t\t\t\"hevy.api.endpoint\": endpoint,\n\t\t\t},\n\t\t});\n\t\ttracedConfig._startTime = Date.now();\n\t\treturn config;\n\t});\n\n\taxiosInstance.interceptors.response.use(\n\t\t(response) => {\n\t\t\tconst tracedConfig = response.config as TracedConfig;\n\t\t\tconst { method, endpoint, durationMs } = extractRequestMeta({\n\t\t\t\tmethod: response.config.method,\n\t\t\t\turl: response.config.url,\n\t\t\t\t_startTime: tracedConfig._startTime,\n\t\t\t});\n\n\t\t\tfinalizeRequestTrace({\n\t\t\t\tspan: tracedConfig._span,\n\t\t\t\tstatusCode: response.status,\n\t\t\t\tdurationMs,\n\t\t\t\tmethod,\n\t\t\t\tendpoint,\n\t\t\t});\n\n\t\t\treturn response;\n\t\t},\n\t\t(error) => {\n\t\t\tconst tracedConfig = (error.config ?? {}) as TracedConfig;\n\t\t\tconst { method, endpoint, durationMs } = extractRequestMeta({\n\t\t\t\tmethod: error.config?.method,\n\t\t\t\turl: error.config?.url,\n\t\t\t\t_startTime: tracedConfig._startTime,\n\t\t\t});\n\n\t\t\tfinalizeRequestTrace({\n\t\t\t\tspan: tracedConfig._span,\n\t\t\t\tstatusCode: error.response?.status ?? 0,\n\t\t\t\tdurationMs,\n\t\t\t\tmethod,\n\t\t\t\tendpoint,\n\t\t\t\terror,\n\t\t\t});\n\n\t\t\tthrow error;\n\t\t},\n\t);\n\n\t// Create headers object with API key\n\tconst headers = {\n\t\t\"api-key\": apiKey,\n\t};\n\n\tconst client = createResilientClient(axiosInstance);\n\n\t// Return an object with all the API methods using ReturnType for automatic type inference\n\t// All API calls use wrapApi to ensure TypeScript validates arg order matches generated API\n\treturn {\n\t\t// Workouts\n\t\tgetWorkouts: (\n\t\t\tparams?: GetV1WorkoutsQueryParams,\n\t\t): ReturnType<typeof api.getV1Workouts> =>\n\t\t\twrapApi(api.getV1Workouts)(headers, params, { client }),\n\t\tgetWorkout: (\n\t\t\tworkoutId: string,\n\t\t): ReturnType<typeof api.getV1WorkoutsWorkoutid> =>\n\t\t\twrapApi(api.getV1WorkoutsWorkoutid)(workoutId, headers, { client }),\n\t\tcreateWorkout: (\n\t\t\tdata: PostV1WorkoutsMutationRequest,\n\t\t): ReturnType<typeof api.postV1Workouts> =>\n\t\t\twrapApi(api.postV1Workouts)(data, headers, { client }),\n\t\tupdateWorkout: (\n\t\t\tworkoutId: string,\n\t\t\tdata: PutV1WorkoutsWorkoutidMutationRequest,\n\t\t): ReturnType<typeof api.putV1WorkoutsWorkoutid> =>\n\t\t\twrapApi(api.putV1WorkoutsWorkoutid)(workoutId, data, headers, {\n\t\t\t\tclient,\n\t\t\t}),\n\t\tgetWorkoutCount: (): ReturnType<typeof api.getV1WorkoutsCount> =>\n\t\t\twrapApi(api.getV1WorkoutsCount)(headers, { client }),\n\t\tgetWorkoutEvents: (\n\t\t\tparams?: GetV1WorkoutsEventsQueryParams,\n\t\t): ReturnType<typeof api.getV1WorkoutsEvents> =>\n\t\t\twrapApi(api.getV1WorkoutsEvents)(headers, params, { client }),\n\n\t\t// Routines\n\t\tgetRoutines: (\n\t\t\tparams?: GetV1RoutinesQueryParams,\n\t\t): ReturnType<typeof api.getV1Routines> =>\n\t\t\twrapApi(api.getV1Routines)(headers, params, { client }),\n\t\tgetRoutineById: (\n\t\t\troutineId: string,\n\t\t): ReturnType<typeof api.getV1RoutinesRoutineid> =>\n\t\t\twrapApi(api.getV1RoutinesRoutineid)(routineId, headers, { client }),\n\t\tcreateRoutine: (\n\t\t\tdata: PostV1RoutinesMutationRequest,\n\t\t): ReturnType<typeof api.postV1Routines> =>\n\t\t\twrapApi(api.postV1Routines)(data, headers, { client }),\n\t\tupdateRoutine: (\n\t\t\troutineId: string,\n\t\t\tdata: PutV1RoutinesRoutineidMutationRequest,\n\t\t): ReturnType<typeof api.putV1RoutinesRoutineid> =>\n\t\t\twrapApi(api.putV1RoutinesRoutineid)(routineId, data, headers, {\n\t\t\t\tclient,\n\t\t\t}),\n\n\t\t// Exercise Templates\n\t\tgetExerciseTemplates: (\n\t\t\tparams?: GetV1ExerciseTemplatesQueryParams,\n\t\t): ReturnType<typeof api.getV1ExerciseTemplates> =>\n\t\t\twrapApi(api.getV1ExerciseTemplates)(headers, params, { client }),\n\t\tgetExerciseTemplate: (\n\t\t\ttemplateId: string,\n\t\t): ReturnType<typeof api.getV1ExerciseTemplatesExercisetemplateid> =>\n\t\t\twrapApi(api.getV1ExerciseTemplatesExercisetemplateid)(\n\t\t\t\ttemplateId,\n\t\t\t\theaders,\n\t\t\t\t{\n\t\t\t\t\tclient,\n\t\t\t\t},\n\t\t\t),\n\t\tgetExerciseHistory: (\n\t\t\texerciseTemplateId: string,\n\t\t\tparams?: GetV1ExerciseHistoryExercisetemplateidQueryParams,\n\t\t): ReturnType<typeof api.getV1ExerciseHistoryExercisetemplateid> =>\n\t\t\twrapApi(api.getV1ExerciseHistoryExercisetemplateid)(\n\t\t\t\texerciseTemplateId,\n\t\t\t\theaders,\n\t\t\t\tparams,\n\t\t\t\t{ client },\n\t\t\t),\n\t\tcreateExerciseTemplate: (\n\t\t\tdata: PostV1ExerciseTemplatesMutationRequest,\n\t\t): ReturnType<typeof api.postV1ExerciseTemplates> =>\n\t\t\twrapApi(api.postV1ExerciseTemplates)(data, headers, { client }),\n\n\t\t// Routine Folders\n\t\tgetRoutineFolders: (\n\t\t\tparams?: GetV1RoutineFoldersQueryParams,\n\t\t): ReturnType<typeof api.getV1RoutineFolders> =>\n\t\t\twrapApi(api.getV1RoutineFolders)(headers, params, { client }),\n\t\tcreateRoutineFolder: (\n\t\t\tdata: PostV1RoutineFoldersMutationRequest,\n\t\t): ReturnType<typeof api.postV1RoutineFolders> =>\n\t\t\twrapApi(api.postV1RoutineFolders)(data, headers, { client }),\n\t\tgetRoutineFolder: (\n\t\t\tfolderId: string,\n\t\t): ReturnType<typeof api.getV1RoutineFoldersFolderid> =>\n\t\t\twrapApi(api.getV1RoutineFoldersFolderid)(folderId, headers, {\n\t\t\t\tclient,\n\t\t\t}),\n\n\t\t// Body Measurements\n\t\tgetBodyMeasurements: (\n\t\t\tparams?: GetV1BodyMeasurementsQueryParams,\n\t\t): ReturnType<typeof api.getV1BodyMeasurements> =>\n\t\t\twrapApi(api.getV1BodyMeasurements)(headers, params, { client }),\n\t\tgetBodyMeasurement: (\n\t\t\tdate: string,\n\t\t): ReturnType<typeof api.getV1BodyMeasurementsDate> =>\n\t\t\twrapApi(api.getV1BodyMeasurementsDate)(date, headers, { client }),\n\t\tcreateBodyMeasurement: (\n\t\t\tdata: PostV1BodyMeasurementsMutationRequest,\n\t\t): ReturnType<typeof api.postV1BodyMeasurements> =>\n\t\t\twrapApi(api.postV1BodyMeasurements)(data, headers, { client }),\n\t\tupdateBodyMeasurement: (\n\t\t\tdate: string,\n\t\t\tdata: PutV1BodyMeasurementsDateMutationRequest,\n\t\t): ReturnType<typeof api.putV1BodyMeasurementsDate> =>\n\t\t\twrapApi(api.putV1BodyMeasurementsDate)(date, data, headers, {\n\t\t\t\tclient,\n\t\t\t}),\n\n\t\t// User\n\t\tgetUserInfo: (): ReturnType<typeof api.getV1UserInfo> =>\n\t\t\twrapApi(api.getV1UserInfo)(headers, { client }),\n\t};\n}\n\n/**\n * Type representing the Hevy API client returned by createClient.\n * Useful for typing variables that hold the client instance.\n */\nexport type HevyApiClient = ReturnType<typeof createClient>;\n","// Import the Kubb-based client\nimport { createClient as createKubbClient } from \"./hevyClientKubb.js\";\n\nexport function createClient(apiKey: string, baseUrl: string) {\n\treturn createKubbClient(apiKey, baseUrl);\n}\n\n// Export the HevyClient type for use in other modules\nexport type HevyClient = ReturnType<typeof createClient>;\n","import { SpanStatusCode } from \"@opentelemetry/api\";\nimport type { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { deserializeMessage } from \"@modelcontextprotocol/sdk/shared/stdio.js\";\nimport type { JSONRPCMessage } from \"@modelcontextprotocol/sdk/types.js\";\nimport { Sentry, tracer } from \"./telemetry.js\";\nimport { stdioParseErrors } from \"./metrics.js\";\n\nconst UTF8_BOM = \"\\uFEFF\";\n\nexport interface StdioChunkSnapshot {\n\tlastChunkByteLength: number;\n\tlastChunkStartsWithUtf8Bom: boolean;\n}\n\ninterface MutableReadBuffer {\n\t_buffer?: Buffer;\n\treadMessage: () => JSONRPCMessage | null;\n}\n\ntype MutableStdioServerTransport = {\n\t_readBuffer?: MutableReadBuffer;\n\t_ondata?: (chunk: Buffer) => void;\n};\n\ninterface SdkPrivateStdioAdapter {\n\twrapOnData: (onChunk: (chunk: Buffer) => void) => void;\n\tinstallReadMessageHook: (\n\t\tonReadLine: (line: string) => JSONRPCMessage,\n\t) => boolean;\n}\n\n/**\n * Adapter boundary around MCP SDK stdio internals.\n *\n * MCP SDK v1.29.0 exposes public message-level hooks but does not expose a\n * public raw-chunk hook on `StdioServerTransport`. To capture chunk metadata,\n * we currently rely on private internals (`_ondata`, `_readBuffer`, `_buffer`)\n * in this one place.\n *\n * If those internals change in a future SDK release, this adapter should fail\n * closed and preserve default transport behavior (no instrumentation patching).\n */\nfunction createSdkPrivateStdioAdapter(\n\ttransport: StdioServerTransport,\n): SdkPrivateStdioAdapter {\n\tconst mutableTransport = transport as unknown as MutableStdioServerTransport;\n\n\treturn {\n\t\twrapOnData(onChunk) {\n\t\t\tconst originalOnData = mutableTransport._ondata;\n\t\t\tif (typeof originalOnData !== \"function\") {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tmutableTransport._ondata = (chunk: Buffer) => {\n\t\t\t\tonChunk(chunk);\n\t\t\t\toriginalOnData(chunk);\n\t\t\t};\n\t\t},\n\t\tinstallReadMessageHook(onReadLine) {\n\t\t\tconst readBuffer = mutableTransport._readBuffer;\n\t\t\tif (!readBuffer || typeof readBuffer.readMessage !== \"function\") {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\treadBuffer.readMessage = () => {\n\t\t\t\tconst buffer = readBuffer._buffer;\n\t\t\t\tif (!buffer) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tconst index = buffer.indexOf(\"\\n\");\n\t\t\t\tif (index === -1) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\n\t\t\t\tconst lineBuffer = buffer.subarray(0, index);\n\t\t\t\treadBuffer._buffer = buffer.subarray(index + 1);\n\t\t\t\tconst line = lineBuffer.toString(\"utf8\").replace(/\\r$/, \"\");\n\t\t\t\treturn onReadLine(line);\n\t\t\t};\n\n\t\t\treturn true;\n\t\t},\n\t};\n}\n\nfunction hasUtf8BomPrefix(chunk: Buffer): boolean {\n\treturn (\n\t\tchunk.length >= 3 &&\n\t\tchunk[0] === 0xef &&\n\t\tchunk[1] === 0xbb &&\n\t\tchunk[2] === 0xbf\n\t);\n}\n\nfunction parseFailurePosition(error: unknown): number | null {\n\tif (!(error instanceof Error)) {\n\t\treturn null;\n\t}\n\n\tconst match = error.message.match(/position\\s+(\\d+)/i);\n\tif (!match || !match[1]) {\n\t\treturn null;\n\t}\n\n\tconst position = Number.parseInt(match[1], 10);\n\treturn Number.isFinite(position) ? position : null;\n}\n\nfunction getFailureLocation(\n\tfailurePosition: number | null,\n\tlineHadLeadingBom: boolean,\n): string {\n\tif (lineHadLeadingBom) {\n\t\treturn \"line_start_bom\";\n\t}\n\tif (failurePosition === 0) {\n\t\treturn \"line_start\";\n\t}\n\tif (failurePosition !== null) {\n\t\treturn \"line_body\";\n\t}\n\treturn \"unknown\";\n}\n\nexport function deserializeMessageWithObservability(\n\tline: string,\n\tchunkSnapshot: StdioChunkSnapshot,\n): JSONRPCMessage {\n\tconst lineHadLeadingBom = line.startsWith(UTF8_BOM);\n\tconst normalizedLine = lineHadLeadingBom ? line.slice(1) : line;\n\tconst lineByteLength = Buffer.byteLength(line);\n\n\treturn tracer.startActiveSpan(\n\t\t\"mcp.stdio.deserialize\",\n\t\t{\n\t\t\tattributes: {\n\t\t\t\t\"mcp.transport\": \"stdio\",\n\t\t\t\t\"mcp.stdio.parse.line.char_length\": line.length,\n\t\t\t\t\"mcp.stdio.parse.line.byte_length\": lineByteLength,\n\t\t\t\t\"mcp.stdio.parse.line.had_leading_bom\": lineHadLeadingBom,\n\t\t\t\t\"mcp.stdio.parse.line.bom_stripped\": lineHadLeadingBom,\n\t\t\t\t\"mcp.stdio.parse.chunk.last_byte_length\":\n\t\t\t\t\tchunkSnapshot.lastChunkByteLength,\n\t\t\t\t\"mcp.stdio.parse.chunk.last_had_utf8_bom\":\n\t\t\t\t\tchunkSnapshot.lastChunkStartsWithUtf8Bom,\n\t\t\t},\n\t\t},\n\t\t(span) => {\n\t\t\ttry {\n\t\t\t\tconst message = deserializeMessage(normalizedLine);\n\t\t\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\t\t\tif (message && typeof message === \"object\" && \"method\" in message) {\n\t\t\t\t\tspan.setAttribute(\n\t\t\t\t\t\t\"mcp.method\",\n\t\t\t\t\t\tString((message as { method: unknown }).method),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn message;\n\t\t\t} catch (error) {\n\t\t\t\tconst failurePosition = parseFailurePosition(error);\n\t\t\t\tconst failureLocation = getFailureLocation(\n\t\t\t\t\tfailurePosition,\n\t\t\t\t\tlineHadLeadingBom,\n\t\t\t\t);\n\n\t\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\t\tspan.recordException(error as Error);\n\t\t\t\tspan.setAttribute(\"mcp.stdio.parse.failure.location\", failureLocation);\n\t\t\t\tif (failurePosition !== null) {\n\t\t\t\t\tspan.setAttribute(\n\t\t\t\t\t\t\"mcp.stdio.parse.failure.position\",\n\t\t\t\t\t\tfailurePosition,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tstdioParseErrors.add(1, { failure_location: failureLocation });\n\n\t\t\t\tSentry.withScope((scope) => {\n\t\t\t\t\tscope.setTag(\"mcp.transport\", \"stdio\");\n\t\t\t\t\tscope.setTag(\"mcp.stdio.parse.failure.location\", failureLocation);\n\t\t\t\t\tscope.setContext(\"mcpStdioParse\", {\n\t\t\t\t\t\tlineCharLength: line.length,\n\t\t\t\t\t\tlineByteLength,\n\t\t\t\t\t\tlineHadLeadingBom,\n\t\t\t\t\t\tbomStripped: lineHadLeadingBom,\n\t\t\t\t\t\tlastChunkByteLength: chunkSnapshot.lastChunkByteLength,\n\t\t\t\t\t\tlastChunkStartsWithUtf8Bom:\n\t\t\t\t\t\t\tchunkSnapshot.lastChunkStartsWithUtf8Bom,\n\t\t\t\t\t\tfailureLocation,\n\t\t\t\t\t\tfailurePosition,\n\t\t\t\t\t\tfailureStage: \"deserializeMessage\",\n\t\t\t\t\t\terrorName: error instanceof Error ? error.name : \"UnknownError\",\n\t\t\t\t\t});\n\t\t\t\t\tSentry.captureException(error);\n\t\t\t\t});\n\n\t\t\t\tthrow error;\n\t\t\t} finally {\n\t\t\t\tspan.end();\n\t\t\t}\n\t\t},\n\t);\n}\n\nexport function createInstrumentedStdioTransport<\n\tT extends StdioServerTransport,\n>(transport: T): T {\n\tconst privateAdapter = createSdkPrivateStdioAdapter(transport);\n\tlet lastChunkSnapshot: StdioChunkSnapshot = {\n\t\tlastChunkByteLength: 0,\n\t\tlastChunkStartsWithUtf8Bom: false,\n\t};\n\n\tprivateAdapter.wrapOnData((chunk) => {\n\t\tlastChunkSnapshot = {\n\t\t\tlastChunkByteLength: chunk.byteLength,\n\t\t\tlastChunkStartsWithUtf8Bom: hasUtf8BomPrefix(chunk),\n\t\t};\n\t});\n\n\tconst didInstallReadMessageHook = privateAdapter.installReadMessageHook(\n\t\t(line) => deserializeMessageWithObservability(line, lastChunkSnapshot),\n\t);\n\tif (!didInstallReadMessageHook) {\n\t\treturn transport;\n\t}\n\n\treturn transport;\n}\n","// Telemetry must be initialized before any other imports so that\n// OpenTelemetry and Sentry are ready before application code runs.\nimport {\n\tSentry,\n\ttracer,\n\tserviceName,\n\tserviceVersion,\n\tsetCurrentUserId,\n} from \"./utils/telemetry.js\";\nimport { serverStartups } from \"./utils/metrics.js\";\n\nimport { SpanStatusCode } from \"@opentelemetry/api\";\nimport { createHmac } from \"node:crypto\";\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/sdk/server/stdio.js\";\nimport { z } from \"zod\";\nimport { registerBodyMeasurementTools } from \"./tools/body-measurements.js\";\nimport { registerFolderTools } from \"./tools/folders.js\";\nimport { registerRoutineTools } from \"./tools/routines.js\";\nimport { registerTemplateTools } from \"./tools/templates.js\";\nimport { registerUserTools } from \"./tools/user.js\";\nimport { registerWorkoutTools } from \"./tools/workouts.js\";\nimport { assertApiKey, parseConfig } from \"./utils/config.js\";\nimport { createClient } from \"./utils/hevyClient.js\";\nimport { createInstrumentedStdioTransport } from \"./utils/stdio-observability.js\";\n\nconst name = serviceName;\nconst version = serviceVersion;\n\nconst HELP_TEXT = [\n\t\"Usage:\",\n\t\" hevy-mcp [options]\",\n\t\"\",\n\t\"Options:\",\n\t\" -h, --help Show this help message and exit\",\n\t\" -v, --version Show version and exit\",\n\t\" --hevy-api-key=<api-key> (deprecated, use HEVY_API_KEY env var)\",\n\t\"\",\n\t\"Environment:\",\n\t\" HEVY_API_KEY=<api-key> Hevy API key from Hevy app settings\",\n\t\"\",\n\t\"Examples:\",\n\t\" HEVY_API_KEY=your-key npx hevy-mcp\",\n\t\" npx hevy-mcp --hevy-api-key=your-key\",\n\t\" npm start -- --hevy-api-key=your-key\",\n].join(\"\\n\");\n\nfunction getCliAction(args: string[]): \"start\" | \"version\" | \"help\" {\n\tfor (const arg of args) {\n\t\tif (arg === \"--version\" || arg === \"-v\") {\n\t\t\treturn \"version\";\n\t\t}\n\n\t\tif (arg === \"--help\" || arg === \"-h\") {\n\t\t\treturn \"help\";\n\t\t}\n\t}\n\n\treturn \"start\";\n}\n\nconst HEVY_API_BASEURL = \"https://api.hevyapp.com\";\n\nconst SENTRY_USER_ID_CONTEXT = \"hevy-mcp:sentry-user-id:v1\";\n\nfunction fingerprintApiKey(apiKey: string) {\n\t// HMAC-SHA-256 gives Sentry a deterministic pseudonymous user ID without\n\t// sending, logging, or storing the raw Hevy API key.\n\treturn createHmac(\"sha256\", apiKey)\n\t\t.update(SENTRY_USER_ID_CONTEXT)\n\t\t.digest(\"hex\");\n}\n\nconst serverConfigSchema = z.object({\n\tapiKey: z\n\t\t.string()\n\t\t.min(1, \"Hevy API key is required\")\n\t\t.describe(\"Your Hevy API key (available in the Hevy app settings).\"),\n});\n\nexport const configSchema = serverConfigSchema;\ntype ServerConfig = z.infer<typeof serverConfigSchema>;\n\nfunction buildServer(apiKey: string) {\n\tconst userId = fingerprintApiKey(apiKey);\n\n\treturn tracer.startActiveSpan(\n\t\t\"mcp.server.build\",\n\t\t{\n\t\t\tattributes: {\n\t\t\t\t\"mcp.server.name\": name,\n\t\t\t\t\"mcp.server.version\": version,\n\t\t\t\t\"mcp.transport\": \"stdio\",\n\t\t\t\t\"user.id\": userId,\n\t\t\t},\n\t\t},\n\t\t(span) => {\n\t\t\ttry {\n\t\t\t\tSentry.setUser({ id: userId });\n\t\t\t\tsetCurrentUserId(userId);\n\n\t\t\t\tconst baseServer = new McpServer({\n\t\t\t\t\tname,\n\t\t\t\t\tversion,\n\t\t\t\t});\n\t\t\t\tconst server = Sentry.wrapMcpServerWithSentry(baseServer);\n\n\t\t\t\tconst hevyClient = tracer.startActiveSpan(\n\t\t\t\t\t\"mcp.hevy-client.initialize\",\n\t\t\t\t\t(childSpan) => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\treturn createClient(apiKey, HEVY_API_BASEURL);\n\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\tchildSpan.end();\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t);\n\t\t\t\tconsole.error(\"Hevy client initialized with API key\");\n\n\t\t\t\ttracer.startActiveSpan(\n\t\t\t\t\t\"mcp.tools.register\",\n\t\t\t\t\t{\n\t\t\t\t\t\tattributes: {\n\t\t\t\t\t\t\t\"mcp.tools.count\": 6,\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\t(toolsSpan) => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tregisterWorkoutTools(server, hevyClient);\n\t\t\t\t\t\t\tregisterRoutineTools(server, hevyClient);\n\t\t\t\t\t\t\tregisterTemplateTools(server, hevyClient);\n\t\t\t\t\t\t\tregisterFolderTools(server, hevyClient);\n\t\t\t\t\t\t\tregisterBodyMeasurementTools(server, hevyClient);\n\t\t\t\t\t\t\tregisterUserTools(server, hevyClient);\n\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\ttoolsSpan.end();\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\t\t\treturn server;\n\t\t\t} catch (e) {\n\t\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\t\tthrow e;\n\t\t\t} finally {\n\t\t\t\tspan.end();\n\t\t\t}\n\t\t},\n\t);\n}\n\nexport function createServer({ config }: { config: ServerConfig }) {\n\tconst { apiKey } = serverConfigSchema.parse(config);\n\tconst server = buildServer(apiKey);\n\treturn server;\n}\n\nexport default createServer;\n\nexport async function runServer() {\n\tconst args = process.argv.slice(2);\n\tconst cliAction = getCliAction(args);\n\n\tif (cliAction === \"version\") {\n\t\tconsole.log(version);\n\t\treturn;\n\t}\n\n\tif (cliAction === \"help\") {\n\t\tconsole.log(HELP_TEXT);\n\t\treturn;\n\t}\n\n\tserverStartups.add(1, { version });\n\n\tawait tracer.startActiveSpan(\n\t\t\"mcp.server.run\",\n\t\t{\n\t\t\tattributes: {\n\t\t\t\t\"mcp.transport\": \"stdio\",\n\t\t\t},\n\t\t},\n\t\tasync (span) => {\n\t\t\ttry {\n\t\t\t\tconst cfg = parseConfig(args, process.env);\n\t\t\t\tconst apiKey = cfg.apiKey;\n\t\t\t\tassertApiKey(apiKey);\n\n\t\t\t\tconst server = buildServer(apiKey);\n\t\t\t\tconsole.error(\"Starting MCP server in stdio mode\");\n\t\t\t\tconst transport = createInstrumentedStdioTransport(\n\t\t\t\t\tnew StdioServerTransport(),\n\t\t\t\t);\n\n\t\t\t\tawait tracer.startActiveSpan(\n\t\t\t\t\t\"mcp.server.connect\",\n\t\t\t\t\t{\n\t\t\t\t\t\tattributes: {\n\t\t\t\t\t\t\t\"mcp.transport\": \"stdio\",\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tasync (connectSpan) => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tawait server.connect(transport);\n\t\t\t\t\t\t\tconnectSpan.setStatus({ code: SpanStatusCode.OK });\n\t\t\t\t\t\t} catch (e) {\n\t\t\t\t\t\t\tconnectSpan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\t\t\t\t\tthrow e;\n\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\tconnectSpan.end();\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t);\n\n\t\t\t\tspan.setStatus({ code: SpanStatusCode.OK });\n\t\t\t} catch (e) {\n\t\t\t\tspan.setStatus({ code: SpanStatusCode.ERROR });\n\t\t\t\tthrow e;\n\t\t\t} finally {\n\t\t\t\tspan.end();\n\t\t\t}\n\t\t},\n\t);\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hevy-mcp",
3
- "version": "1.26.2",
3
+ "version": "1.26.4",
4
4
  "description": "A Model Context Protocol (MCP) server implementation that interfaces with the Hevy fitness tracking app and its API.",
5
5
  "keywords": [
6
6
  "api",
@@ -96,6 +96,6 @@
96
96
  "vitest": "^4.1.9"
97
97
  },
98
98
  "engines": {
99
- "node": ">=26.0.0"
99
+ "node": ">=24.0.0"
100
100
  }
101
101
  }