hevy-mcp 3.0.0 → 3.1.1

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
@@ -1,168 +1,90 @@
1
- # hevy-mcp: Model Context Protocol Server for Hevy Fitness API
1
+ # hevy-mcp: Hevy workouts for your AI assistant
2
2
 
3
3
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
4
4
  [![Build and Test](https://github.com/chrisdoc/hevy-mcp/actions/workflows/build-and-test.yml/badge.svg)](https://github.com/chrisdoc/hevy-mcp/actions/workflows/build-and-test.yml)
5
5
  [![Codecov](https://codecov.io/gh/chrisdoc/hevy-mcp/branch/main/graph/badge.svg)](https://codecov.io/gh/chrisdoc/hevy-mcp)
6
6
  [![npm version](https://img.shields.io/npm/v/hevy-mcp.svg)](https://www.npmjs.com/package/hevy-mcp)
7
7
 
8
- A Model Context Protocol (MCP) server implementation that interfaces with the [Hevy fitness tracking app](https://www.hevyapp.com/) and its [API](https://api.hevyapp.com/docs/). This server enables AI assistants like **Claude Desktop** and **Cursor** to access and manage workout data, routines, and exercise templates through the Hevy API (requires PRO subscription).
8
+ `hevy-mcp` connects MCP-compatible assistants such as Claude Desktop and Cursor
9
+ to the [Hevy](https://www.hevyapp.com/) fitness API. Ask about workout history,
10
+ analyze progress, browse routines and exercises, or create and update Hevy data
11
+ without leaving your assistant.
9
12
 
10
- ---
13
+ A Hevy API key, available with Hevy PRO, is required.
11
14
 
12
- ## 📋 Table of Contents
15
+ ## Quick Start
13
16
 
14
- - [Features](#features)
15
- - [Quick Start](#quick-start)
16
- - [Prerequisites](#prerequisites)
17
- - [Installation](#installation)
18
- - [Run with Docker](#run-with-docker)
19
- - [Claude Desktop Configuration](#claude-desktop-configuration)
20
- - [Cursor Configuration](#cursor-configuration)
21
- - [Other MCP Clients (via add-mcp)](#other-mcp-clients-via-add-mcp)
22
- - [Why hevy-mcp?](#why-hevy-mcp)
23
- - [Configuration](#configuration)
24
- - [Available MCP Tools](#available-mcp-tools)
25
- - [Available MCP Resources](#available-mcp-resources)
26
- - [Development & Contributing](#development--contributing)
17
+ Use local stdio when your MCP client can launch a command. Hosted Streamable
18
+ HTTP setup is documented below but is temporarily unavailable.
27
19
 
28
- ---
20
+ ### Option A: Local stdio
29
21
 
30
- ## 🚀 Features
22
+ The npm package and official container are **stdio-only** MCP executables. Your
23
+ client starts the process and communicates through standard input/output; this
24
+ is not an interactive terminal command or an HTTP service.
31
25
 
32
- - **Workout Management**: Fetch, create, and update workouts.
33
- - **Routine Management**: Access and manage workout routines.
34
- - **Exercise Templates**: Browse available exercise templates with in-memory caching.
35
- - **Folder Organization**: Manage routine folders.
26
+ #### npx
36
27
 
37
- ---
28
+ Requires Node.js 20 or newer, as declared by the package metadata.
38
29
 
39
- ## 🏁 Quick Start
30
+ Claude Desktop (`claude_desktop_config.json`) and Cursor (`~/.cursor/mcp.json`)
31
+ both accept an `mcpServers` entry like this:
40
32
 
41
- Pick the workflow that fits your setup:
42
-
43
- | Scenario | Command | Requirements |
44
- | :-------------------- | :-------------------------------------------------------------------------------------- | :------------------------- |
45
- | **One-off stdio run** | `HEVY_API_KEY=your_key npx -y hevy-mcp` or `HEVY_API_KEY=your_key bunx hevy-mcp@latest` | Node.js ≥ 20, Hevy API key |
46
- | **Docker stdio run** | `docker run -i --rm -e HEVY_API_KEY ghcr.io/chrisdoc/hevy-mcp:latest` | Docker, Hevy API key |
47
- | **Local development** | `npm install && npm run build && npm start` | `.env` with `HEVY_API_KEY` |
48
-
49
- ---
50
-
51
- ## 🛠️ Prerequisites
52
-
53
- - **Node.js**: v20 or higher (strongly recommended to use the exact version pinned in `.nvmrc`).
54
- - **npm**: v10 or higher.
55
- - **Bun** (optional): If you want to launch with `bunx`.
56
- - **Docker** (optional): If you want an isolated container-based stdio setup.
57
- - **Hevy API key**: Required for all operations (available with Hevy PRO).
58
-
59
- ---
60
-
61
- ## 📦 Installation
62
-
63
- ### Run via npx or bunx
64
-
65
- You can launch the server directly without cloning. Both launchers are covered
66
- by nightly smoke tests:
67
-
68
- ```bash
69
- # npm launcher
70
- HEVY_API_KEY=your_hevy_api_key_here npx -y hevy-mcp
71
-
72
- # bun launcher
73
- HEVY_API_KEY=your_hevy_api_key_here bunx hevy-mcp@latest
74
- ```
75
-
76
- ### Manual Installation
77
-
78
- ```bash
79
- # Clone the repository
80
- git clone https://github.com/chrisdoc/hevy-mcp.git
81
- cd hevy-mcp
82
-
83
- # Install dependencies
84
- npm install
85
-
86
- # Create .env and add your keys
87
- cp .env.sample .env
88
- # Edit .env and add your HEVY_API_KEY
89
- ```
90
-
91
- ### Run with Docker
92
-
93
- Official multi-platform images are published to GitHub Container Registry for
94
- `linux/amd64` and `linux/arm64`:
95
-
96
- ```bash
97
- export HEVY_API_KEY=your_hevy_api_key_here
98
- docker run -i --rm -e HEVY_API_KEY ghcr.io/chrisdoc/hevy-mcp:latest
99
- ```
100
-
101
- The server uses stdio, so `-i` keeps standard input open for the MCP client.
102
- `--rm` removes the stopped container automatically. The `-e HEVY_API_KEY`
103
- form forwards the variable from the host environment without putting the key
104
- in the command arguments.
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
-
112
- Use `latest` to follow the newest stable release. For reproducible deployments,
113
- pin the exact version shown on the release, using a tag such as
114
- `ghcr.io/chrisdoc/hevy-mcp:X.Y.Z`. Major (`:X`) and major.minor (`:X.Y`) tags
115
- are also published for controlled automatic updates.
116
-
117
- ---
118
-
119
- ## 🔗 Integration
120
-
121
- ### Claude Desktop Configuration
122
-
123
- To use this server with Claude Desktop, add the following to your `claude_desktop_config.json`:
124
-
125
- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
126
- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
33
+ - **Claude Desktop on macOS:**
34
+ `~/Library/Application Support/Claude/claude_desktop_config.json`
35
+ - **Claude Desktop on Windows:**
36
+ `%APPDATA%\Claude\claude_desktop_config.json`
127
37
 
128
38
  ```json
129
39
  {
130
40
  "mcpServers": {
131
- "hevy-mcp": {
41
+ "hevy": {
132
42
  "command": "npx",
133
43
  "args": ["-y", "hevy-mcp"],
134
44
  "env": {
135
- "HEVY_API_KEY": "sk_live_your_key_here"
45
+ "HEVY_API_KEY": "your-hevy-api-key"
136
46
  }
137
47
  }
138
48
  }
139
49
  }
140
50
  ```
141
51
 
142
- If you prefer Bun, swap the launcher fields:
52
+ #### bunx
53
+
54
+ Requires [Bun](https://bun.sh/). Use the same client configuration with a Bun
55
+ launcher:
143
56
 
144
57
  ```json
145
58
  {
146
- "command": "bunx",
147
- "args": ["hevy-mcp@latest"]
59
+ "mcpServers": {
60
+ "hevy": {
61
+ "command": "bunx",
62
+ "args": ["hevy-mcp@latest"],
63
+ "env": {
64
+ "HEVY_API_KEY": "your-hevy-api-key"
65
+ }
66
+ }
67
+ }
148
68
  }
149
69
  ```
150
70
 
151
- To run Claude Desktop through Docker instead, first create an environment file
152
- outside the repository containing your real key:
71
+ #### Docker
72
+
73
+ Official images support `linux/amd64` and `linux/arm64`. Keep stdin open with
74
+ `-i` because the container runs the same stdio server:
153
75
 
154
- ```dotenv
155
- HEVY_API_KEY=replace_with_your_real_key
76
+ ```bash
77
+ export HEVY_API_KEY=your-hevy-api-key
78
+ docker run -i --rm -e HEVY_API_KEY ghcr.io/chrisdoc/hevy-mcp:latest
156
79
  ```
157
80
 
158
- Restrict access to that file where supported (for example,
159
- `chmod 600 /absolute/path/to/hevy-mcp.env`), then use its absolute path in the
160
- Claude Desktop configuration:
81
+ For an MCP client, store the key in a protected environment file and configure
82
+ the client to launch Docker:
161
83
 
162
84
  ```json
163
85
  {
164
86
  "mcpServers": {
165
- "hevy-mcp": {
87
+ "hevy": {
166
88
  "command": "docker",
167
89
  "args": [
168
90
  "run",
@@ -177,239 +99,173 @@ Claude Desktop configuration:
177
99
  }
178
100
  ```
179
101
 
180
- This configuration runs the same stdio server inside the container; it does
181
- not expose an HTTP port or start a detached service. Docker reads the key from
182
- the environment file, so the Claude configuration does not replace an
183
- inherited key with a placeholder. Replace `latest` with an exact version tag if
184
- you want Claude Desktop to stay on a pinned release.
185
-
186
- ### Cursor Configuration
187
-
188
- Add this server under `"mcpServers"` in `~/.cursor/mcp.json`:
189
-
190
- ```json
191
- {
192
- "mcpServers": {
193
- "hevy-mcp": {
194
- "command": "npx",
195
- "args": ["-y", "hevy-mcp"],
196
- "env": {
197
- "HEVY_API_KEY": "your-api-key-here"
198
- }
199
- }
200
- }
201
- }
202
- ```
203
-
204
- If you prefer Bun, swap the launcher fields:
205
-
206
- ```json
207
- {
208
- "command": "bunx",
209
- "args": ["hevy-mcp@latest"]
210
- }
211
- ```
212
-
213
- ### Other MCP Clients (via add-mcp)
102
+ Pin an exact image tag such as `ghcr.io/chrisdoc/hevy-mcp:X.Y.Z` when you need
103
+ reproducible upgrades.
214
104
 
215
- For a generic setup flow across MCP clients, use [`add-mcp`](https://github.com/neon-solutions/add-mcp):
105
+ You can also add the local npm server to supported clients with
106
+ [`add-mcp`](https://github.com/neon-solutions/add-mcp):
216
107
 
217
108
  ```bash
218
- npx add-mcp hevy-mcp --env "HEVY_API_KEY=secret"
109
+ npx add-mcp hevy-mcp --env "HEVY_API_KEY=your-hevy-api-key"
219
110
  ```
220
111
 
221
- This bootstraps the `hevy-mcp` entry in your client config without manual JSON edits.
222
-
223
- ---
224
-
225
- ## ✨ Why hevy-mcp?
226
-
227
- - 🚀 **High Performance**: Built with the **Oxc** toolchain (`oxlint`/`oxfmt`) for near-instant linting and formatting.
228
- - 🛡️ **Type Safety**: Fully type-safe implementation using **Zod** and **Kubb**-generated API clients.
229
- - 📉 **Observability**: Built-in **Sentry** monitoring for error tracking, lifecycle and tool tracing, and stdio parse diagnostics.
230
- - ⚡ **Optimized**: Includes in-memory caching for exercise templates to reduce API latency.
231
-
232
- ---
233
-
234
- ## ⚙️ Configuration
112
+ ### Option B: Hosted Streamable HTTP temporarily unavailable
235
113
 
236
- Supply your Hevy API key via the `HEVY_API_KEY` environment variable (in
237
- `.env` or system environment).
114
+ > [!WARNING]
115
+ > `https://hevy.chrisdoc.dev/mcp` is currently intercepted by an interactive
116
+ > Cloudflare challenge, so non-browser MCP clients cannot connect. Use local
117
+ > stdio until the route is restored.
238
118
 
239
- Set `HEVY_MCP_API_TIMEOUT` to override the default 30-second Hevy API request
240
- timeout. Its value is in milliseconds.
119
+ When available, the hosted endpoint does not require Node.js, Bun, or Docker:
241
120
 
242
- Set `HEVY_MCP_DEBUG=1` to emit verbose, privacy-bounded diagnostics to stderr.
243
- Debug records include tool invocations and sanitized Hevy API response timing
244
- and status details. Other values leave diagnostics disabled, and stdout remains
245
- reserved for the MCP JSON-RPC stream.
246
-
247
- ```env
248
- # Example .env
249
- HEVY_API_KEY=your_hevy_api_key_here
250
- # Optional: customize Hevy API request timeout (milliseconds)
251
- HEVY_MCP_API_TIMEOUT=30000
252
- # Optional: enable verbose stderr diagnostics (only the value 1 enables it)
253
- HEVY_MCP_DEBUG=1
121
+ ```text
122
+ https://hevy.chrisdoc.dev/mcp
254
123
  ```
255
124
 
256
- ### 🧠 Exercise Template Cache Behavior
257
-
258
- `search-exercise-templates` and the `hevy://exercise-templates` resource use a
259
- shared in-memory async cache for the full exercise template catalog:
260
-
261
- - **TTL**: 5 minutes per cached catalog entry.
262
- - **Memory bound**: max 1 catalog entry (LRU bounded cache).
263
- - **In-flight de-duplication**: concurrent requests share the same active
264
- fetch when possible.
265
- - **Manual refresh**: set `refresh: true` in the tool input to invalidate the
266
- cached catalog and force a re-fetch from the Hevy API.
267
-
268
- Paginated `get-exercise-templates` requests still call the API directly to keep
269
- paging behavior explicit and avoid cross-page invalidation complexity.
270
-
271
- ### 📡 Sentry Monitoring
272
-
273
- `hevy-mcp` includes Sentry monitoring to observe errors and usage in production. It initializes `@sentry/node` with tracing enabled and PII collection disabled by default. Recent observability changes also add:
274
-
275
- - lifecycle spans around server build, run, and stdio connect
276
- - per-tool execution spans plus captured handler exceptions
277
- - stdio parse diagnostics, including leading UTF-8 BOM stripping and invalid JSON context
278
- - a deterministic pseudonymous Sentry user ID derived from `HEVY_API_KEY`, so the raw key is never sent to Sentry
279
-
280
- ---
281
-
282
- <details>
283
- <summary><strong>⚠️ Migration Note (v1.18.0)</strong></summary>
284
-
285
- As of **v1.18.0**, `hevy-mcp` removed HTTP/SSE transport and its previous
286
- Docker packaging. Docker support is now available again for the stdio server.
287
-
288
- Both `npx hevy-mcp` and the official container image use stdio; HTTP ports and
289
- detached-container deployment are not supported.
290
-
291
- </details>
292
-
293
- ---
125
+ Configure a remote MCP server in your client and send your Hevy API key as a
126
+ fixed authorization header. Exact configuration keys vary by client; clients
127
+ that use `url` and `headers` commonly accept this shape:
294
128
 
295
- ## 🛠️ Available MCP Tools
296
-
297
- | Category | Tools |
298
- | :-------------------- | :--------------------------------------------------------------------------------------------------------------------------------- |
299
- | **Workouts** | `get-workouts`, `get-workout`, `create-workout`, `update-workout`, `get-workout-count`, `get-workout-events` |
300
- | **Routines** | `get-routines`, `get-routine`, `create-routine`, `update-routine` |
301
- | **Templates** | `get-exercise-templates`, `get-exercise-template`, `search-exercise-templates`, `create-exercise-template`, `get-exercise-history` |
302
- | **Folders** | `get-routine-folders`, `get-routine-folder`, `create-routine-folder` |
303
- | **Body Measurements** | `get-body-measurements`, `get-body-measurement`, `create-body-measurement`, `update-body-measurement` |
304
- | **User** | `get-user-info` |
305
-
306
- > **Delete operations are currently unsupported:** The upstream Hevy OpenAPI
307
- > spec does not expose `DELETE` endpoints for workouts, routines, routine
308
- > folders, exercise templates, or body measurements, so `hevy-mcp` does not
309
- > provide delete tools for these resources.
310
-
311
- ## 💬 Available MCP Prompts
312
-
313
- | Prompt | Arguments | Guided workflow |
314
- | :---------------------------- | :------------------------------------------------------------------------------------- | :---------------------------------------------------- |
315
- | `analyze-workout-progress` | Optional `weeks` (1-12; defaults to `4` when omitted from a supplied arguments object) | Analyze recent workout and body-measurement trends. |
316
- | `create-workout-from-routine` | `routineId`, `startTime` (UTC ISO seconds) | Record a completed workout using a routine as a plan. |
317
-
318
- Compatibility note: with MCP SDK v1.29.0, clients using the default must send
319
- `arguments: {}` because the SDK rejects requests that omit the entire
320
- `arguments` object before prompt field defaults are evaluated.
321
-
322
- ---
323
-
324
- ## 📚 Available MCP Resources
325
-
326
- | Name | URI |
327
- | :------------------- | :-------------------------- |
328
- | `user-profile` | `hevy://user` |
329
- | `workout-count` | `hevy://workout-count` |
330
- | `exercise-templates` | `hevy://exercise-templates` |
331
- | `routine-folders` | `hevy://routine-folders` |
332
-
333
- ---
334
-
335
- ## 👨‍💻 Development & Contributing
336
-
337
- ### Quick Commands
338
-
339
- - **Build**: `npm run build`
340
- - **Lint/Format**: `npm run check` (uses oxlint/oxfmt)
341
- - **Type Check**: `npm run check:types`
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)
345
- - **Changeset Check**: `npm run check:changeset`
346
- - **Tool Token Cost**: `npm run measure:tokens` ([measurement guide](./docs/token-cost-tracking.md))
347
-
348
- For a detailed senior engineer guide, please refer to [AGENTS.md](./AGENTS.md).
349
-
350
- ### Pull Request Checks
351
-
352
- - **Conventional Commits**: CI lints commit messages on pull requests, so use
353
- prefixes such as `feat:`, `fix:`, `docs:`, `ci:`, `chore:`, `refactor:`,
354
- `test:`, or `style:`.
355
- - **Type Checking**: CI runs `npm run check:types` on pull requests and pushes
356
- to `main`; run this locally before opening a PR.
357
- - **Changesets**: Contributor pull requests targeting `main` must include a
358
- changeset. Dependabot PRs and automated `changeset-release/main` release PRs
359
- are handled by automation and skip this check.
360
-
361
- ### API Client Generation
362
-
363
- The API client is automatically generated from the OpenAPI spec using [Kubb](https://kubb.dev/):
364
-
365
- ```bash
366
- npm run build:client
129
+ ```json
130
+ {
131
+ "mcpServers": {
132
+ "hevy": {
133
+ "url": "https://hevy.chrisdoc.dev/mcp",
134
+ "headers": {
135
+ "Authorization": "Bearer your-hevy-api-key"
136
+ }
137
+ }
138
+ }
139
+ }
367
140
  ```
368
141
 
369
- ### Versioning & Releases
370
-
371
- This project uses [Changesets](https://github.com/changesets/changesets) to
372
- manage versioning, changelogs, releases, and pull request validation.
373
-
374
- 1. **Routine Release Cadence**: Merge the automated
375
- `changeset-release/main` (**"Version Packages"**) Pull Request on a regular
376
- cadence (weekly is a good default) instead of ad-hoc frequent merges.
377
- 2. **Urgent Release Exception**: Security fixes and high-impact,
378
- user-facing bug fixes can be released immediately outside the routine
379
- cadence.
380
- 3. **Use Bump Changesets Only for User-Facing Runtime Changes**: If your
381
- change is user-facing/runtime-visible, run:
382
- ```bash
383
- npx changeset
384
- ```
385
- Follow the prompts to choose `patch`, `minor`, or `major`, then write a
386
- short summary. This creates a markdown file under `.changeset/`.
387
- 4. **Use Empty Changesets for Internal-Only Work**: Docs, CI, test-only,
388
- refactor, and chore changes should use an empty changeset:
389
- ```bash
390
- npx changeset --empty
391
- ```
392
- 5. **Validate Before Opening a PR**: Contributor pull requests targeting
393
- `main` are checked for a changeset in CI. Dependabot PRs and automated
394
- `changeset-release/main` release PRs are handled separately. You can run the
395
- same validation locally with:
396
- ```bash
397
- npm run check:changeset
398
- ```
399
- 6. **Automated Releases**:
400
- - Pushing changesets to `main` triggers a GitHub Action that automatically
401
- creates or updates a **"Version Packages"** Pull Request.
402
- - When this Pull Request is merged, the package is automatically built,
403
- published to npm (via OIDC Trusted Publishing), and a GitHub Release is
404
- created.
405
-
406
- ---
407
-
408
- ## 📄 License & Acknowledgements
409
-
410
- - **License**: [MIT](./LICENSE)
411
- - **Credits**: [Model Context Protocol](https://github.com/modelcontextprotocol), [Hevy Fitness](https://www.hevyapp.com/).
412
-
413
- ---
414
-
415
- **Contributions are welcome!** Please open an issue or PR for any major changes.
142
+ The hosted transport is stateless **Streamable HTTP** at `POST /mcp`. The bearer
143
+ value is a custom Hevy API credential, not OAuth. The endpoint does not expose a
144
+ legacy SSE or `GET` event stream, and `GET` and `DELETE` requests return `405`.
145
+ Clients that require OAuth discovery, dynamic registration, token refresh, or a
146
+ legacy SSE transport are not compatible unless they can send the fixed custom
147
+ header above.
148
+
149
+ ### How to verify it is working
150
+
151
+ Restart or reconnect your MCP client after saving the configuration, then try:
152
+
153
+ - "What routines do I have saved on Hevy?"
154
+ - "Show my most recent workouts."
155
+ - "Which Hevy account is connected?"
156
+ - "Find exercise templates containing squat."
157
+
158
+ The assistant should ask for approval before mutation tools when the client
159
+ supports tool confirmations.
160
+
161
+ ## Guided MCP prompts
162
+
163
+ These server-provided prompts coordinate multiple tools for common workflows:
164
+
165
+ | Prompt | Arguments | Workflow |
166
+ | ----------------------------- | ------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
167
+ | `analyze-workout-progress` | Optional `weeks` from 1-12; default is `4` | Paginates through recent workouts and body measurements, then analyzes frequency, volume, variety, consistency, and measurement trends from retrieved evidence. |
168
+ | `create-workout-from-routine` | Required `routineId` and UTC `startTime` | Loads a routine, asks for actual completed-set data and an end time, then creates a workout without inventing results or copying unsupported routine-only data. |
169
+
170
+ > [!IMPORTANT]
171
+ > With MCP SDK v1.29.0, invoking `analyze-workout-progress` with its default
172
+ > `weeks` value requires clients to send `arguments: {}`. Omitting the entire
173
+ > `arguments` object is rejected by that SDK version before the default is
174
+ > applied.
175
+
176
+ ## Capabilities
177
+
178
+ `hevy-mcp` registers 23 tools:
179
+
180
+ | Category | Tool | Description |
181
+ | -------------------------- | --------------------------- | --------------------------------------------------------------------- |
182
+ | Workouts | `get-workouts` | List workouts from newest to oldest with exercise and timing details. |
183
+ | Workouts | `get-workout` | Get complete details for one workout by ID. |
184
+ | Workouts | `get-workout-count` | Return the account's total workout count. |
185
+ | Workouts | `get-workout-events` | List workout update and delete events since a timestamp. |
186
+ | Workouts | `create-workout` | Create a completed workout in Hevy. |
187
+ | Workouts | `update-workout` | Replace an existing workout by ID. |
188
+ | Routines | `get-routines` | List custom and default workout routines. |
189
+ | Routines | `get-routine` | Get one routine and its exercise configuration by ID. |
190
+ | Routines | `create-routine` | Create a reusable workout routine. |
191
+ | Routines | `update-routine` | Replace an existing routine's content. |
192
+ | Routine folders | `get-routine-folders` | List default and custom routine folders. |
193
+ | Routine folders | `get-routine-folder` | Get one routine folder's metadata by ID. |
194
+ | Routine folders | `create-routine-folder` | Create a routine folder. |
195
+ | Exercise templates/history | `get-exercise-templates` | List exercise templates with equipment and muscle metadata. |
196
+ | Exercise templates/history | `get-exercise-template` | Get complete metadata for one exercise template by ID. |
197
+ | Exercise templates/history | `search-exercise-templates` | Search the full exercise catalog by title substring. |
198
+ | Exercise templates/history | `create-exercise-template` | Create a custom exercise template. |
199
+ | Exercise templates/history | `get-exercise-history` | Get past performed sets for one exercise template. |
200
+ | Body measurements | `get-body-measurements` | List dated body measurements. |
201
+ | Body measurements | `get-body-measurement` | Get the body measurement entry for one date. |
202
+ | Body measurements | `create-body-measurement` | Create a dated body measurement. |
203
+ | Body measurements | `update-body-measurement` | Update the body measurement for an existing date. |
204
+ | Account | `get-user-info` | Return the user's ID, display name, and public profile URL. |
205
+
206
+ The Hevy API currently exposes no delete endpoints for workouts, routines,
207
+ routine folders, exercise templates, or body measurements, so there are no
208
+ corresponding delete tools.
209
+
210
+ ### Resources
211
+
212
+ | Name | URI | Description |
213
+ | -------------------- | --------------------------- | -------------------------------------------- |
214
+ | `user-profile` | `hevy://user` | Authenticated Hevy user profile. |
215
+ | `workout-count` | `hevy://workout-count` | Total number of workouts in the account. |
216
+ | `exercise-templates` | `hevy://exercise-templates` | Full formatted exercise template catalog. |
217
+ | `routine-folders` | `hevy://routine-folders` | Full formatted list of Hevy routine folders. |
218
+
219
+ ## Advanced configuration
220
+
221
+ | Setting | Default | Scope | Notes |
222
+ | ---------------------- | ------------------------------ | ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
223
+ | `HEVY_API_KEY` | None; required | Local stdio | Hevy API key from the Hevy app. Use the hosted `Authorization` header instead for Streamable HTTP. Never pass the key in a URL. |
224
+ | `HEVY_MCP_API_TIMEOUT` | `30000` ms | Local stdio | Positive Hevy API request timeout in milliseconds. Invalid or non-positive values fall back to 30,000 ms. |
225
+ | `HEVY_MCP_DEBUG` | Disabled | Local stdio | Only the exact value `1` enables privacy-bounded diagnostics on stderr. Stdout stays reserved for MCP JSON-RPC. |
226
+ | `MCP_ALLOWED_ORIGINS` | No browser origins allowed | Self-hosted Cloudflare Worker | Optional comma-separated exact origins. Wildcards are unsupported. Requests without `Origin`, such as desktop clients, remain accepted. |
227
+ | `XDG_CACHE_HOME` | `~/.cache` | Local stdio | Changes the root for the best-effort npm version-check cache at `hevy-mcp/update-check.json`. |
228
+ | `SENTRY_DSN` | Packaged project DSN | Optional local Node telemetry | Overrides the Sentry destination. An empty value disables Sentry export. The Worker entry point does not import Node telemetry. |
229
+ | `SENTRY_RELEASE` | `hevy-mcp@<installed-version>` | Optional local Node telemetry | Overrides the release label attached to local Sentry events and traces. |
230
+ | `-h`, `--help` | N/A | Local stdio CLI | Print supported options and exit without starting the server. |
231
+ | `-v`, `--version` | N/A | Local stdio CLI | Print the installed version and exit without starting the server. |
232
+
233
+ The local executable does **not** support `PORT`, `HEVY_MCP_TRANSPORT`, or
234
+ `--transport`. It always uses stdio and does not provide local HTTP or SSE
235
+ behavior. Use the hosted endpoint after its route is restored, or deploy the
236
+ separate Cloudflare Worker when Streamable HTTP is required now.
237
+
238
+ ## Cache behavior
239
+
240
+ `search-exercise-templates` and `hevy://exercise-templates` share a
241
+ server-scoped in-memory catalog cache:
242
+
243
+ - Entries live for five minutes and the cache holds at most one catalog.
244
+ - Concurrent catalog requests share an in-flight fetch when possible.
245
+ - `search-exercise-templates` accepts `refresh: true` to invalidate the cache.
246
+ - Paginated `get-exercise-templates` calls always fetch their requested page.
247
+ - Each hosted Worker request gets a fresh cache, preventing cross-key sharing.
248
+
249
+ ## Security and mutations
250
+
251
+ - Keep `HEVY_API_KEY` out of source control, URLs, logs, and screenshots.
252
+ - Local clients provide the key through the child process environment. Hosted
253
+ clients send it only in `Authorization: Bearer <HEVY_API_KEY>`.
254
+ - The hosted Worker validates each key with Hevy, does not store it, and sends
255
+ it upstream only as Hevy's `api-key` header.
256
+ - Browser requests to a self-hosted Worker must exactly match an origin in
257
+ `MCP_ALLOWED_ORIGINS`; wildcard CORS is intentionally unsupported.
258
+ - Create operations can produce duplicates when retried. Update operations
259
+ replace existing records. Review tool inputs and use client confirmations.
260
+
261
+ ## Contributing and self-hosting
262
+
263
+ Developer setup, testing lanes, generated-client workflows, Cloudflare Worker
264
+ deployment, and pull request rules live in the
265
+ [contributor guide](https://github.com/chrisdoc/hevy-mcp/blob/main/CONTRIBUTING.md).
266
+
267
+ ## License and acknowledgements
268
+
269
+ - **License:** [MIT](./LICENSE)
270
+ - **Credits:** [Model Context Protocol](https://github.com/modelcontextprotocol)
271
+ and [Hevy Fitness](https://www.hevyapp.com/)
package/dist/cli.mjs CHANGED
@@ -4,15 +4,15 @@
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@3.0.0" };
7
+ e.SENTRY_RELEASE = { id: "hevy-mcp@3.1.1" };
8
8
  var n = new e.Error().stack;
9
- n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "03cf150f-6466-4ca3-9cf1-e423cc0e3cd2", e._sentryDebugIdIdentifier = "sentry-dbid-03cf150f-6466-4ca3-9cf1-e423cc0e3cd2");
9
+ n && (e._sentryDebugIds = e._sentryDebugIds || {}, e._sentryDebugIds[n] = "47a79c69-c982-44cf-abda-d010f962b955", e._sentryDebugIdIdentifier = "sentry-dbid-47a79c69-c982-44cf-abda-d010f962b955");
10
10
  } catch (e) {}
11
11
  })();
12
- import { r as runServer } from "./src-BBzEvkOX.mjs";
12
+ import { i as createSafeErrorDiagnostic, r as runServer } from "./src-CkkrTrrg.mjs";
13
13
  //#region src/cli.ts
14
14
  runServer().catch((error) => {
15
- console.error("Fatal error in main():", error);
15
+ console.error("Fatal error in main()", createSafeErrorDiagnostic(error));
16
16
  process.exit(1);
17
17
  });
18
18
  //#endregion
package/dist/cli.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.mjs","names":[],"sources":["../src/cli.ts"],"sourcesContent":["import { runServer } from \"./index.js\";\n\nvoid runServer().catch((error) => {\n\tconsole.error(\"Fatal error in main():\", error);\n\tprocess.exit(1);\n});\n"],"mappings":";;;;;;;;;;;;;AAEK,UAAU,CAAC,CAAC,OAAO,UAAU;CACjC,QAAQ,MAAM,0BAA0B,KAAK;CAC7C,QAAQ,KAAK,CAAC;AACf,CAAC"}
1
+ {"version":3,"file":"cli.mjs","names":[],"sources":["../src/cli.ts"],"sourcesContent":["import { runServer } from \"./index.js\";\nimport { createSafeErrorDiagnostic } from \"./utils/safe-error-diagnostic.js\";\n\nvoid runServer().catch((error) => {\n\tconsole.error(\"Fatal error in main()\", createSafeErrorDiagnostic(error));\n\tprocess.exit(1);\n});\n"],"mappings":";;;;;;;;;;;;;AAGK,UAAU,CAAC,CAAC,OAAO,UAAU;CACjC,QAAQ,MAAM,yBAAyB,0BAA0B,KAAK,CAAC;CACvE,QAAQ,KAAK,CAAC;AACf,CAAC"}