hevy-mcp 2.0.0 → 3.0.0
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 +10 -6
- package/dist/cli.mjs +2 -2
- package/dist/index.mjs +2 -2
- package/dist/{src-c3mB-R0m.mjs → src-BBzEvkOX.mjs} +22 -54
- package/dist/src-BBzEvkOX.mjs.map +1 -0
- package/package.json +15 -2
- package/server.json +2 -2
- package/dist/src-c3mB-R0m.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -103,6 +103,12 @@ The server uses stdio, so `-i` keeps standard input open for the MCP client.
|
|
|
103
103
|
form forwards the variable from the host environment without putting the key
|
|
104
104
|
in the command arguments.
|
|
105
105
|
|
|
106
|
+
The image uses the official Node.js LTS Alpine base, runs as the non-root
|
|
107
|
+
`node` user, and ships the application and its third-party runtime dependencies
|
|
108
|
+
as a standalone bundle. It does not include an application `/app/node_modules`
|
|
109
|
+
directory; the official Node base image may still contain its own globally
|
|
110
|
+
packaged npm or Corepack files.
|
|
111
|
+
|
|
106
112
|
Use `latest` to follow the newest stable release. For reproducible deployments,
|
|
107
113
|
pin the exact version shown on the release, using a tag such as
|
|
108
114
|
`ghcr.io/chrisdoc/hevy-mcp:X.Y.Z`. Major (`:X`) and major.minor (`:X.Y`) tags
|
|
@@ -230,10 +236,6 @@ This bootstraps the `hevy-mcp` entry in your client config without manual JSON e
|
|
|
230
236
|
Supply your Hevy API key via the `HEVY_API_KEY` environment variable (in
|
|
231
237
|
`.env` or system environment).
|
|
232
238
|
|
|
233
|
-
> ⚠️ CLI API key arguments (`--hevy-api-key=...`, `--hevyApiKey=...`,
|
|
234
|
-
> `hevy-api-key=...`) are still accepted for backward compatibility, but are
|
|
235
|
-
> deprecated and insecure. Use `HEVY_API_KEY` instead.
|
|
236
|
-
|
|
237
239
|
Set `HEVY_MCP_API_TIMEOUT` to override the default 30-second Hevy API request
|
|
238
240
|
timeout. Its value is in milliseconds.
|
|
239
241
|
|
|
@@ -337,9 +339,11 @@ Compatibility note: with MCP SDK v1.29.0, clients using the default must send
|
|
|
337
339
|
- **Build**: `npm run build`
|
|
338
340
|
- **Lint/Format**: `npm run check` (uses oxlint/oxfmt)
|
|
339
341
|
- **Type Check**: `npm run check:types`
|
|
340
|
-
- **Unit Tests**: `
|
|
341
|
-
- **Full
|
|
342
|
+
- **Unit Tests**: `npm run test:unit`
|
|
343
|
+
- **Full Vitest Discovery**: `npm test` (builds first; live tests skip when
|
|
344
|
+
`HEVY_API_KEY` is absent)
|
|
342
345
|
- **Changeset Check**: `npm run check:changeset`
|
|
346
|
+
- **Tool Token Cost**: `npm run measure:tokens` ([measurement guide](./docs/token-cost-tracking.md))
|
|
343
347
|
|
|
344
348
|
For a detailed senior engineer guide, please refer to [AGENTS.md](./AGENTS.md).
|
|
345
349
|
|
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@
|
|
7
|
+
e.SENTRY_RELEASE = { id: "hevy-mcp@3.0.0" };
|
|
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-
|
|
12
|
+
import { r as runServer } from "./src-BBzEvkOX.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@
|
|
7
|
+
e.SENTRY_RELEASE = { id: "hevy-mcp@3.0.0" };
|
|
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-
|
|
12
|
+
import { n as createServer, r as runServer, t as configSchema } from "./src-BBzEvkOX.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@
|
|
7
|
+
e.SENTRY_RELEASE = { id: "hevy-mcp@3.0.0" };
|
|
8
8
|
var n = new e.Error().stack;
|
|
9
|
-
n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "
|
|
9
|
+
n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "06533ca8-0b74-40dd-a418-fc98c764276c", e._sentryDebugIdIdentifier = "sentry-dbid-06533ca8-0b74-40dd-a418-fc98c764276c");
|
|
10
10
|
} catch (e) {}
|
|
11
11
|
})();
|
|
12
12
|
import * as Sentry from "@sentry/node";
|
|
@@ -41,10 +41,10 @@ import semver from "semver";
|
|
|
41
41
|
* OTel Collector → Honeycomb: performance traces, metrics
|
|
42
42
|
*/
|
|
43
43
|
const name$1 = "hevy-mcp";
|
|
44
|
-
const version$1 = "
|
|
44
|
+
const version$1 = "3.0.0";
|
|
45
45
|
const collectorToken = "NH9vOela-HYreQxAbJa68cjEmORoEKM57EvneUDVcOo";
|
|
46
46
|
const COLLECTOR_ENDPOINT = "https://otel.chrisdoc.dev/v1";
|
|
47
|
-
const sentryRelease = process.env.SENTRY_RELEASE ?? `hevy-mcp@
|
|
47
|
+
const sentryRelease = process.env.SENTRY_RELEASE ?? `hevy-mcp@3.0.0`;
|
|
48
48
|
const resource = resourceFromAttributes({
|
|
49
49
|
"service.name": name$1,
|
|
50
50
|
"service.version": version$1
|
|
@@ -2110,43 +2110,20 @@ function registerWorkoutTools(server, hevyClient) {
|
|
|
2110
2110
|
}, "update-workout-operation"));
|
|
2111
2111
|
}
|
|
2112
2112
|
//#endregion
|
|
2113
|
+
//#region src/tools/register.ts
|
|
2114
|
+
/** Register every Hevy tool in its production ordering. */
|
|
2115
|
+
function registerHevyTools(server, hevyClient, options = {}) {
|
|
2116
|
+
registerWorkoutTools(server, hevyClient);
|
|
2117
|
+
registerRoutineTools(server, hevyClient);
|
|
2118
|
+
registerTemplateTools(server, hevyClient, { logger: options.logger });
|
|
2119
|
+
registerFolderTools(server, hevyClient);
|
|
2120
|
+
registerBodyMeasurementTools(server, hevyClient);
|
|
2121
|
+
registerUserTools(server, hevyClient);
|
|
2122
|
+
}
|
|
2123
|
+
//#endregion
|
|
2113
2124
|
//#region src/utils/config.ts
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
"(--hevy-api-key=..., --hevyApiKey=..., hevy-api-key=...) is",
|
|
2117
|
-
"deprecated and insecure. Use the HEVY_API_KEY environment",
|
|
2118
|
-
"variable instead."
|
|
2119
|
-
].join(" ");
|
|
2120
|
-
/**
|
|
2121
|
-
* Parse CLI arguments and environment to derive configuration.
|
|
2122
|
-
* Priority order for API key: deprecated CLI flag forms > environment variable.
|
|
2123
|
-
* Supported deprecated CLI arg forms:
|
|
2124
|
-
* --hevy-api-key=KEY
|
|
2125
|
-
* --hevyApiKey=KEY
|
|
2126
|
-
* hevy-api-key=KEY (bare, e.g. when passed after npm start -- )
|
|
2127
|
-
*/
|
|
2128
|
-
function parseConfig(argv, env) {
|
|
2129
|
-
let apiKey = "";
|
|
2130
|
-
let usedDeprecatedApiKeyArg = false;
|
|
2131
|
-
const apiKeyArgPatterns = [
|
|
2132
|
-
/^--hevy-api-key=(.+)$/i,
|
|
2133
|
-
/^--hevyApiKey=(.+)$/i,
|
|
2134
|
-
/^hevy-api-key=(.+)$/i
|
|
2135
|
-
];
|
|
2136
|
-
for (const raw of argv) {
|
|
2137
|
-
for (const pattern of apiKeyArgPatterns) {
|
|
2138
|
-
const m = raw.match(pattern);
|
|
2139
|
-
if (m) {
|
|
2140
|
-
apiKey = m[1];
|
|
2141
|
-
usedDeprecatedApiKeyArg = true;
|
|
2142
|
-
break;
|
|
2143
|
-
}
|
|
2144
|
-
}
|
|
2145
|
-
if (apiKey) break;
|
|
2146
|
-
}
|
|
2147
|
-
if (usedDeprecatedApiKeyArg) console.error(DEPRECATED_CLI_ARGUMENT_WARNING);
|
|
2148
|
-
if (!apiKey) apiKey = env.HEVY_API_KEY || "";
|
|
2149
|
-
return { apiKey };
|
|
2125
|
+
function parseConfig(env) {
|
|
2126
|
+
return { apiKey: env.HEVY_API_KEY || "" };
|
|
2150
2127
|
}
|
|
2151
2128
|
function assertApiKey(apiKey) {
|
|
2152
2129
|
if (!apiKey) {
|
|
@@ -3555,16 +3532,13 @@ const HELP_TEXT = [
|
|
|
3555
3532
|
"Options:",
|
|
3556
3533
|
" -h, --help Show this help message and exit",
|
|
3557
3534
|
" -v, --version Show version and exit",
|
|
3558
|
-
" --hevy-api-key=<api-key> (deprecated, use HEVY_API_KEY env var)",
|
|
3559
3535
|
"",
|
|
3560
3536
|
"Environment:",
|
|
3561
3537
|
" HEVY_API_KEY=<api-key> Hevy API key from Hevy app settings",
|
|
3562
3538
|
" HEVY_MCP_DEBUG=1 Enable verbose diagnostics on stderr",
|
|
3563
3539
|
"",
|
|
3564
3540
|
"Examples:",
|
|
3565
|
-
" HEVY_API_KEY=your-key npx hevy-mcp"
|
|
3566
|
-
" npx hevy-mcp --hevy-api-key=your-key",
|
|
3567
|
-
" npm start -- --hevy-api-key=your-key"
|
|
3541
|
+
" HEVY_API_KEY=your-key npx hevy-mcp"
|
|
3568
3542
|
].join("\n");
|
|
3569
3543
|
function getCliAction(args) {
|
|
3570
3544
|
for (const arg of args) {
|
|
@@ -3675,12 +3649,7 @@ function buildServer(apiKey) {
|
|
|
3675
3649
|
tracer.startActiveSpan("mcp.tools.register", (toolsSpan) => {
|
|
3676
3650
|
try {
|
|
3677
3651
|
const counting = createToolCountingServer(server);
|
|
3678
|
-
|
|
3679
|
-
registerRoutineTools(counting.server, hevyClient);
|
|
3680
|
-
registerTemplateTools(counting.server, hevyClient, { logger: clientLogger });
|
|
3681
|
-
registerFolderTools(counting.server, hevyClient);
|
|
3682
|
-
registerBodyMeasurementTools(counting.server, hevyClient);
|
|
3683
|
-
registerUserTools(counting.server, hevyClient);
|
|
3652
|
+
registerHevyTools(counting.server, hevyClient, { logger: clientLogger });
|
|
3684
3653
|
toolsSpan.setAttribute("mcp.tools.count", counting.getCount());
|
|
3685
3654
|
} finally {
|
|
3686
3655
|
toolsSpan.end();
|
|
@@ -3710,8 +3679,7 @@ async function createServer({ config }) {
|
|
|
3710
3679
|
return buildServer(apiKey);
|
|
3711
3680
|
}
|
|
3712
3681
|
async function runServer() {
|
|
3713
|
-
const
|
|
3714
|
-
const cliAction = getCliAction(args);
|
|
3682
|
+
const cliAction = getCliAction(process.argv.slice(2));
|
|
3715
3683
|
if (cliAction === "version") {
|
|
3716
3684
|
console.error(`${name} v${version}`);
|
|
3717
3685
|
return;
|
|
@@ -3723,7 +3691,7 @@ async function runServer() {
|
|
|
3723
3691
|
serverStartups.add(1, { version });
|
|
3724
3692
|
await tracer.startActiveSpan("mcp.server.run", { attributes: { "mcp.transport": "stdio" } }, async (span) => {
|
|
3725
3693
|
try {
|
|
3726
|
-
const apiKey = parseConfig(
|
|
3694
|
+
const apiKey = parseConfig(process.env).apiKey;
|
|
3727
3695
|
assertApiKey(apiKey);
|
|
3728
3696
|
const server = await createServer({ config: { apiKey } });
|
|
3729
3697
|
console.error("Starting MCP server in stdio mode");
|
|
@@ -3756,4 +3724,4 @@ async function runServer() {
|
|
|
3756
3724
|
//#endregion
|
|
3757
3725
|
export { createServer as n, runServer as r, configSchema as t };
|
|
3758
3726
|
|
|
3759
|
-
//# sourceMappingURL=src-
|
|
3727
|
+
//# sourceMappingURL=src-BBzEvkOX.mjs.map
|