Skip to main content
Glama
RyK57

hevy-mcp-server

by RyK57

hevy-mcp-server

MCP server for the Hevy workout tracking API. Gives an LLM read and write access to workouts, routines, exercise templates, per-exercise history, and body measurements.

Covers all 15 endpoints of the Hevy public API (v0.0.1) across 27 tools.

Requirements

Related MCP server: hevy-mcp-server

Install

pnpm install
pnpm run build

Configure

Set HEVY_API_KEY in your MCP client config. For Claude Desktop, in claude_desktop_config.json:

{
  "mcpServers": {
    "hevy": {
      "command": "node",
      "args": ["/absolute/path/to/hevy-mcp-server/dist/index.js"],
      "env": { "HEVY_API_KEY": "your-key-here" }
    }
  }
}

Variable

Required

Default

Purpose

HEVY_API_KEY

yes

Your Hevy API key

HEVY_API_BASE_URL

no

https://api.hevyapp.com

Override the API host

HEVY_REQUEST_TIMEOUT_MS

no

30000

Per-request timeout

TRANSPORT

no

stdio

stdio or http

PORT / HOST

no

3000 / 127.0.0.1

HTTP transport bind address

MCP_PATH_SECRET

when hosted

Serves the endpoint at /mcp/<secret>. Required when HOST is not loopback

ALLOWED_ORIGINS

no

localhost + claude.ai

Comma-separated origin allowlist

Remote/HTTP mode, locally:

TRANSPORT=http PORT=3000 pnpm start   # POST JSON-RPC to http://127.0.0.1:3000/mcp

Inspect the tools interactively:

HEVY_API_KEY=your-key pnpm run inspect

Deploying (for Claude mobile / claude.ai connectors)

Claude connects to custom connectors from Anthropic's cloud, not from your device, so mobile and claude.ai need this reachable over public HTTPS. Claude Code and Claude Desktop don't — use stdio there instead.

1. Generate a path secret

openssl rand -hex 32

The server refuses to start on a non-loopback interface without MCP_PATH_SECRET set, because a public endpoint holding your Hevy key is an open proxy to your account. With it set, the endpoint moves to /mcp/<secret> and every other path returns 404 — including a wrong secret, so probing the host doesn't reveal that an MCP server lives there.

2. Deploy

The included Dockerfile and railway.json work as-is on Railway, Render, or Fly. The image sets TRANSPORT=http and HOST=0.0.0.0 and runs as a non-root user. Set two variables in the platform's dashboard:

Variable

Value

HEVY_API_KEY

your key from https://hevy.com/settings?developer

MCP_PATH_SECRET

the value from step 1

PORT is injected by the platform. /healthz is an unauthenticated liveness probe.

3. Verify

curl -s https://your-app.up.railway.app/healthz
# {"status":"ok","server":"hevy-mcp-server","version":"1.0.0"}

4. Add the connector

On claude.ai in a browser — connectors can't be added from the mobile app:

  1. Customize → Connectors → Add custom connector

  2. URL: https://your-app.up.railway.app/mcp/<secret>

  3. On your phone, open a chat and enable it under + → Connectors

Treat that URL like a password: it's the only thing standing between the internet and your training log. If it leaks, rotate MCP_PATH_SECRET and re-add the connector.

Tools

Workoutshevy_list_workouts, hevy_get_workout, hevy_count_workouts, hevy_list_workout_events, hevy_create_workout, hevy_update_workout

Sessionshevy_start_session, hevy_get_active_session, hevy_finish_session, hevy_cancel_session

Routineshevy_list_routines, hevy_get_routine, hevy_create_routine, hevy_update_routine

Routine foldershevy_list_routine_folders, hevy_get_routine_folder, hevy_create_routine_folder

Exercise templateshevy_search_exercise_templates, hevy_list_exercise_templates, hevy_get_exercise_template, hevy_create_exercise_template

Progresshevy_get_exercise_history, hevy_list_body_measurements, hevy_get_body_measurement, hevy_create_body_measurement, hevy_update_body_measurement

Accounthevy_get_user_info

Every read tool takes response_format: "markdown" | "json". Markdown is the default and is optimized for an LLM reading it; JSON is the full structured payload. structuredContent is always populated regardless of format.

Examples

"What did I train this week?"hevy_list_workouts with page_size=5. Returns titles, duration, exercise list, and total volume per session.

"Log today's bench: 3x8 at 60kg"hevy_search_exercise_templates with query="bench press" to get the id, then hevy_create_workout with three sets of { weight_kg: 60, reps: 8 }.

