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 +203 -343
- package/dist/cli.mjs +4 -4
- package/dist/cli.mjs.map +1 -1
- package/dist/index.d.mts +1 -2
- package/dist/index.mjs +2 -2
- package/dist/{src-c3mB-R0m.mjs → src-CkkrTrrg.mjs} +899 -845
- package/dist/src-CkkrTrrg.mjs.map +1 -0
- package/package.json +23 -5
- package/server.json +2 -2
- package/dist/src-c3mB-R0m.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -1,162 +1,90 @@
|
|
|
1
|
-
# hevy-mcp:
|
|
1
|
+
# hevy-mcp: Hevy workouts for your AI assistant
|
|
2
2
|
|
|
3
3
|
[](https://opensource.org/licenses/MIT)
|
|
4
4
|
[](https://github.com/chrisdoc/hevy-mcp/actions/workflows/build-and-test.yml)
|
|
5
5
|
[](https://codecov.io/gh/chrisdoc/hevy-mcp)
|
|
6
6
|
[](https://www.npmjs.com/package/hevy-mcp)
|
|
7
7
|
|
|
8
|
-
|
|
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
|
-
##
|
|
15
|
+
## Quick Start
|
|
13
16
|
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
30
|
+
Claude Desktop (`claude_desktop_config.json`) and Cursor (`~/.cursor/mcp.json`)
|
|
31
|
+
both accept an `mcpServers` entry like this:
|
|
40
32
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
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
|
|
41
|
+
"hevy": {
|
|
126
42
|
"command": "npx",
|
|
127
43
|
"args": ["-y", "hevy-mcp"],
|
|
128
44
|
"env": {
|
|
129
|
-
"HEVY_API_KEY": "
|
|
45
|
+
"HEVY_API_KEY": "your-hevy-api-key"
|
|
130
46
|
}
|
|
131
47
|
}
|
|
132
48
|
}
|
|
133
49
|
}
|
|
134
50
|
```
|
|
135
51
|
|
|
136
|
-
|
|
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
|
-
"
|
|
141
|
-
|
|
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
|
-
|
|
146
|
-
outside the repository containing your real key:
|
|
71
|
+
#### Docker
|
|
147
72
|
|
|
148
|
-
|
|
149
|
-
|
|
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
|
-
|
|
153
|
-
|
|
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
|
|
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
|
-
|
|
175
|
-
|
|
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
|
-
|
|
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=
|
|
109
|
+
npx add-mcp hevy-mcp --env "HEVY_API_KEY=your-hevy-api-key"
|
|
213
110
|
```
|
|
214
111
|
|
|
215
|
-
|
|
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
|
-
>
|
|
234
|
-
> `hevy
|
|
235
|
-
>
|
|
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
|
-
|
|
238
|
-
timeout. Its value is in milliseconds.
|
|
119
|
+
When available, the hosted endpoint does not require Node.js, Bun, or Docker:
|
|
239
120
|
|
|
240
|
-
|
|
241
|
-
|
|
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
|
-
|
|
255
|
-
|
|
256
|
-
`
|
|
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
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
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
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
-
|
|
407
|
-
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
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@
|
|
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] = "
|
|
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-
|
|
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()
|
|
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()
|
|
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 };
|