hevy-mcp 2.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,162 +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
- Use `latest` to follow the newest stable release. For reproducible deployments,
107
- pin the exact version shown on the release, using a tag such as
108
- `ghcr.io/chrisdoc/hevy-mcp:X.Y.Z`. Major (`:X`) and major.minor (`:X.Y`) tags
109
- are also published for controlled automatic updates.
110
-
111
- ---
112
-
113
- ## 🔗 Integration
114
-
115
- ### Claude Desktop Configuration
116
-
117
- To use this server with Claude Desktop, add the following to your `claude_desktop_config.json`:
118
-
119
- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
120
- **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`
121
37
 
122
38
  ```json
123
39
  {
124
40
  "mcpServers": {
125
- "hevy-mcp": {
41
+ "hevy": {
126
42
  "command": "npx",
127
43
  "args": ["-y", "hevy-mcp"],
128
44
  "env": {
129
- "HEVY_API_KEY": "sk_live_your_key_here"
45
+ "HEVY_API_KEY": "your-hevy-api-key"
130
46
  }
131
47
  }
132
48
  }
133
49
  }
134
50
  ```
135
51
 
136
- 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:
137
56
 
138
57
  ```json
139
58
  {
140
- "command": "bunx",
141
- "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
+ }
142
68
  }
143
69
  ```
144
70
 
145
- To run Claude Desktop through Docker instead, first create an environment file
146
- outside the repository containing your real key:
71
+ #### Docker
147
72
 
148
- ```dotenv
149
- HEVY_API_KEY=replace_with_your_real_key
73
+ Official images support `linux/amd64` and `linux/arm64`. Keep stdin open with
74
+ `-i` because the container runs the same stdio server:
75
+
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
150
79
  ```
151
80
 
152
- Restrict access to that file where supported (for example,
153
- `chmod 600 /absolute/path/to/hevy-mcp.env`), then use its absolute path in the
154
- Claude Desktop configuration:
81
+ For an MCP client, store the key in a protected environment file and configure
82
+ the client to launch Docker:
155
83
 
156
84
  ```json
