gym
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@gymbench, 3 more at 225"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
██████╗ ██╗ ██╗███╗ ███╗
██╔════╝ ╚██╗ ██╔╝████╗ ████║
██║ ███╗ ╚████╔╝ ██╔████╔██║
██║ ██║ ╚██╔╝ ██║╚██╔╝██║
╚██████╔╝ ██║ ██║ ╚═╝ ██║
╚═════╝ ╚═╝ ╚═╝ ╚═╝A barbell and macro log your chat client can actually use.
gym is an MCP server with a deliberately small web front end. Routines, workouts, sets, food, water — all of it logged by talking to Claude (or any MCP client) instead of tapping through a tracker app between sets.
Why this exists
Every training app asks you to stop what you are doing and operate a UI. Mid-set, out of breath, hands chalked, that is real friction — and friction is why logs die three weeks in. Same story with food: nobody wants to search a database for "chicken thigh, roasted" while dinner gets cold.
The chat client is already open. "bench, 3 more at 225" is one sentence. "how much protein do I have left today?" is one question. Both should be one tool call, not a screen.
So the tracker became a server and the interface became a conversation. There are 21 tools, an OAuth 2.0 flow so connecting a client is safe, and a web app that does exactly two things: sign you in, and let you approve a client. Everything else happens in chat.
Related MCP server: Workout Planner Ai MCP
What it can do
Routines — the program, and its planned days.
Tool | |
| Create a training program |
| List programs, with their sessions |
| Remove a program; logged workouts survive and unlink |
| Add a planned day (Push, Pull, Legs) with its exercises |
| Read planned days and their exercise order |
| Remove a planned day |
Workouts — what was actually trained.
Tool | |
| Open a live session, optionally from a routine day |
| Log one completed set — |
| Close it out |
| Recent sessions with their sets |
| Search the exercise catalogue |
| Every recent set of one lift, newest first — call before suggesting a weight |
Nutrition — food, water, targets, and the calendar day they belong to.
Tool | |
| Decide where the user's day starts and ends |
| Daily calorie and macro goals |
| One item per call, macros estimated when not stated |
| Read and correct the day's log |
| Track intake |
| Eaten vs. remaining, broken down by meal — the "how am I doing today" tool |
Plus ping, which exists to prove a connection is live.
The hard part: "today"
This sounds trivial and is not. The server runs in UTC. Postgres agreed it was 2026-08-23 01:12+00 while the person logging dinner was standing in New York at 21:12 on the 22nd. Log that meal against now() and it lands on tomorrow — the single most annoying way a food tracker can lie to you.
Two servers in two regions would disagree about the same meal. NOW() is not an answer, and neither is the server's local clock.
So the day is resolved at write time, in the user's own zone:
users.timezoneholds an IANA name (America/New_York), set once viaset_timezone.Every entry stores both
logged_at timestamptz(the instant) andlogged_on date(the calendar day it counts towards, computed throughIntl.DateTimeFormatin that user's zone).Reads filter on
logged_on, never on a timestamp range, over(user_id, logged_on)indexes.
An 11pm snack counts towards that night. A 12:05am snack counts towards the new day. The logic is checked against both 2026 DST seams, including the 01:30 that happens twice in November.
New accounts default to UTC, which is a placeholder rather than a real answer — nutrition tools return a timezone_warning until it is set, so the model knows to ask.
Connecting a client
The server speaks streamable HTTP and advertises its own OAuth metadata, so any MCP client that supports remote servers can discover the rest on its own. All you ever hand it is the /mcp URL.
Claude (web or desktop) — Settings → Connectors → Add custom connector:
Field | Value |
Name | Anything. |
URL |
|
Hit Continue. Claude calls the server, gets a 401 pointing at the authorization metadata, registers itself, and opens a browser tab. Sign in with Discord, approve the connection on the consent screen, and the tools show up in the connector list.
Claude Code
claude mcp add --transport http gym https://gym-api.skylerx.ir/mcpSame flow — the first call triggers the browser sign-in.
Notes:
The path matters.
https://hostalone will not work; it has to behttps://host/mcp.Hosted servers need real HTTPS. For local development
http://localhost:8888/mcpis fine.Nothing is granted until you click approve, and the consent screen shows which client asked and where its codes will be sent.
What happens under the hood
Two identities, never confused. A session cookie is the human, browser only. A bearer token is the client, API only — and it only exists after that human clicked approve.
sequenceDiagram
participant C as MCP client
participant A as API (Hono)
participant B as Browser
participant D as Discord
C->>A: POST /mcp (no token)
A-->>C: 401 + WWW-Authenticate → metadata
C->>A: POST /oauth/register
C->>B: open /oauth/authorize?…PKCE
A-->>B: 302 /login?return_to=…
B->>D: sign in
D-->>A: callback → session cookie
A-->>B: 302 back to /authorize
A-->>B: 302 /consent?request_id=…
B->>A: approve
A-->>C: redirect_uri?code=…
C->>A: POST /oauth/token (+ verifier)
A-->>C: access_tokenDetails worth knowing:
PKCE (S256) throughout, with dynamic client registration, advertised at
/.well-known/oauth-authorization-server.Nothing is granted until consent.
/authorizeparks the request in Redis for ten minutes; only the approve route mints a code.Consent is bound to the account that started it. Approve and deny are
GETnavigations, because aSameSite=Laxcookie will not travel on a cross-site POST — so each pending request records who created it and refuses a different session. An attacker can start a flow; only their own account can ever consent to it.return_tois origin-checked on both sides, so an interrupted/authorizecan resume without becoming an open redirect.One MCP server per request. Tools close over the authenticated user, so nothing leaks between callers.
Stack
API | Hono 4 · |
MCP |
|
Data | Postgres 17 · Drizzle ORM 1.0-rc · Redis 7 for OAuth state, codes and pending consent |
Web | Next.js 16 (App Router, RSC) · Tailwind 4 · Biome |
Auth | OAuth 2.0 + PKCE for clients · Discord OAuth for humans |
Quick start
pnpm install
docker compose up -d # postgres :5432, redis :6379
cp apps/backend/.env.example apps/backend/.env # then fill in Discord creds
pnpm --filter backend db:push
pnpm --filter backend dev # :8888
pnpm --filter www dev # :3000Open http://localhost:3000, sign in, and point an MCP client at http://localhost:8888/mcp.
Uses pnpm throughout.
pnpm dlxin place ofnpx.
Environment
apps/backend/.env
Variable | |
|
|
| Port to listen on |
| Postgres connection string |
| Redis connection string |
| Public origin of this API. Every OAuth URL it advertises is built from this |
| Public origin of the web app. Login and consent redirects go here |
| Optional. Scope for the session cookie, e.g. |
| From the Discord developer portal |
|
|
apps/www/.env.local
Variable | |
| Must equal the backend's |
| Optional. Hostname this app is served from when it is not localhost — Next blocks cross-origin dev asset requests without it. Host only, no scheme |
Layout
apps/
backend/
src/
routes/ auth · oauth · well-known
middleware/ is-authenticated (cookie) · mcp-gate (bearer)
services/ auth · tool-manager · nutrition · ownership
tools/ one file per MCP tool, registered in index.ts
utils/ day · urls · cookies · env · mcp · format
db/ schema + drizzle client
www/
src/app/ / · /login · /consent
src/lib/ api · sessionAdding a tool: write the file, export a defineTool({...}), add one line to tools/index.ts. The registry is explicit on purpose — the compiler checks every entry, and registration stays synchronous.
Deploying
The API and the site can live on separate hosts, but the session cookie has to reach both. Put them on subdomains of one domain you own and set COOKIE_DOMAIN to the shared parent:
gym-api.skylerx.ir → HOSTED_API_URL
gym.skylerx.ir → FRONTEND_URL
COOKIE_DOMAIN=.skylerx.irTwo unrelated hostnames still complete the OAuth flow — every step that needs the cookie happens on the API host — but the site can never show a signed-in state, so its "already signed in, skip the login page" check goes dead.
Secure on the session cookie follows HOSTED_API_URL's scheme, so serving the API over https is enough; there is no separate flag to remember.
Not done yet
Refresh grant validates a differently-derived hash than the one it stored, so token renewal fails. Access tokens last an hour.
No sign-out route.
Google sign-in was removed; Discord is the only provider.
No editing of a logged set, and no personal-record tool.
The frontend never reports the browser's timezone at sign-up —
set_timezoneis the only path.
This server cannot be installed
Maintenance
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
- FlicenseAqualityBmaintenancePersonal workout coach MCP server that logs exercises in natural language, tracks progress with SQLite, and provides coaching signals like estimated 1RM and volume trends.6
- AlicenseNot gradedqualityBmaintenanceEnables creating workout plans, tracking progress, suggesting exercises, and calculating training volume through natural language, compliant with MCP protocol.MIT
- AlicenseNot gradedqualityBmaintenanceSelf-hosted fitness tracking MCP server that gives AI assistants access to your nutrition, training, weight, sleep, and accomplishment data via 77 tools and 5 resources. Enables natural-language logging and querying of personal health metrics through Claude or ChatGPT.1BSD 2-Clause "Simplified"
- FlicenseNot gradedqualityCmaintenanceOffline MCP server for logging workouts, tracking dietary macros, and retrieving daily summaries, all stored in local SQLite. Enables fitness tracking via natural language in MCP-compatible clients.
Related MCP Connectors
Create Hevy routines and analyze your training from chat. Unofficial; BYO Hevy PRO API key.
Manage clients, plans, sessions, habits, and billing on Trainzilla via one-click OAuth.
Log, query, and edit expenses, budgets, and accounts in Manilo from any MCP-compatible AI assistant.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/SklyerX/gym-app-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server