catence
Catence is a local, read-only MCP server that integrates fitness and health data from Garmin, Intervals.icu, and Strava, enabling AI-assisted analysis and reporting. Key capabilities:
Data Discovery & Status: Check sync state, list datasets, schemas, and coverage via catence_status, describe_data, describe_dataset.
Querying & Aggregation: Fetch time-series data with read_series (with downsampling), run aggregations with aggregate_data, or use custom SQL via query_read_only_data.
Statistical Analysis & Modeling: Perform rolling statistics, correlations, trends, and anomalies with analyze_series; fit regression models with fit_series_model.
Activity & Performance: Find activities by filters with find_activities, retrieve FTP/VO2max history, generate cycling and swim progress reports.
Power Analysis: Explore power-duration bests via power_curve_trend and power_coverage_report.
Swimming: Get lap data with get_swim_laps and session comparisons with swim_progress_report.
Strava Enrichment: On-demand hydration of Strava activities and segments (get_activity_segments, hydrate_strava_activity, etc.).
Search: Find relevant context across activities, plans, and messages with search_context.
All tools are read-only except the explicit hydration operations, ensuring data provenance and quality.
Allows syncing and importing canonical activity and health data from Garmin Connect, including activities, daily health metrics, FTP history, VO2max estimates, and more.
Provides targeted enrichment of activities with Strava data, including hydrating individual activities, recent activities, and segment history, using a read-only Strava API allowlist.
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., "@catenceWhat's my average pace for outdoor runs this year?"
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.
Catence
Local MCP server for primary Garmin data, with added Intervals.icu metrics and Strava enrichment.