157
85
  {
158
86
  "mcpServers": {
159
- "hevy-mcp": {
87
+ "hevy": {
160
88
  "command": "docker",
161
89
  "args": [
162
90
  "run",
@@ -171,241 +99,173 @@ Claude Desktop configuration:
171
99
  }
172
100
  ```
173
101
 
174
- This configuration runs the same stdio server inside the container; it does
175
- not expose an HTTP port or start a detached service. Docker reads the key from
176
- the environment file, so the Claude configuration does not replace an
177
- inherited key with a placeholder. Replace `latest` with an exact version tag if
178
- you want Claude Desktop to stay on a pinned release.
179
-
180
- ### Cursor Configuration
181
-
182
- Add this server under `"mcpServers"` in `~/.cursor/mcp.json`:
183
-
184
- ```json
185
- {
186
- "mcpServers": {
187
- "hevy-mcp": {
188
- "command": "npx",
189
- "args": ["-y", "hevy-mcp"],
190
- "env": {
191
- "HEVY_API_KEY": "your-api-key-here"
192
- }
193
- }
194
- }
195
- }
196
- ```
197
-
198
- If you prefer Bun, swap the launcher fields:
199
-
200
- ```json
201
- {
202
- "command": "bunx",
203
- "args": ["hevy-mcp@latest"]
204
- }
205
- ```
206
-
207
- ### 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.
208
104
 
209
- 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):
210
107
 
211
108
  ```bash
212
- npx add-mcp hevy-mcp --env "HEVY_API_KEY=secret"
109
+ npx add-mcp hevy-mcp --env "HEVY_API_KEY=your-hevy-api-key"
213
110
  ```
214
111
 
215
- This bootstraps the `hevy-mcp` entry in your client config without manual JSON edits.
216
-
217
- ---
218
-
219
- ## ✨ Why hevy-mcp?
220
-
221
- - 🚀 **High Performance**: Built with the **Oxc** toolchain (`oxlint`/`oxfmt`) for near-instant linting and formatting.
222
- - 🛡️ **Type Safety**: Fully type-safe implementation using **Zod** and **Kubb**-generated API clients.
223
- - 📉 **Observability**: Built-in **Sentry** monitoring for error tracking, lifecycle and tool tracing, and stdio parse diagnostics.
224
- - ⚡ **Optimized**: Includes in-memory caching for exercise templates to reduce API latency.
225
-
226
- ---
227
-
228
- ## ⚙️ Configuration
229
-
230
- Supply your Hevy API key via the `HEVY_API_KEY` environment variable (in
231
- `.env` or system environment).
112
+ ### Option B: Hosted Streamable HTTP temporarily unavailable
232
113
 
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.
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.
236
118
 
237
- Set `HEVY_MCP_API_TIMEOUT` to override the default 30-second Hevy API request
238
- timeout. Its value is in milliseconds.
119
+ When available, the hosted endpoint does not require Node.js, Bun, or Docker:
239
120
 
240
- Set `HEVY_MCP_DEBUG=1` to emit verbose, privacy-bounded diagnostics to stderr.
241
- Debug records include tool invocations and sanitized Hevy API response timing
242
- and status details. Other values leave diagnostics disabled, and stdout remains
243
- reserved for the MCP JSON-RPC stream.
244
-
245
- ```env
246
- # Example .env
247
- HEVY_API_KEY=your_hevy_api_key_here
248
- # Optional: customize Hevy API request timeout (milliseconds)
249
- HEVY_MCP_API_TIMEOUT=30000
250
- # Optional: enable verbose stderr diagnostics (only the value 1 enables it)
251
- HEVY_MCP_DEBUG=1
121
+ ```text
122
+ https://hevy.chrisdoc.dev/mcp
252
123
  ```
253
124
 
254
- ### 🧠 Exercise Template Cache Behavior
255
-
256
- `search-exercise-templates` and the `hevy://exercise-templates` resource use a
257
- shared in-memory async cache for the full exercise template catalog:
258
-
259
- - **TTL**: 5 minutes per cached catalog entry.
260
- - **Memory bound**: max 1 catalog entry (LRU bounded cache).
261
- - **In-flight de-duplication**: concurrent requests share the same active
262
- fetch when possible.
263
- - **Manual refresh**: set `refresh: true` in the tool input to invalidate the
264
- cached catalog and force a re-fetch from the Hevy API.
265
-
266
- Paginated `get-exercise-templates` requests still call the API directly to keep
267
- paging behavior explicit and avoid cross-page invalidation complexity.
268
-
269
- ### 📡 Sentry Monitoring
270
-
271
- `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:
272
-
273
- - lifecycle spans around server build, run, and stdio connect
274
- - per-tool execution spans plus captured handler exceptions
275
- - stdio parse diagnostics, including leading UTF-8 BOM stripping and invalid JSON context
276
- - a deterministic pseudonymous Sentry user ID derived from `HEVY_API_KEY`, so the raw key is never sent to Sentry
277
-
278
- ---
279
-
280
- <details>
281
- <summary><strong>⚠️ Migration Note (v1.18.0)</strong></summary>
282
-
283
- As of **v1.18.0**, `hevy-mcp` removed HTTP/SSE transport and its previous
284
- Docker packaging. Docker support is now available again for the stdio server.
285
-
286
- Both `npx hevy-mcp` and the official container image use stdio; HTTP ports and
287
- detached-container deployment are not supported.
288
-
289
- </details>
290
-
291
- ---
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:
292
128
 
293
- ## 🛠️ Available MCP Tools
294
-
295
- | Category | Tools |
296
- | :-------------------- | :--------------------------------------------------------------------------------------------------------------------------------- |
297
- | **Workouts** | `get-workouts`, `get-workout`, `create-workout`, `update-workout`, `get-workout-count`, `get-workout-events` |
298
- | **Routines** | `get-routines`, `get-routine`, `create-routine`, `update-routine` |
299
- | **Templates** | `get-exercise-templates`, `get-exercise-template`, `search-exercise-templates`, `create-exercise-template`, `get-exercise-history` |
300
- | **Folders** | `get-routine-folders`, `get-routine-folder`, `create-routine-folder` |
301
- | **Body Measurements** | `get-body-measurements`, `get-body-measurement`, `create-body-measurement`, `update-body-measurement` |
302
- | **User** | `get-user-info` |
303
-
304
- > **Delete operations are currently unsupported:** The upstream Hevy OpenAPI
305
- > spec does not expose `DELETE` endpoints for workouts, routines, routine
306
- > folders, exercise templates, or body measurements, so `hevy-mcp` does not
307
- > provide delete tools for these resources.
308
-
309
- ## 💬 Available MCP Prompts
310
-
311
- | Prompt | Arguments | Guided workflow |
312
- | :---------------------------- | :------------------------------------------------------------------------------------- | :---------------------------------------------------- |
313
- | `analyze-workout-progress` | Optional `weeks` (1-12; defaults to `4` when omitted from a supplied arguments object) | Analyze recent workout and body-measurement trends. |
314
- | `create-workout-from-routine` | `routineId`, `startTime` (UTC ISO seconds) | Record a completed workout using a routine as a plan. |
315
-
316
- Compatibility note: with MCP SDK v1.29.0, clients using the default must send
317
- `arguments: {}` because the SDK rejects requests that omit the entire
318
- `arguments` object before prompt field defaults are evaluated.
319
-
320
- ---
321
-
322
- ## 📚 Available MCP Resources
323
-
324
- | Name | URI |
325
- | :------------------- | :-------------------------- |
326
- | `user-profile` | `hevy://user` |
327
- | `workout-count` | `hevy://workout-count` |
328
- | `exercise-templates` | `hevy://exercise-templates` |
329
- | `routine-folders` | `hevy://routine-folders` |
330
-
331
- ---
332
-
333
- ## 👨‍💻 Development & Contributing
334
-
335
- ### Quick Commands
336
-
337
- - **Build**: `npm run build`
338
- - **Lint/Format**: `npm run check` (uses oxlint/oxfmt)
339
- - **Type Check**: `npm run check:types`
340
- - **Unit Tests**: `npx vitest run --exclude 'tests/integration/**'`
341
- - **Full Test Suite**: `npm test` (requires `HEVY_API_KEY`)
342
- - **Changeset Check**: `npm run check:changeset`
343
-
344
- For a detailed senior engineer guide, please refer to [AGENTS.md](./AGENTS.md).
345
-
346
- ### Pull Request Checks
347
-
348
- - **Conventional Commits**: CI lints commit messages on pull requests, so use
349
- prefixes such as `feat:`, `fix:`, `docs:`, `ci:`, `chore:`, `refactor:`,
350
- `test:`, or `style:`.
351
- - **Type Checking**: CI runs `npm run check:types` on pull requests and pushes
352
- to `main`; run this locally before opening a PR.
353
- - **Changesets**: Contributor pull requests targeting `main` must include a
354
- changeset. Dependabot PRs and automated `changeset-release/main` release PRs
355
- are handled by automation and skip this check.
356
-
357
- ### API Client Generation
358
-
359
- The API client is automatically generated from the OpenAPI spec using [Kubb](https://kubb.dev/):
360
-
361
- ```bash
362
- 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
+ }
363
140
  ```
364
141
 
365
- ### Versioning & Releases
366
-
367
- This project uses [Changesets](https://github.com/changesets/changesets) to
368
- manage versioning, changelogs, releases, and pull request validation.
369
-
370
- 1. **Routine Release Cadence**: Merge the automated
371
- `changeset-release/main` (**"Version Packages"**) Pull Request on a regular
372
- cadence (weekly is a good default) instead of ad-hoc frequent merges.
373
- 2. **Urgent Release Exception**: Security fixes and high-impact,
374
- user-facing bug fixes can be released immediately outside the routine
375
- cadence.
376
- 3. **Use Bump Changesets Only for User-Facing Runtime Changes**: If your
377
- change is user-facing/runtime-visible, run:
378
- ```bash
379
- npx changeset
380
- ```
381
- Follow the prompts to choose `patch`, `minor`, or `major`, then write a
382
- short summary. This creates a markdown file under `.changeset/`.
383
- 4. **Use Empty Changesets for Internal-Only Work**: Docs, CI, test-only,
384
- refactor, and chore changes should use an empty changeset:
385
- ```bash
386
- npx changeset --empty
387
- ```
388
- 5. **Validate Before Opening a PR**: Contributor pull requests targeting
389
- `main` are checked for a changeset in CI. Dependabot PRs and automated
390
- `changeset-release/main` release PRs are handled separately. You can run the
391
- same validation locally with:
392
- ```bash
393
- npm run check:changeset
394
- ```
395
- 6. **Automated Releases**:
396
- - Pushing changesets to `main` triggers a GitHub Action that automatically
397
- creates or updates a **"Version Packages"** Pull Request.
398
- - When this Pull Request is merged, the package is automatically built,
399
- published to npm (via OIDC Trusted Publishing), and a GitHub Release is
400
- created.
401
-
402
- ---
403
-
404
- ## 📄 License & Acknowledgements
405
-
406
- - **License**: [MIT](./LICENSE)
407
- - **Credits**: [Model Context Protocol](https://github.com/modelcontextprotocol), [Hevy Fitness](https://www.hevyapp.com/).
408
-
409
- ---
410
-
411
- **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@2.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-c3mB-R0m.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"}
package/dist/index.d.mts CHANGED
@@ -1,5 +1,4 @@
1
1
 
2
- import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
2
  import { z } from "zod";
4
3
 
5
4
  //#region src/index.d.ts
@@ -14,7 +13,7 @@ declare function createServer({
14
13
  config
15
14
  }: {
16
15
  config: ServerConfig;
17
- }): Promise<McpServer>;
16
+ }): Promise<import("@modelcontextprotocol/sdk/server/mcp").McpServer>;
18
17
  declare function runServer(): Promise<void>;
19
18
  //#endregion
20
19
  export { configSchema, createServer, createServer as default, runServer };