"I'm starting legs now"hevy_start_session with title="Leg Day". The start time is stamped server-side and the session shows in Hevy as in-progress. When you're done, hevy_finish_session with what you performed closes it out with the real duration.

"Am I getting stronger on squats?"hevy_search_exercise_templates with query="squat", then hevy_get_exercise_history with a start_date. Returns every logged set newest-first, plus the best set by estimated 1RM.

Design notes

Search before writing. Hevy has no server-side exercise search, but every write needs an exercise_template_id. hevy_search_exercise_templates pages through the catalogue (up to 30 pages of 100) and filters locally on title, muscle group, equipment, and custom-only. Point the model at this tool first — ids cannot be guessed.

Updates are replacements, not patches. hevy_update_workout, hevy_update_routine, and hevy_update_body_measurement overwrite the entire resource; anything omitted is deleted or nulled. All three carry destructiveHint: true, and their descriptions tell the model to read the current state first. These are the only three destructive tools — the Hevy API has no delete endpoints.

Live sessions are a title convention, not server state. Hevy's API has no start-workout endpoint and cannot drive the in-app timer, so hevy_start_session creates a real workout up front titled 🔴 In Progress — <title>, and hevy_finish_session rewrites it with the true end time. That marker is the only handle that persists — the server holds no state between requests, so any chat on any device finds the open session by scanning recent workouts. The cost is that an unfinished session stays visible in the log, and since Hevy exposes no delete, hevy_cancel_session can only relabel it, never remove it.

Everything is kilograms. The API has no unit field. Input fields are named weight_kg so there's no ambiguity about what the model is sending, and markdown output renders both (60 kg (132.3 lb)) so a US-based reader doesn't have to convert mentally.

Page-size caps are enforced client-side. Hevy returns a bare 400 for an oversized page. The Zod schemas cap each endpoint at its documented limit (10 for most, 100 for exercise templates), so the model gets a precise message instead of a failed request.

Errors resolve to next actions. A 404 names the tool that produces valid ids for that resource. A 409 on a body measurement points at the update tool. A 403 explains that API access requires Pro.

Permissive output schemas. Hevy's docs warn that this 0.0.1 API may change structure without notice. Output schemas use passthrough() with optional fields so an upstream field addition doesn't turn into a hard tool failure.

Project layout

src/
├── index.ts               # entry point, transport selection
├── constants.ts           # API limits, enums, character limit
├── types.ts               # interfaces for every Hevy entity
├── services/
│   └── hevy-client.ts     # fetch wrapper, auth, error → guidance mapping
├── schemas/
│   ├── inputs.ts          # Zod input schemas
│   └── outputs.ts         # structuredContent schemas
├── formatters/
│   ├── response.ts        # pagination, truncation, format dispatch
│   └── entities.ts        # per-entity markdown rendering
└── tools/
    ├── workouts.ts
    ├── sessions.ts         # in-progress workout tracking
    ├── routines.ts
    ├── exercise-templates.ts
    └── progress.ts

Caveats

  • The Hevy API is officially version 0.0.1 and its own docs warn the structure may change or be abandoned.

  • A routine's folder can't be changed after creation — the update endpoint doesn't accept folder_id.

  • Equipment filtering in search matches against the exercise title, since the API doesn't expose equipment as a field on templates.

  • hevy_create_exercise_template returns a numeric id, unlike the string ids used everywhere else in the API.

Tests

pnpm run build
pnpm test         # 45 checks: MCP handshake, tools, sessions, formatting, errors (mocked API)
pnpm run test:http  # 13 checks: path-secret gating, health check, origin allowlist

Both suites run against a local mock, so no API key or network access is needed.

A
license - permissive license
Not graded
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables interaction with the Hevy fitness tracking platform through their API. Supports managing workouts, routines, exercise templates, and webhook subscriptions for comprehensive fitness data management.
    9
    ISC
  • A
    license
    Not graded
    quality
    C
    maintenance
    Exposes the Hevy workout API to Claude, enabling users to manage workouts, routines, exercise templates, body measurements, and user info via natural language.
    5,897
    MIT

View all related MCP servers

Related MCP Connectors

  • Create Hevy routines and analyze your training from chat. Unofficial; BYO Hevy PRO API key.

  • Training analytics over your Hevy log: e1RM, PRs, volume, consistency, bodyweight.

  • 63 tools for Apple Health, Fitbit, Oura & Health Connect data in Claude, ChatGPT, Grok & Mistral.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/RyK57/hevy-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server