tymewear-mcp
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., "@tymewear-mcpWhat are my current VT1 and VT2 thresholds?"
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.
Tyme Wear MCP Server
A Model Context Protocol server that connects Claude to the Tyme Wear breathing sensor platform. Analyze your ventilatory data, activities, thresholds, and training zones directly through Claude.
Built on the same architecture as trainingpeaks-mcp.
What is Tyme Wear?
Tyme Wear makes the VitalPro chest strap, a wearable breathing sensor that measures ventilatory metrics (breathing rate, tidal volume, minute ventilation) alongside heart rate. It uses ventilatory thresholds (VT1, VT2) to define personalized training zones. Used by Team Visma | Lease a Bike.
Related MCP server: Strava MCP Server
Features
40 MCP tools for profile, activities, breathing data, VE thresholds, compact per-activity analysis, activity files/detection, training plans, workout recommendations, integrations, subscription/account, resting/max physiology, and exports
Secure credential storage via system keyring (macOS Keychain / Windows Credential Manager) with AES-256-GCM encrypted file fallback
Auto-authentication with token caching and automatic re-auth on expiry
Smart breathing data with summary, window, and full modes to avoid context overflow
Per-activity insights (
tw_get_activity_insights): detected VT1/VT2/VO2max with measured power-at-threshold, confidence scores, a truncated-test flag, and per-zone time/calories — in one call, no FIT parsingCompact activity analysis (
tw_get_activity_analysis): reconciled timestamps, labeled summary and capability states, per-channel processed/new-processed/FIT fallback, deterministic elapsed-second merging, and paginationSlim activity payloads:
tw_get_activityandtw_get_activity_workout_zone_detectiondrop multi-MB per-second arrays by default (opt back in withinclude=[...])Public Streamable HTTP mode with static-bearer or OAuth auth (one-click claude.ai connector), single-tenant to the operator's Tyme Wear account
Quick Start
1. Install
git clone https://github.com/tkelkermans/tymewear-mcp.git
cd tymewear-mcp
python -m venv .venv
source .venv/bin/activate
pip install -e .2. Authenticate
tymewear-mcp authEnter your Tyme Wear email and password. Credentials are stored securely in your system keyring with an encrypted file fallback.
3. Configure Claude Desktop
Add to your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json on macOS):
{
"mcpServers": {
"tymewear": {
"command": "/path/to/tymewear-mcp/.venv/bin/tymewear-mcp",
"args": ["serve"]
}
}
}Or run tymewear-mcp config to generate the snippet with the correct path.
4. Restart Claude Desktop
The Tyme Wear tools will appear in Claude's tool list.
CLI Commands
Command | Description |
| Store Tyme Wear credentials (interactive or |
| Check if stored credentials are valid |
| Remove stored credentials |
| Output Claude Desktop config snippet |
| Start the MCP server (stdio transport) |
| Start the public Streamable HTTP server |
Public Internet Deployment
serve-public exposes a Streamable HTTP MCP endpoint for hosted deployments. It is authenticated and stateless; it is not an anonymous public API.
Public Server
Set the public URL and one or more MCP bearer tokens through environment variables. Each bearer token must be at least 32 characters; use a generated random secret.
export TYMEWEAR_PUBLIC_URL="https://mcp.example.com/mcp"
export TYMEWEAR_PUBLIC_BEARER_TOKENS="replace-with-a-long-random-secret-of-32-plus-chars"
tymewear-mcp serve-public \
--host 0.0.0.0 \
--port 8000 \
--public-url "$TYMEWEAR_PUBLIC_URL"The MCP endpoint is /mcp by default. /healthz returns only {"status":"ok"} and does not expose customer data.
Container
The included Dockerfile runs the public server as a non-root user. Inject secrets at runtime:
docker build -t tymewear-mcp-public .
docker run --rm -p 8000:8000 \
-e TYMEWEAR_PUBLIC_URL="https://mcp.example.com/mcp" \
-e TYMEWEAR_PUBLIC_BEARER_TOKENS="replace-with-a-long-random-secret-of-32-plus-chars" \
tymewear-mcp-publicVercel
The repo also includes a root Vercel Python ASGI entrypoint (main.py). Vercel's Python framework routes requests to the ASGI app directly, so vercel.json must not rewrite /mcp, /healthz, or /.well-known/* to an internal function path. Link the local directory to the intended Vercel project, connect that project to the Git repository, then configure at least TYMEWEAR_PUBLIC_BEARER_TOKENS for both Production and Preview. The entrypoint fails closed if the public bearer token env is absent. Use a separate Preview bearer token to limit credential scope. TYMEWEAR_PUBLIC_URL is recommended for production aliases, but preview deployments can derive it from Vercel's deployment URL.
PRODUCTION_TOKEN_FILE=/path/to/generated-production-bearer-token
PREVIEW_TOKEN_FILE=/path/to/generated-preview-bearer-token
chmod 600 "$PRODUCTION_TOKEN_FILE" "$PREVIEW_TOKEN_FILE"
vercel link
vercel git connect
vercel env add TYMEWEAR_PUBLIC_BEARER_TOKENS production --sensitive --yes < "$PRODUCTION_TOKEN_FILE"
vercel env add TYMEWEAR_PUBLIC_BEARER_TOKENS preview --sensitive --yes < "$PREVIEW_TOKEN_FILE"Keep token files readable only by their owner; the deployment wrapper rejects token files that are accessible by group or others. Use vercel env update TYMEWEAR_PUBLIC_BEARER_TOKENS production --sensitive --yes < "$PRODUCTION_TOKEN_FILE" when rotating an existing token. Do not pass bearer tokens through vercel deploy --env, shell echo, or other command arguments that can end up in shell history or process listings.
The same path is wrapped by scripts/deploy_public_vercel.sh for manual recovery deployments. It requires an existing Vercel project link, uploads the token from a file, deploys production, and runs scripts/verify_public_endpoint.py against the deployed MCP URL:
scripts/deploy_public_vercel.sh --token-file "$PRODUCTION_TOKEN_FILE"Set PYTHON=/path/to/python when the verifier should run with a specific interpreter, such as the repo virtual environment.
Automated deploy (CI/CD)
.github/workflows/deploy.yml runs the locked test suite (ruff + mypy + pytest) on every push and pull request. It does not hold Vercel credentials or deploy the application.
The linked Vercel Git integration creates preview deployments for feature branches and pull requests, then creates the production deployment when main is updated. No VERCEL_TOKEN GitHub Actions secret is required. Runtime variables such as TYMEWEAR_PUBLIC_BEARER_TOKENS remain managed in the Vercel project and persist across Git deployments.
claude.ai connector (OAuth)
The static bearer token works for header-capable clients (Claude Code: claude mcp add --transport http <url> --header "Authorization: Bearer <token>"). claude.ai's connector instead authenticates via OAuth, so to add the MCP there the server runs as an OAuth protected resource: it validates JWT access tokens from a managed provider (e.g. WorkOS AuthKit or Stytch) and enforces an email allowlist. It stays single-tenant — every authorized user reads the operator's data via server-side credentials.
Set these (sensitive) Vercel env vars to enable it:
Var | Purpose |
| Provider issuer URL (enables OAuth protected-resource mode) |
| Optional expected token |
| Optional explicit JWKS URL (else discovered from the issuer) |
| Optional scopes to advertise to the client (default |
| Comma-separated allowlist of emails permitted to connect |
| The operator's Tyme Wear credentials used for all upstream calls |
Provider setup (WorkOS AuthKit example): create an app, enable Google/email login, enable Dynamic Client Registration so claude.ai can self-register, and copy the issuer URL into TYMEWEAR_PUBLIC_ISSUER_URL. Then add the connector in claude.ai → it discovers the provider via the server's /.well-known/oauth-protected-resource, registers, and runs the hosted login; only allow-listed emails are admitted.
The static TYMEWEAR_PUBLIC_BEARER_TOKENS path keeps working alongside OAuth (dual-mode). Without TYMEWEAR_PUBLIC_ISSUER_URL, OAuth is off and only the bearer path is active.
Post-Deploy Verification
After deployment, verify the public endpoint without printing secrets:
TYMEWEAR_PUBLIC_URL="https://mcp.example.com/mcp" \
python scripts/verify_public_endpoint.py --bearer-token-file "$TOKEN_FILE"The verifier checks /healthz, unauthenticated /mcp rejection, authenticated MCP initialize, authenticated tools/list, required compact-analysis/profile tools, and public security/no-cache headers.
It also confirms public deployments do not advertise raw activity reads or disk exports, and that default deployments do not advertise mutation tools.
Public Client Authentication
Public mode is single-tenant: it authenticates upstream to Tyme Wear with the operator's own credentials from TYMEWEAR_EMAIL / TYMEWEAR_PASSWORD (server-side env), so every authorized caller reads the operator's data. Clients only need to prove they are allowed to connect — there is no per-request Tyme Wear token.
Header-capable clients (e.g. Claude Code) send the static gateway bearer token:
Authorization: Bearer <TYMEWEAR_PUBLIC_BEARER_TOKENS entry>When OAuth is enabled (TYMEWEAR_PUBLIC_ISSUER_URL set), clients such as the claude.ai connector instead send a provider-issued JWT obtained through the hosted login; the server validates it (signature via JWKS, issuer, optional audience) and admits only allow-listed emails. Both paths work at once (dual-mode).
Earlier revisions required a per-request
X-Tymewear-Token. Single-tenant mode removed it — credentials are now server-side.
Public Data Policy
In public mode:
Access is gated by the static bearer token and/or the OAuth email allowlist; only allow-listed identities connect.
The operator's Tyme Wear credentials live only in server-side env (keep them in a secret manager). They are read straight from the environment — public mode does not touch the local keyring or encrypted credential file (those write under
$HOME, which is read-only on serverless).Every tool result and stable public error passes through one non-mutating recursive privacy projection before JSON serialization. It removes non-JSON values, non-finite numbers, emails, user/account/profile UUIDs, device identifiers/serials, tokens, signed/callback/download URLs, S3 or temporary paths, heavy raw fields, and coordinates outside the explicit analysis location contract.
tw_get_activity_analysisis the public compact raw-sample interface. It keeps labeled availability, capability, channel, provenance, summary, and paginated sample data.include_locationmust be the literal booleantrue; onlyraw_samples.data[*].position_lat/position_longand their matching channel metadata may then survive. Home, generic, and unrelated coordinates are always removed.Public responses include
Cache-Control: no-store,Pragma: no-cache,X-Robots-Tag: noindex, nofollow, HSTS for HTTPS public URLs, and baseline security headers to reduce accidental intermediary caching, indexing, and browser-side leakage of customer data.Profile/activity mutation tools are hidden and return
PUBLIC_MUTATIONS_DISABLEDby default. Only enable them with--allow-mutationsorTYMEWEAR_PUBLIC_ALLOW_MUTATIONS=truefor trusted deployments.CSV, FIT, and strap-file export tools return
PUBLIC_EXPORTS_DISABLEDbecause the local implementation writes files to disk.tw_get_processed_data,tw_get_new_processed_data,tw_get_activity_logs, andtw_get_activity_strap_filesare hidden and returnPUBLIC_RAW_DATA_DISABLED, even when mutations are enabled. Local stdio mode retains these tools. Compact workout-zone detection remains public.
Public tool errors are stable and do not echo upstream exception text:
Code | Meaning |
| The request does not match the published strict tool schema |
| The requested tool is not registered |
| Server-side Tyme Wear credentials are unavailable |
| A public client, handler, close, or projection operation failed |
| A raw/log/file-read tool is unavailable in public mode |
| A disk-writing export is unavailable in public mode |
| A mutation is unavailable without explicit trusted-deployment opt-in |
Production Hardening
Terminate TLS at the edge and set
TYMEWEAR_PUBLIC_URLto the canonical HTTPS MCP URL.Keep
TYMEWEAR_PUBLIC_URLpath aligned with the mounted MCP path (/mcpby default). Public mode rejects URL query strings, fragments, and route/path mismatches at startup.Inject
TYMEWEAR_PUBLIC_BEARER_TOKENSfrom a secret manager, not shell history or source control. Tokens shorter than 32 characters are rejected at startup.Keep public deployments read-only unless you have a specific trusted-client requirement for profile/activity mutations.
Prefer an OAuth or identity-aware proxy in front of
serve-publicfor untrusted clients; rotate static bearer tokens regularly.When using an OAuth-capable proxy or authorization server, set
TYMEWEAR_PUBLIC_ISSUER_URLor--issuer-urlso MCP clients can discover protected-resource metadata.Public HTTP request bodies are capped at 1 MiB by default, including chunked/streamed bodies. Override with
TYMEWEAR_PUBLIC_MAX_BODY_BYTESor--max-body-bytesonly if a trusted deployment needs larger JSON-RPC requests.Keep authorization header, request body, and response body logging disabled at the reverse proxy and application platform.
Restrict outbound network egress to Tyme Wear API hosts where your platform supports it.
Set explicit
--allowed-hostand--allowed-originvalues when the public URL host is not the only valid host/origin. Public mode rejects untrustedHostheaders across all routes, refuses wildcard*host/origin configuration, requires allowed origins to be exact http(s) origins without paths, and requires non-localhost origins to use HTTPS.
Available Tools
Auth & Profile
Tool | Description |
| Check authentication status and token validity |
| Get athlete profile: weight, height, VE targets (VT1, BP, VT2, VO2max) per sport, subscription status, external accounts |
| Update profile fields (weight, height, units) |
Activities
Tool | Description |
| List activities with cursor pagination and website filters for sports, activity types, search, user ID, and pro team |
| Full activity detail: duration, thresholds, zones, TSS, firmware, third-party links. Heavy arrays are summarised by default. Local stdio callers may use |
| Compact read-only analysis with reconciled timestamps, summary, breakpoints, explicit capabilities, per-channel source/unit/coverage/provenance, and samples merged before pagination. |
| Compact per-activity report: VT1/VT2/Endurance VE+HR+confidence, measured power-at-threshold, detected breakpoint times, per-zone time/calories, quality flags, a truncated-test flag, and VE targets — works for tests and rides |
| Algorithm processing status for an activity |
| Pin/unpin an activity for threshold detection |
| Get currently pinned activity |
| Delete an activity (irreversible) |
Breathing Data
Tool | Description |
| Local-only per-second breathing time-series with summary, window, and full modes; public mode uses |
| Local-only new-format processed data when available; public mode uses |
Activity Files & Detection
Tool | Description |
| Get local-only read-only activity logs/events |
| Get local-only strap-file metadata when available |
| Export raw strap files when available |
| Workout-zone detection (per-zone time/calories, VT1/VT2 VE+HR+confidence, estimated power). Point clouds are summarised by default. Local stdio callers may use |
Training Plans & Workouts
Tool | Description |
| Get current training plan |
| Get training-plan data for a date |
| Get training-plan data for a week |
| Get training-plan history |
| Get training-plan configuration |
| Get training-plan preview |
| Get workout recommendation |
Integrations & Account
Tool | Description |
| List integrations |
| Get integration details |
| Get integration health/status |
| Get subscription status |
| Get available subscription plans |
| Get resting/max physiology values |
Thresholds & Zones
Tool | Description |
| Current VE targets (VT1, BP, VT2, VO2max) per sport |
| Join an external power series ( |
| Zone time distribution across activities |
| Tag a ventilatory threshold (vt1, vt2, bp, vo2max) from a specific activity |
| Tag a new-model zone value (fatmax, vt1, vt2, vo2max) from a specific activity |
Max Values
Tool | Description |
| List pending max value detection notifications |
| Accept or dismiss a detected max value |
Exports
Tool | Description |
| Export activity as CSV |
| Export full CSV with all data channels |
| Export activity as FIT file |
Example Prompts
Once configured, you can ask Claude things like:
"Show me my last 10 bike activities"
"Analyze the breathing data from my ride yesterday — what were my average VE and time in each zone?"
"What are my current VT1 and VT2 thresholds for cycling?"
"Pull the insights for my last threshold test — what's my power at VT2 and did it reach VO2max?"
"Export my last activity as a FIT file"
"Compare my VE targets between running and cycling"
"Show my current training plan and workout recommendation"
"Check whether my latest ride has strap files, logs, or workout-zone detection results"
"List my connected integrations and subscription status"
Security
Credentials stored in system keyring (preferred) or AES-256-GCM encrypted file with PBKDF2 key derivation (600K iterations, machine-specific salt)
Tokens and credentials are never returned in MCP tool results (sanitized before reaching Claude)
Environment variable auth available for CI/containers:
TYMEWEAR_EMAIL+TYMEWEAR_PASSWORDFile permissions set to 600 (owner read/write only) on encrypted credential files
Public mode requires bearer or OAuth authentication and is single-tenant: upstream Tyme Wear auth uses server-side
TYMEWEAR_EMAIL/TYMEWEAR_PASSWORDenv (never the local keyring or encrypted file, which are read-only on serverless), every result is privacy-projected, and raw/file/export tools are disabled
Architecture
tymewear-mcp/
├── src/tymewear_mcp/
│ ├── cli.py # CLI entry point
│ ├── server.py # MCP server + 40 tool registrations
│ ├── public.py # Public Streamable HTTP server + bearer/OAuth auth
│ ├── auth/ # Credential storage (keyring → encrypted → env) + OIDC verifier (oidc.py)
│ ├── client/ # Async HTTP client + Pydantic models
│ └── tools/ # Tool implementations (incl. threshold_analysis.py, _slimming.py)
└── tests/ # 340 testsTech stack: Python 3.10+, MCP SDK, httpx, Pydantic, keyring, cryptography, PyJWT
Development
pip install -e ".[dev]"
pytest tests/ -v # Run tests
ruff check src tests # Lint
mypy src/ # Type checkLicense
MIT
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
- AlicenseBqualityAmaintenanceConnects Claude Desktop to Garmin Connect, enabling natural language queries of fitness activity data, health metrics, sleep analysis, workout management, and device information with 94 available tools.1101MIT
- AlicenseAqualityDmaintenanceConnects Claude to your Strava account for analyzing training, predicting race times, and generating periodized training plans via natural language.1361ISC
- FlicenseNot gradedqualityBmaintenanceConnects Claude to Garmin Connect data for personalized running coaching, including morning readiness checks, post-run analysis, weekly reviews, and goal tracking.
- AlicenseAqualityDmaintenanceConnects Strava training data to Claude, enabling personalized coaching through analysis of training load, workout planning, gear maintenance, and power metrics.10MIT
Related MCP Connectors
Garmin data in Claude & ChatGPT via the Garmin Health API. OAuth sign-in, no password sharing.
Garmin data in Claude: 135 tools — activities, sleep, HRV, training, workouts. Free, open source.
WHOOP recovery, strain, sleep and workouts in Claude via official WHOOP OAuth. Free, open source.
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/tkelkermans/tymewear-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server