Garmin Training MCP
Leia seus dados de treino do Garmin e escreva treinos estruturados de volta no seu relógio. Corridas, parciais, sono e frequência cardíaca entram; sessões de corrida e força agendadas no dispositivo. Roda localmente via stdio, ou hospedado com OAuth 2.1.
Documentação
garmin-mcp
Pergunte ao Claude sobre seus dados do Garmin e peça para ele enviar a sessão para o seu relógio.
Um servidor MCP local que conecta o Claude Desktop à sua própria conta do Garmin Connect. Ele lê suas corridas, divisões de pace, zonas de frequência cardíaca e métricas diárias de saúde — e, ao contrário das integrações somente leitura do Garmin que existem por aí, ele pode criar um treino estruturado e agendá-lo, para que a resposta a "o que devo correr na quinta-feira?" chegue ao seu pulso em vez de ficar em um registro de chat.
Tudo roda como um subprocesso local na sua máquina. Sem hospedagem, sem servidor guardando suas credenciais, sem exposição à rede.
You: My last three runs are all at the same effort. Give me something harder
for Thursday, based on what my recent paces actually support.
Claude: [reads your activities and splits, then proposes]
Thursday Threshold (running, about 52m 55s)
warmup: 15m
5 x
interval: 1.00 km @ 4:00/km-4:10/km
recovery: 1m 30s
cooldown: 10m
Create this and put it on Thursday?
Instalação
macOS 10.15 (Catalina) ou mais recente, com o Claude Desktop já instalado:
curl -fsSL https://raw.githubusercontent.com/Bartolome69/garmin-mcp/main/scripts/bootstrap.sh | bash
Isso baixa o código para ~/garmin-mcp, instala um Python moderno via
uv, faz login no Garmin e registra o
servidor com o Claude Desktop. É o único comando que a maioria das pessoas precisa. Leia-o
primeiro se preferir —
scripts/bootstrap.sh é curto.
Depois, saia completamente do Claude Desktop (⌘Q) e reabra-o.
Instalação manual, ou no Linux
git clone https://github.com/Bartolome69/garmin-mcp.git
cd garmin-mcp
./scripts/setup.sh # venv + dependencies
./scripts/login.sh # sign in to Garmin once, caches the session
Depois, registre-o no seu cliente MCP. Para o Claude Desktop no macOS,
o ./scripts/install-claude-desktop.sh faz isso (com o aplicativo fechado). Para qualquer
outra coisa, copie o .mcp.json.example, preencha os caminhos absolutos e aponte seu cliente
para python -m garmin_mcp via stdio.
Ferramentas
| Ferramenta | O que retorna |
|---|---|
get_activities(limit, start_date, end_date) | Corridas, pedaladas e treinos: distância, duração, pace por km e milha, FC média e máxima, zonas de FC, cadência, efeito do treino, além de dinâmica de corrida e potência quando o relógio registra |
get_activity_details(activity_id) | Uma atividade em detalhes: distância por divisão, pace, FC, cadência, dinâmica de corrida e potência, além do tempo completo em cada zona de FC |
get_daily_summary(date) | Passos, distância, calorias, FC de repouso/mínima/máxima, body battery, estresse, minutos de intensidade |
get_sleep_data(date) | Estágios do sono com durações e porcentagens, pontuação do sono, VFC noturno, FC de repouso |
list_workouts(limit) | Treinos estruturados salvos na conta |
create_workout(name, steps, sport, description) | Cria um treino estruturado e o adiciona ao Garmin Connect |
schedule_workout(workout_id, date) | Coloca um treino em uma data, que é o que sincroniza com o relógio |
unschedule_workout(date, schedule_id) | Remove um treino de um dia. Reversível — o treino em si é mantido |
delete_workout(workout_id, confirm) | Exclui um treino. A primeira chamada apenas lê o nome dele; a remoção exige uma segunda chamada citando esse nome |
get_plan_chart(weeks_back, weeks_forward) | Desenha o plano como imagem para a conversa: as sessões de cada dia ao lado do que foi planejado |
get_progress(weeks) | Quais sessões planejadas foram realmente concluídas, semana a semana. Conta uma sessão se ela ocorreu dentro de um dia antes ou depois da data agendada |
get_profile() | VO2 máx. e recordes pessoais — 5k, 10k, meia, maratona e demais |
get_connection_status() | Se o servidor está conectado, qual conta (mascarada) e o estado do cache de tokens |
Datas aceitam YYYY-MM-DD, today, yesterday, tomorrow ou um deslocamento com sinal
como -7 ou +3.
Escrevendo treinos
create_workout recebe uma lista ordenada de etapas. Cada uma tem um type (warmup,
interval, recovery, rest, cooldown ou repeat), exatamente um de
duration_seconds ou distance_meters, e um alvo opcional — ou pace
(minutos por km, como "4:05" ou um intervalo ["4:00","4:10"]) ou hr ([150, 165]).
Aquecimento de 15 minutos, 5×1km a 4:05 com recuperações de 90 segundos, desaquecimento de 10 minutos:
[{"type": "warmup", "duration_seconds": 900},
{"type": "repeat", "times": 5, "steps": [
{"type": "interval", "distance_meters": 1000, "pace": "4:05"},
{"type": "recovery", "duration_seconds": 90}]},
{"type": "cooldown", "duration_seconds": 600}]
Um pace único é ampliado em 5 s/km para cada lado, porque o Garmin alerta em um intervalo e um alvo exato apita constantemente. Grupos de repetição não se aninham. Criar um treino apenas o salva — agende-o em uma data para que ele chegue ao relógio.
O que ele pode e não pode fazer na sua conta
A leitura é irrestrita. A escrita é limitada à biblioteca de treinos: criar um treino, agendá-lo, desagendá-lo, excluí-lo. Nada atinge seu histórico de treinos — nenhuma ferramenta exclui ou edita uma atividade registrada, então uma corrida que você fez não pode ser perdida aqui, por mais errada que uma chamada de ferramenta seja.
delete_workout é protegido em vez de confiado a um docstring. A primeira chamada
nunca exclui: ela lê o treino de volta e retorna o nome dele, e apenas uma segunda
chamada passando esse nome como confirm o remove. Um modelo não pode destruir um treino
que não tenha nomeado primeiro.
Sua senha é lida do ambiente, enviada diretamente ao Garmin e nunca
gravada em disco. Apenas o token de sessão emitido pelo Garmin é armazenado em cache, em
~/.garmin-mcp/tokens.json, escrito 0600 dentro de um diretório 0700. Nenhuma ferramenta
retorna a senha ou o token — get_connection_status informa um endereço
mascarado e a idade e as permissões do cache, nada mais. Os logs vão para o stderr, então
eles nunca corrompem o fluxo MCP no stdout.
Após o primeiro login, o servidor roda com o token em cache. Defina
GARMIN_EMAIL e GARMIN_PASSWORD no ambiente do servidor se quiser
que ele reautentique sem supervisão quando esse token eventualmente expirar; deixe
GARMIN_PASSWORD de fora e você executará scripts/login.sh novamente.
Se não funcionar
Comece por aqui — ele percorre do interpretador até uma chamada real ao Garmin e identifica o primeiro elo quebrado:
./scripts/doctor.sh
"O Garmin está limitando logins deste endereço IP (429)" — a falha mais comum, e não é sua senha: o Garmin bloqueia por endereço de rede antes de verificar as credenciais. Wi-Fi de escritório, redes universitárias e VPNs são os mais afetados. Faça login uma vez usando o hotspot do celular; depois disso, a sessão em cache é usada.
"O Garmin está pedindo um código de múltiplos fatores" — o servidor não pode solicitar
via stdio, então execute ./scripts/login.sh em um terminal uma vez. Ele lida com o código e
armazena a sessão em cache.
O Claude não consegue ver as ferramentas — o Claude Desktop carrega a configuração na inicialização e
grava a própria cópia ao fechar, então uma alteração feita enquanto ele está em execução
desaparece. Saia completamente, execute ./scripts/install-claude-desktop.sh, reabra.
A instalação falha mencionando Rust, OpenSSL ou um compilador — o macOS é antigo demais.
O limite mínimo é 10.15 (Catalina), definido pelo próprio interpretador Python:
o build Intel do uv é compilado com minos 10.15 e não será iniciado abaixo disso, então
nenhum ajuste de pacotes ajuda. Os instaladores passam --only-binary :all: para que
isso falhe rapidamente em vez de se tornar uma compilação de fonte condenada, e tentam novamente com
constraints-legacy.txt caso um pacote simplesmente tenha perdido um wheel.
Sem dados de sono — o relógio não foi usado durante a noite ou não sincronizou. Sono, VFC e body battery noturnos só existem se você dormir com ele.
Habilidades de treino
skills/ contém metodologia de treino que se baseia nas ferramentas — como
ler os dados e o que prescrever a partir deles. A primeira é uma habilidade de meia
maratona no estilo de Pete Pfitzinger.
Desenvolvimento
.venv/bin/python tests/smoke_test.py
Aciona o servidor via stdio real, como um cliente MCP faria, contra uma conta Garmin simulada — sem rede, sem credenciais. Cobre o formato de resposta de cada ferramenta, construção de treinos, entrada inválida e o caminho de inicialização sem credenciais.
.venv/bin/python -m garmin_mcp.check
O mesmo caminho de código contra sua conta real, imprimindo o que retorna. Útil para confirmar uma configuração de ponta a ponta.
Outros clientes MCP e ChatGPT
Nada aqui é específico do Claude: ele fala MCP via stdio, então qualquer cliente que
inicie um servidor local o executará — Claude Code, Cursor, VS Code, Zed,
Windsurf. Copie o .mcp.json.example, preencha os caminhos absolutos e aponte o cliente para
python -m garmin_mcp.
O ChatGPT não pode executar isso. Os conectores dele usam uma URL HTTPS pública via SSE, porque o ChatGPT executa nos servidores da OpenAI e não pode iniciar um processo na sua máquina — não há opção de servidor local para habilitar. Servir isso ao ChatGPT significaria hospedá-lo publicamente e guardar as credenciais Garmin dos usuários, que é exatamente o que este projeto evita.
Ressalvas
Não é afiliado ao Garmin. Ele usa a mesma API privada que o site do Garmin Connect
usa, via
garminconnect, porque
o Garmin não publica uma API OAuth para consumidores. Essa API pode mudar sem aviso e
levar isso junto.
Licença MIT. Construído com Claude Code.