Garmin Agent Tools
Provides direct Garmin Connect tools for reading selected live activity, readiness, and device fields, and for previewing, creating, scheduling, and requesting device synchronization of a fixed 20-minute running connectivity test workout.
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.
Garmin Agent Tools
Direct Garmin Connect tools for a personal agent's own Linux cloud computer or a user's Mac/Linux computer. No Intervals.icu, no Coach Loop dependency, no model API key, no publisher-hosted health database.
這是什麼
An experimental CLI and optional stdio MCP server. It reads selected live activity/readiness/device fields and can preview, create, schedule and request device synchronization of one fixed 20-minute running connectivity test. This is a transport spike, not a training coach or a general workout editor.
Related MCP server: Garmin Claude MCP
給誰用
Developers and athletes testing whether their personal agent can operate Garmin directly on its own computer. Having an agent cloud computer does not prove that package installation, Garmin authentication, private login, persistence or device delivery works there. Each is an independent acceptance gate.
Install
Python 3.11+ on Linux/macOS. Review the code and use an isolated environment. Install from a specific reviewed commit rather than silently updating an agent tool from a moving branch.
git clone https://github.com/atomchung/garmin-agent-tools.git
cd garmin-agent-tools
python3 -m venv .venv
.venv/bin/python -m pip install --require-hashes -r requirements.lock
PYTHONPATH=src .venv/bin/python -m garmin_agent_tools.cli doctor
PYTHONPATH=src .venv/bin/python -m unittest discover -s tests -vThe default private state is ~/.local/share/garmin-agent-tools, outside the checkout. Override with GARMIN_AGENT_HOME pointing to an owner-only directory. This spike supports one Garmin account per state directory. Account and region are bound to each preview.
Login privately, on the computer that will run the tool
An execution permission is not a Garmin login. Never type a password, verification code or token into agent chat, a shell command, a public issue, or a repository file.
For an interactive private terminal:
PYTHONPATH=src .venv/bin/python -m garmin_agent_tools.cli loginFor an agent cloud computer whose browser can access its own loopback network:
PYTHONPATH=src .venv/bin/python -m garmin_agent_tools.cli login-webThis prints a short-lived http://127.0.0.1:8765/<random-path> link. Open it only in the browser on that same agent computer. The athlete must use the platform's private browser sign-in/takeover flow to enter Garmin credentials. The local helper forwards them to Garmin over HTTPS, supports a separate MFA form, and persists only returned tokens. It never returns credential values to the agent. The helper binds only to loopback, checks Host/Origin and a form nonce, disables request logs and caching, and exits after ten minutes. Do not expose it using a public tunnel or proxy. Do not fill its fields through ordinary agent-visible tool arguments. If the platform cannot give the athlete private access to this form, stop: there is no fallback to posting secrets in chat.
Browser-only Garmin sign-in does not authenticate this CLI. The helper is an explicit credential flow on the agent machine, not a browser-cookie extraction tool. If Garmin challenges or refuses the cloud environment, preserve that limitation; do not disable TLS verification or route through the athlete's computer to claim a cloud-only pass.
Use --region china only for separate China-region testing; overseas success does not prove China support.
Read and test
Use an explicit date in the athlete's timezone:
PYTHONPATH=src .venv/bin/python -m garmin_agent_tools.cli snapshot --date 2026-01-01
PYTHONPATH=src .venv/bin/python -m garmin_agent_tools.cli test-preview --tag my-test --date 2026-01-01 --device-id 123456The preview names the account binding, date, device and fixed warmup/run/cooldown durations of 300/600/300 seconds with open targets. Show those effects to the athlete. Omit --date for an unscheduled template and --device-id to omit device delivery. Neither omission invents a calendar date or a default watch. After explicit approval of that exact preview:
PYTHONPATH=src .venv/bin/python -m garmin_agent_tools.cli test-apply --approve PREVIEW_SHA256
PYTHONPATH=src .venv/bin/python -m garmin_agent_tools.cli workout WORKOUT_ID
PYTHONPATH=src .venv/bin/python -m garmin_agent_tools.cli calendar --date 2026-01-01 --workout-id WORKOUT_IDThe same approval resumes verified effects without duplicating workouts or calendar entries. An uncertain upload or schedule is fenced for manual inspection, not blindly retried. HTTP return from a device-message request does not prove the watch received or rendered a workout. The athlete verifies the named workout and 5/10/5 minute steps on the watch. No workout deletion or modification of unrelated items is exposed.
Optional MCP
The lock file includes the MCP SDK. Start the same bounded tools over stdio:
PYTHONPATH=src .venv/bin/python -m garmin_agent_tools.cli mcpA host may instead call the CLI. Login is intentionally absent from the model-facing MCP tool surface; its inputs never include credentials. Do not assume the host's MCP annotations replace explicit approval or an application-enforced boundary.
Portable agent entry
The GitHub package includes a portable Skill
and host-neutral browser contract.
Use python -m garmin_agent_tools.browser skill-path after installation. The Skill
can be loaded by a host that supports local skills; this is not a registered
plugin or marketplace submission. Browser-only agents still need process/file
access to run local MCP. Another host can submit selected observations with
record-read rather than using Dot's CUA API. Its method is explicitly labelled
parent_browser_tool; request/URL/freshness checks do not independently attest it.
python -m garmin_agent_tools.browser training-guidance returns a reviewed
snapshot of the shared training judgment, source revision and digest. It touches
no athlete state. This package does not collect full coaching context or store a
current PlanState; loading a reference is not full Coach Loop integration.
Compatibility evidence: Dot's CUA route has two real selected-workout reads on the preceding source version. Generic parent submissions have separate anonymous SDK acceptance checks; Grok/Muse/other hosts have not had live acceptance. Do not infer compatibility from a product name or claim the new version has provider acceptance until the corresponding live check exists.
Garmin browser-session expiry has no guaranteed TTL in this package. Check actual login state on each use, preserve journals, and request the platform's normal private sign-in only when required. Do not extract cookies or schedule artificial keepalive visits. ChatGPT Health support does not establish Dot Health access.
Browser-backed local MCP
This alternative uses the agent platform's already authorized Garmin browser
session. It does not use the Garmin API client's tokens. The same local MCP server
exposes read_workout, preview_test and apply_test, with actual server
instructions and a browser_workflow prompt. read_snapshot remains an API-backend
capability; the browser backend does not provide activity or training-status data.
Use the environment installed from the existing hash lock above. The browser server also exposes its stdio transport for developers:
PYTHONPATH=src .venv/bin/python -m garmin_agent_tools.cli mcp --backend browserThat command serves the protocol only. A direct host needs its own parent queue dispatcher; without it, browser reads time out. It is not an installed native plugin. The supported Dot workflow below uses the SDK caller, which announces each request to the parent CUA agent.
For a parent agent with command execution and supported CUA, use the SDK caller:
PYTHONPATH=src .venv/bin/python -m garmin_agent_tools.browser inspect
PYTHONPATH=src .venv/bin/python -m garmin_agent_tools.browser read-workout --workout-id WORKOUT_IDEvery invocation retrieves and prints the actual instructions, complete tool catalogue and prompt match before a tool call. This is an agent-mediated workflow: the SDK and MCP server do not launch, attach to or control a browser. A platform's native plugin registration is not supplied or proved by these commands.
The default private browser state is ~/.local/share/garmin-agent-tools-browser,
separate from API state and source. A trusted operator may set
GARMIN_AGENT_BROWSER_HOME to another absolute private directory outside the
checkout. An existing write runtime can be preserved with
GARMIN_WRITEPREP_RUNTIME; the SDK explicitly binds that same path into its server.
Do not copy credentials or provider state into a checkout, use a different empty
runtime to retry a possible write, or assume process continuity proves VM retention.
Read and delivery contracts
Use the packaged Dot CUA adapter for the supplied worker, or the parent-browser entry for another supported browser tool. The exact test delivery contract owns proposal, confirmation, account consistency, execution and readback. These files ship with the Skill in the installed wheel.
The pre-package prototype had two real browser-backed MCP reads in one Dot environment. This package has separate anonymous protocol/integration checks; those do not prove a live packaged deployment, Garmin creation/calendar delivery, native registration, a complete training coach, or watch synchronization.
Data and security boundary
The browser backend retains selected workout observations and delivery journals in its separate private state. They are not raw HTML or a complete health archive; the agent/model platform can also retain returned outputs.
Raw activities, GPS and FIT files stay with Garmin. Selected read summaries are returned on demand, not saved as a health archive. The agent/model platform can retain outputs under its own policy.
Tokens stay in
GARMIN_AGENT_SESSIONor a private.envin the state directory (0700 directory, 0600 file). File permissions are not encryption. An agent-platform administrator or another process with equivalent user access may still reach them. Do not call this platform-blind encryption or a Garmin-scoped OAuth integration.Passwords and MFA codes are transient login inputs. They are not stored, printed or sent to the publisher. Credentials are never copied from a different device during cloud acceptance.
Local previews/journals/receipts store account binding and workout/schedule/device identifiers to prevent duplicate effects. Keep them out of Git and public diagnostic reports.
Removing local tokens is not server-side revocation of copied credentials. Account/security actions at Garmin are separate.
The library uses Garmin's unofficial internal service interfaces. MIT licensing does not establish Garmin authorization for commercial distribution or guarantee continued service access.
The pin starts from the version used for the initial direct-device spike. Change it for a demonstrated compatibility/security need and re-run live acceptance; do not silently upgrade to a moving upstream branch.
Acceptance and honest reporting
Record runtime/install, private login, live reads, upload readback, calendar readback, device request, athlete watch verification and second-process continuity separately. Run a second process for snapshot/calendar checks; that proves process continuity, not indefinite VM retention. Do not publish raw test outputs, account identifiers, credentials or health readings as GitHub evidence.
PYTHONPATH=src python3 -m unittest discover -s tests -vTests use anonymous fake data and do not contact Garmin. They are not proof of a particular agent cloud deployment.
License and attribution
MIT for this wrapper. python-garminconnect is a separately licensed MIT dependency by Ron Klinkien and contributors; see THIRD_PARTY_NOTICES.md. Garmin is a trademark of Garmin Ltd. This independent project is not affiliated with Garmin, OpenAI, Meta, Cursor or xAI.
This server cannot be deployed
Maintenance
Related MCP Connectors
AI coach for Garmin: builds training plans and structured workouts, synced straight to your watch.
Running coach: your AI reads your runs and recovery, and writes sessions to your watch or phone.
Your endurance training data in your AI assistant: activities, recovery, plan, workout edits.
Garmin data in Claude & ChatGPT via the Garmin Health API. OAuth sign-in, no password sharing.
Related MCP Servers
- AlicenseAqualityBmaintenanceDaash connects Garmin Connect to ChatGPT and Claude. Your assistant reads your runs, splits, sleep, HRV, Body Battery and recovery, and writes structured workouts and whole training plans to your Garmin calendar, so they're on your watch at the next sync. Free, hosted, open source. Works on free Claude.264MIT
- AlicenseNot gradedqualityCmaintenanceLets Claude read a runner's recent activities and wellness signals — sleep, HRV, resting heart rate — and then design, schedule, edit, or delete structured workouts. Planned sessions are written to an intervals.icu calendar that syncs through Garmin Connect onto the user's watch, without exposing Garmin credentials.MIT
- AlicenseNot gradedqualityBmaintenanceEnables an AI agent to read Garmin sleep, readiness and activity data, build an athlete profile, check proposed sessions against code-enforced limits and real calendar availability, and then push approved structured workouts to a Garmin watch. Plans are proposed and stored under a plan ID, so only explicitly approved sessions are ever written.MIT
- AlicenseNot gradedqualityAmaintenanceConnects a user's own Garmin data to compatible AI clients through Garmin's official Personal API, running locally over stdio with read-only access and no Garmin username or password.1MIT