... what?
As a context, I'm both an endurance athlete and a data junkie. I already got a coach for all the serious stuff, but I wanted to hook up some—any—LLM to the insane amount of data collected from Garmin, derived on Intervals.icu (I don't pay for TrainingPeaks) and comparable efforts on Strava segments. Naturally, the first answer was a local MCP server for my current tooling.
Related MCP server: fitMCP
What is included
Garmin, Intervals.icu, and Strava ingestion with source-aware normalization.
Read-only MCP tools, plus explicitly named, lock-guarded write tools for Strava hydration and detached syncs.
One shared Catence agent can serve several isolated athlete stores. Every personal-data MCP call names an
athleteId; Catence never silently combines athletes.A password-protected Chainlit Console with an authenticated dashboard, a data-sync button with live progress, and in-app model management.
A generated demo catalog for safe evaluation in Glama, desktop MCP clients, or local development.
Catence helps explore recovery, training load, trends, activity detail, swimming/cycling/running progress, segments, gear, and data quality. It reports the evidence and coverage it can see; it does not diagnose or prescribe training.
Requirements
Node.js 22+
Python 3.12+ and uv for Garmin and Strava provider workers
Provider credentials for the athletes you choose to sync
Quick start
Install Catence and create the first athlete. The default catalog home is ~/.catence; set CATENCE_HOME or pass --home to use a different location.
Every catence-data command requires --athlete <id>; there is no default athlete. Pair it with --home <dir> to select the catalog when not using the default home.
npm install --global catence@latest # or catence@beta
catence-data setup --athlete alex --label "Alex"Store each provider value through stdin so it does not enter shell history. Values are written to the selected athlete's owner-only local secret file.
printf %s 'alex@example.com' | catence-data --athlete alex secret set --provider garmin --field email --value-stdin
printf %s 'your-garmin-password' | catence-data --athlete alex secret set --provider garmin --field password --value-stdin
printf %s 'intervals-api-key' | catence-data --athlete alex secret set --provider intervals --field apiKey --value-stdin
printf %s '12345' | catence-data --athlete alex secret set --provider intervals --field athleteId --value-stdinSync and create retrieval context:
catence-data --athlete alex sync --provider all
catence-data --athlete alex build-retrieval-indexStart the stdio MCP server:
catenceAn agent first calls list_athletes, then includes athleteId with every data tool. This is intentional: a shared agent may access the stores you configured, but no tool implicitly aggregates or crosses between athletes.
Add another athlete
catence-data athlete add --id sam --label "Sam"
printf %s 'sam@example.com' | catence-data --athlete sam secret set --provider garmin --field email --value-stdin
printf %s 'sam-password' | catence-data --athlete sam secret set --provider garmin --field password --value-stdin
catence-data --athlete sam sync --provider garmin
catence-data athlete listGarmin, Intervals, and Strava client credentials are isolated per athlete. Strava OAuth tokens remain in that athlete's own store. The old 0.1 single-store directory cannot be migrated safely: create a fresh home and re-sync each athlete.
Common operations
catence-data --athlete alex status
catence-data --athlete alex sync --provider intervals
catence-data --athlete alex sync --provider garmin --from 2025-07-29
catence-data --athlete alex backfill --provider garmin --from 2020-01-01 --refresh
catence-data --athlete alex retry --run <run-id>
catence-data --athlete alex progress --watch
catence-data --athlete alex auth strava --callback
catence-data --athlete alex disconnect strava
catence-data update --check
catence-data updateDocumentation
Document | Covers |
Install, catalog, secrets, sync, background progress, stdio/HTTP MCP, demo, common operations | |
Local web chat setup, model config, doctor, updates, troubleshooting | |
One-container stack: deploy script, | |
Complete | |
Model providers (OpenAI, Anthropic, OpenAI-compatible/Azure, Opencode Go/Zen), reasoning effort | |
Design rationale, layers, data flow, serving | |
Implementation contract for answering questions, current tools, planned endpoints | |
Release artifacts: npm, PyPI, APM, MCPB |
MCP clients and HTTP
For a packaged installation, point a client at catence:
codex mcp add catence -- catence
claude mcp add --transport stdio catence -- catenceFor a source checkout:
codex mcp add catence -- npm --prefix /absolute/path/to/catence run mcpOptional local Streamable HTTP MCP and dashboard APIs:
catence serve --host 127.0.0.1 --port 8787GET /api/v1/athletes returns IDs and labels only. GET /api/v1/dashboard requires athleteId, for example http://127.0.0.1:8787/api/v1/dashboard?athleteId=alex&days=28. Browser origins must be listed with --allow-origin; the packaged Console instead proxies the dashboard through its authenticated same-origin route. The MCP server has no authentication of its own.
Configuration
config.example.json documents rate limits, Strava budgets, and Console model profiles. Keep per-athlete provider values in catence-data secret set, not in .env or config.json. The full config.json schema —including per-model reasoning effort— is documented in docs/configuration.md and docs/llm-providers.md.
For source development:
npm ci
npm run check
npm test
UV_CACHE_DIR=$PWD/.cache/uv uv run --project console --group dev python -m pytest console/tests -qData and caveats
The current available sources respond to my own used platforms. I used some wrappers:
Strava is only used for segments and gear.
Caveats
There are two caveats to the data fetching, both coming from the fact that this was created to be used by a single person. Accessing the full Garmin API requires applying via a company—which I don't have—and getting Strava data for multiple users is another headache I don't want to get into.
I don't use the official Garmin Connect API. The library uses email/pwd.
Connecting Strava requires the user to be a Strava Premium subscriber and create an API application. The rotating token is stored locally in
<data-dir>/secrets/strava.json.
Maintenance
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceMCP server that exposes Garmin Connect health and activity data (steps, sleep, stress, activities, etc.) via tools for querying, analysis, and visualization.Apache 2.0
- FlicenseNot gradedqualityBmaintenanceA multi-platform fitness MCP server that syncs data from Garmin, Strava, Google Fit, and Suunto into a local DuckDB database and provides analytics tools via MCP.1
- AlicenseBqualityAmaintenancePrivacy-first MCP server for Strava activities, streams, routes and training data.293382MIT
- AlicenseAqualityBmaintenanceMCP server for reading and querying Garmin Connect data, including activities, strength history, recovery, trends, and optionally creating workouts.12MIT
Related MCP Connectors
MCP server for Withings health data — sleep, activity, heart, and body metrics.
Garmin data in Claude & ChatGPT via the Garmin Health API. OAuth sign-in, no password sharing.
MCP server for interacting with the Supabase platform
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/rifusaki/catence'
If you have feedback or need assistance with the MCP directory API, please join our Discord server