hevy-mcp 1.14.3 → 1.15.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 CHANGED
@@ -27,7 +27,8 @@ Pick the workflow that fits your setup:
27
27
 
28
28
  ## Prerequisites
29
29
 
30
- - Node.js (v20 or higher)
30
+ - Node.js (v20 or higher; strongly recommended to use the exact version pinned in
31
+ `.nvmrc` to match CI)
31
32
  - pnpm (via Corepack)
32
33
  - A Hevy API key
33
34
  - Optional: A Smithery account + API key/login if you plan to deploy via Smithery
@@ -59,11 +60,12 @@ cp .env.sample .env
59
60
 
60
61
  ### Integration with Cursor
61
62
 
62
- To use this MCP server with Cursor, you need to update your `~/.cursor/mcp.json` file by adding the following configuration:
63
+ To use this MCP server with Cursor, add/merge this server entry under
64
+ `"mcpServers"` in `~/.cursor/mcp.json`:
63
65
 
64
66
  ```json
65
67
  {
66
- "hevy-mcp-server": {
68
+ "hevy-mcp": {
67
69
  "command": "npx",
68
70
  "args": ["-y", "hevy-mcp"],
69
71
  "env": {
@@ -75,6 +77,34 @@ To use this MCP server with Cursor, you need to update your `~/.cursor/mcp.json`
75
77
 
76
78
  Make sure to replace `your-api-key-here` with your actual Hevy API key.
77
79
 
80
+ If your `mcp.json` already contains other servers, do not replace the whole
81
+ file—merge the `"hevy-mcp"` entry into your existing `"mcpServers"` object.
82
+
83
+ The `"hevy-mcp"` key name is arbitrary. If you already have an existing config
84
+ using a different name (for example `"hevy-mcp-server"`), you can keep it.
85
+
86
+ If you already have an existing `"mcpServers"` object, merge the `"hevy-mcp"`
87
+ entry into it without removing other servers.
88
+
89
+ <details>
90
+ <summary><strong>Example full ~/.cursor/mcp.json</strong></summary>
91
+
92
+ ```json
93
+ {
94
+ "mcpServers": {
95
+ "hevy-mcp": {
96
+ "command": "npx",
97
+ "args": ["-y", "hevy-mcp"],
98
+ "env": {
99
+ "HEVY_API_KEY": "your-api-key-here"
100
+ }
101
+ }
102
+ }
103
+ }
104
+ ```
105
+
106
+ </details>
107
+
78
108
 
79
109
  ## Configuration
80
110
 
@@ -210,8 +240,13 @@ hevy-mcp/
210
240
  │ │ │ ├── schemas/ # Zod schemas
211
241
  │ │ │ └── mocks/ # Mock data
212
242
  │ └── utils/ # Helper utilities
213
- │ ├── formatters.ts # Data formatting helpers
214
- └── validators.ts # Input validation helpers
243
+ │ ├── config.ts # Env/CLI config parsing
244
+ ├── error-handler.ts # Tool error wrapper + response builder
245
+ │ ├── formatters.ts # Domain formatting helpers
246
+ │ ├── hevyClient.ts # API client factory
247
+ │ ├── httpServer.ts # Legacy HTTP transport (deprecated; throws explicit error; kept only for backward compatibility - removing may be breaking)
248
+ │ ├── response-formatter.ts # MCP response utilities
249
+ │ └── tool-helpers.ts # Zod schema -> TS type inference
215
250
  ├── scripts/ # Build and utility scripts
216
251
  └── tests/ # Test suite
217
252
  ├── integration/ # Integration tests with real API
@@ -238,7 +273,9 @@ To run all tests (unit and integration), use:
238
273
  pnpm test
239
274
  ```
240
275
 
241
- > **Note:** If the `HEVY_API_KEY` environment variable is set, integration tests will also run. If not, only unit tests will run.
276
+ > **Note:** `pnpm test` runs **all** tests. Integration tests will fail by design if
277
+ > `HEVY_API_KEY` is missing. If you don’t have an API key locally, use the unit
278
+ > test command below.
242
279
 
243
280
  #### Run Only Unit Tests
244
281
 
@@ -268,8 +305,11 @@ pnpm vitest run tests/integration
268
305
 
269
306
  For GitHub Actions:
270
307
 
