Fitaily MCP
This server does not currently have a deployable release on Glama. Follow the repository's setup instructions to install and configure it for your MCP client, including any required credentials and local dependencies.
Fitaily MCP
Remote Model Context Protocol server that exposes the Fitaily nutrition, training and progress API as 66 tools over Streamable HTTP.
Companion server. Fitaily MCP has no database and no business logic of its own: every tool calls the Fitaily REST API with the user's OAuth token. You need a running Fitaily backend, the same
JWT_SECRET, and an OAuth client (ChatGPT, Claude, Cursor, OpenCode…). It is not a standalone fitness tracker.
What it is
Stateless. One
McpServer+ transport per request; no sessions, no cache, no storage.OAuth 2.1 (PKCE). The Fitaily backend is the authorization server; this process only verifies HS256 access tokens (audience, scopes, expiry).
Scoped access. Every tool checks a
*:reador*:writescope before calling the backend; writes are annotated aswrite/destructiveso clients can ask first.Thin. Backend failures are classified as unauthorized (
401/403) or unreachable/error (502) and returned as short tool errors; response bodies are never forwarded to the model.Structured results. Every tool declares an
outputSchemaand returns the same JSON instructuredContentand incontent[0].text, so typed clients can parse results while text-only clients keep working.
Related MCP server: OpenGym Coach
What it is not
Not a medical device and not medical advice. It reports what the user logged.
Not a data store: nothing is persisted, cached or written to disk.
Not a replacement for the Fitaily REST API — the API remains the source of truth.
Requirements
Requirement | Notes |
Node.js 26+ | matches the Docker image and CI |
pnpm 10+ |
|
Fitaily backend | must expose |
OAuth client | any MCP client that supports remote HTTP + OAuth discovery |
Quickstart
git clone https://github.com/rafafau/fitaily-mcp.git
cd fitaily-mcp
corepack enable
pnpm install
cp .env.example .env # set JWT_SECRET, FITAILY_API_URL and MCP_RESOURCE_URL
pnpm devcurl -s http://localhost:3091/health
# {"success":true,"service":"fitaily","version":"0.2.0","timestamp":"…"}To exercise /mcp locally you need a token minted for this resource. Load the same
.env in your shell and create a short-lived development token:
set -a; . ./.env; set +a
TOKEN=$(node -e "console.log(require('jsonwebtoken').sign(
{ userId: 'dev', scope: 'nutrition:read training:read progress:read', aud: process.env.MCP_RESOURCE_URL },
process.env.JWT_SECRET,
{ expiresIn: '15m', algorithm: 'HS256' }
))")
curl -s http://localhost:3091/mcp \
-H "Authorization: Bearer $TOKEN" \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{
"protocolVersion":"2025-06-18","capabilities":{},
"clientInfo":{"name":"curl","version":"0"}}}'Connect a client
The public endpoint is https://mcp.fitaily.com/mcp; locally it is
http://localhost:3091/mcp. Authentication is discovered automatically through
/.well-known/oauth-protected-resource and /.well-known/oauth-authorization-server.
Claude Code
claude mcp add --transport http fitaily https://mcp.fitaily.com/mcpCursor / VS Code / generic JSON config
{
"mcpServers": {
"fitaily": { "type": "http", "url": "https://mcp.fitaily.com/mcp" }
}
}OpenCode
{
"mcp": {
"fitaily": { "type": "remote", "url": "https://mcp.fitaily.com/mcp", "enabled": true }
}
}Claude Desktop (no native remote transport — bridge it):
{
"mcpServers": {
"fitaily": { "command": "npx", "args": ["-y", "mcp-remote", "https://mcp.fitaily.com/mcp"] }
}
}ChatGPT — Settings → Connectors → add a custom connector with the endpoint URL, then complete the OAuth prompt.
During OAuth the client registers itself dynamically, opens the Fitaily consent screen and
receives an access token whose aud must equal MCP_RESOURCE_URL. A mismatch is rejected
with 403 Token audience mismatch.
Configuration
Variable | Required | Default | Purpose |
| ✅ | — | Verifies HS256 access tokens. Must equal the backend value. |
| ✅ in production |
| Public endpoint URL and expected token audience. No trailing slash. |
| ✅ |
| Base URL of the REST API, including |
| ✅ |
| Authorization server issuer, used in discovery documents and the optional |
|
| HTTP port. | |
|
|
| |
|
| Reverse-proxy hops for client IP + | |
|
| Max JSON body for | |
|
| Rate-limit window per IP. | |
|
| Requests per window per IP on | |
|
|
|
Authentication and scopes
Tokens are HS256 JWTs with userId, client_id, scope, aud, jti and a 15-minute TTL.
The server pins HS256, checks aud, and verifies iss when the claim is present.
Scope | Unlocks |
| meals, foods, water, recipes, diet plans, pantry, profile |
| log/edit/delete meals and water, change goals, recipe CRUD, diet-plan generate/activate/extend, fridge and shopping list |
| activities, plans, workout templates, exercise catalog, strength stats |
|
|
| measurements, goals, aggregates, trends, forecasts |
| add/update measurements and goals |
A 401 response carries WWW-Authenticate: Bearer resource_metadata="…" so clients can
find the authorization server. Missing scopes return 403 Missing scope: <scope>.
Write confirmation is a client responsibility. The server marks mutating tools with
readOnlyHint: false and deletions with destructiveHint: true, but it cannot block a call
the model already decided to make. The bundled skills encode the
“show a summary → wait for yes → call the tool” workflow.
Tools
Full reference with scopes and read/write/destructive labels: docs/tools.md.
Group | Tools | Highlights |
Nutrition | 8 | today's totals, meal history, goals, meal suggestions, meal CRUD |
Foods | 2 | catalog search, barcode lookup |
Water | 3 | history, log, delete |
Recipes | 13 | public catalog, tags, favorites, ratings, CRUD, “fit remaining macros” |
Diet plans | 5 | list, detail, generate, activate, extend |
Training | 8 | history, plans, cardio logging, workout template CRUD |
Exercise catalog | 2 | search, detail |
Strength stats | 3 | personal records, exercise history, muscle activation |
Progress | 6 | summary, measurements, goals |
Stats | 7 | nutrition/activity/measurement aggregates, history, trend, forecast |
Profile | 3 | profile, coach plan, dashboard summary |
Fridge & shopping | 6 | fridge items, shopping list |
Architecture
client ──OAuth token──▶ POST /mcp
├─ rate limit (per IP)
├─ verify JWT (HS256, aud, scopes)
├─ parse JSON (max 1 MB)
├─ new McpServer + tools bound to the token
└─ fetch FITAILY_API_URL/... (10–15 s timeout)One server/transport per request: safe to run multiple replicas, no sticky sessions.
No database, no queue, no disk writes; rate-limit counters live in process memory.
The backend body is never returned to the model — only a stable status and a generic message, so an internal error cannot leak data or HTML.
Backend quirks worth knowing before changing tools: docs/backend-contract.md.
Development
pnpm dev # tsx dev server on :3091 (loads .env when present)
pnpm test # vitest (unit + HTTP integration)
pnpm typecheck # src + tests
pnpm lint # eslint 10 + typescript-eslint
pnpm format # prettier
pnpm build # tsc → dist/
pnpm validate:skills # SKILL.md frontmatter + tool namessrc/
api/ fetch wrapper for the Fitaily API
auth/ JWT verification + scope checks
schemas/ zod input schemas shared by all tools
tools/ one file per domain (66 tools)
config.ts env parsing
server.ts express app, OAuth discovery, /mcp
tests/ vitest + supertest
docs/ tool reference and backend contract
skills/ agent skills that teach clients how to use the toolsAdding or renaming a tool
Add the zod schema in
src/schemas/common.ts.Register it in
src/tools/<domain>.tswith a description that says when to call it,annotations, and the matchingrequireScope.Add the row to
docs/tools.md(the docs test fails otherwise).Add or update a test in
tests/tools.test.tsand, if it is a new workflow, a skill.Run
pnpm lint && pnpm typecheck && pnpm test.
Self-hosting
docker build -t fitaily-mcp .
docker run --rm -p 3091:3091 --env-file .env fitaily-mcpdocker-compose.yml next to the backend:
services:
mcp:
build: .
env_file: .env
restart: unless-stopped
ports:
- "3091:3091"
# Same private network as the backend; FITAILY_API_URL can then use
# http://backend:3001/api instead of a public hostname.
networks:
- fitaily
networks:
fitaily:
external: truePut a TLS-terminating reverse proxy or tunnel in front of it and keep
TRUST_PROXY=1; the container runs as the unprivileged node user and exposes a
HEALTHCHECK against /health.
Privacy and data handling
The server stores nothing: no database, no cache, no files, no analytics.
Access logs contain method, path, status and duration only — never tokens or bodies.
Health data (meals, weight, workouts) passes through in memory for the duration of a request. Fitaily's own privacy policy governs the backend data.
Rate-limit counters are in memory and disappear on restart.
Security
Please report vulnerabilities privately — see SECURITY.md. Do not open a public issue for a suspected token leak or auth bypass.
Operational notes:
JWT_SECRETis shared with the backend. Rotating it invalidates every outstanding token.Tokens are bearer credentials: never log them, never put them in a URL.
Keep
MCP_RESOURCE_URLexact; a trailing slash or wrong scheme breaks the audience check.The default rate limit is intentionally generous (300 req/min/IP). Tighten it for public deployments if your clients make many parallel tool calls.
Design decisions
Generic
outputSchema. Every tool advertisesoutputSchema: { type: "object" }rather than 66 per-tool field schemas. Tools return trimmed, purpose-built projections, and the real consumer benefit isstructuredContentmirroringcontent[0].text. A per-tool schema would duplicate projections and break when the backend adds fields.No streaming progress notifications. Every call is a single backend round-trip (typically 100–800 ms). If a future tool (e.g. AI diet plan generation) needs minutes, progress notifications can be added then without changing today's clients.
ESM modules. The package is
"type": "module"and compiled withmodule: NodeNext. This matches the modern Node/MCP ecosystem; the Docker image builds the TypeScript inside the container and ships onlydist/.
Contributing
Issues and pull requests are welcome. See CONTRIBUTING.md for the local loop and the tool checklist.
License
Apache License 2.0 © 2026 Rafal Sipiatowski. See NOTICE for the attribution notice. The license includes an express patent grant; modified files must carry prominent change notices when redistributed.
Fitaily is a trademark of its owner. This repository is an independent integration; the Fitaily backend and mobile apps are not part of it.
This server cannot be deployed
Maintenance
Related MCP Connectors
Hosted MCP server with managed OAuth for 15+ toolkits: Google Workspace, Fitbit, Oura, Kalshi, etc.
Multi-tenant hosted MCP server for Oura Ring — 21 read-only tools, OAuth per user.
Discover, plan and run tools across your connected business systems through one OAuth MCP endpoint
Query, browse, and automate OmegaAI workspaces from any MCP client. Streamable HTTP with OAuth 2.0.
Related MCP Servers
- 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.72 npm1BSD 2-Clause "Simplified"
- AlicenseNot gradedqualityBmaintenanceEnables ChatGPT to manage fitness routines, guided sessions, workout history, body weight tracking, and statistics through a remote authenticated MCP server with read and write tools.AGPL 3.0
- AlicenseNot gradedqualityBmaintenanceEnables logging workouts, sets, routines, food, water, and macros through natural-language chat in any MCP client, with OAuth-based secure access and timezone-aware daily tracking.ISC
- AlicenseNot gradedqualityCmaintenanceEnables MCP-compatible clients to search foods and manage a personal nutrition diary, saved meals, exercise, weight, favorites, recipes, and monthly summaries via the FatSecret Platform API. It provides 39 tools with confirmation for mutating actions, OAuth 1.0 3-legged authentication, and MCP Streamable HTTP transport.MIT