271
- 1. Unit tests will always run on every push and pull request
272
- 2. Integration tests will only run if the `HEVY_API_KEY` secret is set in the repository settings
308
+ 1. Unit + integration tests are executed as part of the normal `Build and Test` workflow
309
+ 2. Integration tests require the `HEVY_API_KEY` secret to be set
310
+
311
+ The workflow runs `pnpm vitest run --coverage` and provides `HEVY_API_KEY` from
312
+ repository secrets.
273
313
 
274
314
  To set up the `HEVY_API_KEY` secret:
275
315
 
@@ -279,7 +319,23 @@ To set up the `HEVY_API_KEY` secret:
279
319
  4. Set the name to `HEVY_API_KEY` and the value to your Hevy API key
280
320
  5. Click "Add secret"
281
321
 
282
- If the secret is not set, the integration tests step will be skipped with a message indicating that the API key is missing.
322
+ If the secret is not set, the integration tests will fail (by design).
323
+
324
+ Note: GitHub does not provide secrets to pull requests from forks by default, so
325
+ fork PRs may fail CI unless a maintainer reruns the checks with `HEVY_API_KEY`
326
+ available.
327
+
328
+ If CI is failing only because the fork PR is missing `HEVY_API_KEY`, that is
329
+ expected; maintainers may rerun the workflow with secrets enabled.
330
+
331
+ For contributors from forks: CI failures caused solely by missing `HEVY_API_KEY`
332
+ do not indicate a problem with your changes.
333
+
334
+ All other CI checks (build, formatting/linting, unit tests, etc.) are still
335
+ expected to pass.
336
+
337
+ Only failures caused solely by missing `HEVY_API_KEY` on forked PRs are
338
+ considered acceptable.
283
339
 
284
340
  ### Generating API Client
285
341
 
package/dist/cli.js CHANGED
@@ -11,7 +11,7 @@ import { z as z6 } from "zod";
11
11
 
12
12
  // package.json
13
13
  var name = "hevy-mcp";
14
- var version = "1.14.2";
14
+ var version = "1.14.4";
15
15
 
16
16
  // src/tools/folders.ts
17
17
  import { z } from "zod";
@@ -351,7 +351,11 @@ function registerRoutineTools(server, hevyClient) {
351
351
  distanceMeters: z2.coerce.number().int().optional(),
352
352
  duration: z2.coerce.number().int().optional(),
353
353
  durationSeconds: z2.coerce.number().int().optional(),
354
- customMetric: z2.coerce.number().optional()
354
+ customMetric: z2.coerce.number().optional(),
355
+ repRange: z2.object({
356
+ start: z2.coerce.number().int().optional(),
357
+ end: z2.coerce.number().int().optional()
358
+ }).optional()
355
359
  })
356
360
  )
357
361
  })
@@ -386,7 +390,11 @@ function registerRoutineTools(server, hevyClient) {
386
390
  reps: set.reps ?? null,
387
391
  distance_meters: set.distance ?? set.distanceMeters ?? null,
388
392
  duration_seconds: set.duration ?? set.durationSeconds ?? null,
389
- custom_metric: set.customMetric ?? null
393
+ custom_metric: set.customMetric ?? null,
394
+ rep_range: set.repRange ? {
395
+ start: set.repRange.start ?? null,
396
+ end: set.repRange.end ?? null
397
+ } : null
390
398
  })
391
399
  )
392
400
  })
@@ -425,7 +433,11 @@ function registerRoutineTools(server, hevyClient) {
425
433
  distanceMeters: z2.coerce.number().int().optional(),
426
434
  duration: z2.coerce.number().int().optional(),
427
435
  durationSeconds: z2.coerce.number().int().optional(),
428
- customMetric: z2.coerce.number().optional()
436
+ customMetric: z2.coerce.number().optional(),
437
+ repRange: z2.object({
438
+ start: z2.coerce.number().int().optional(),
439
+ end: z2.coerce.number().int().optional()
440
+ }).optional()
429
441
  })
430
442
  )
431
443
  })
@@ -459,7 +471,11 @@ function registerRoutineTools(server, hevyClient) {
459
471
  reps: set.reps ?? null,
460
472
  distance_meters: set.distance ?? set.distanceMeters ?? null,
461
473
  duration_seconds: set.duration ?? set.durationSeconds ?? null,
462
- custom_metric: set.customMetric ?? null
474
+ custom_metric: set.customMetric ?? null,
475
+ rep_range: set.repRange ? {
476
+ start: set.repRange.start ?? null,
477
+ end: set.repRange.end ?? null
478
+ } : null
463
479
  })
464
480
  )
465
481
  })