Futureweb Intervals MCP

Servidor MCP Intervals.icu auto-hospedado para ChatGPT e Claude: análise de treino (planejado vs executado, carga, intensidade, recuperação, alimentação, resistência), todos os campos personalizados e streams, dados Garmin. Somente leitura por padrão, OAuth integrado, GPL-3.0.

Documentação

Futureweb Intervals MCP icon

Futureweb Intervals MCP

Servidor MCP avançado para Intervals.icu, para ChatGPT, Claude e qualquer cliente MCP: métricas enriquecidas com dados Garmin, todos os campos personalizados e streams, insights de recuperação e análise de desempenho de resistência.

CI License: GPL-3.0 Python 3.12+ Status: public beta Garmin Intervals Bridge

Um servidor Model Context Protocol que permite que assistentes de IA leiam e analisem seus dados de treino do Intervals.icu da mesma forma que um treinador faria: atividades com todos os campos personalizados e streams, intervalos, bem-estar em relação a linhas de base pessoais, limiares e zonas, treinos planejados versus executados, subidas, medidores de potência duplos, melhores esforços, eficiência e resistência à fadiga, nutrição e peso, resumos de treino e o calendário. Ele roda onde você quiser, fala apenas com a API do Intervals.icu e não expõe nada que grave a menos que você habilite.

Continuação de mvilanova/intervals-mcp-server. O projeto original não é mais desenvolvido ativamente (último commit em 2 de agosto de 2026, 29 pull requests deixados em aberto). Este fork mantido pela comunidade dá continuidade: os pull requests úteis em aberto foram revisados e mesclados com crédito aos autores, os bugs corrigidos e o servidor reconstruído em torno de análise de treino, dados Garmin e acesso remoto seguro. Não é afiliado ao Intervals.icu ou à Garmin.

Projeto complementar: o Garmin Intervals Bridge restaura as métricas que a Garmin remove dos arquivos que envia ao Intervals.icu (stamina, efeito de treino, tempo de recuperação, VO₂max, dinâmica de corrida, detalhes de sono e FCV …). Este MCP foi feito para ler tudo isso, mas funciona igualmente bem sem o bridge.

Conteúdo

Destaques

  • Todos os itens personalizados, resolvidos dinamicamente. Campos personalizados de atividades, campos de intervalos, streams e campos de bem-estar são lidos das suas próprias definições e reportados com nome, código, valor e unidades. Nada específico de dispositivo é codificado; null, NaN, zero e ausente permanecem distintos, campos que não pertencem ao esporte são mantidos separados e as cargas do dispositivo nunca são misturadas com a carga do Intervals.icu.
  • Streams em resolução total. Qualquer stream como resumo, CSV ou JSON, fatiado por índice ou tempo, reduzido e paginado, além de estatísticas por intervalo de qualquer stream (por exemplo, a queda de stamina de cada intervalo).
  • Análise de treino em vez de despejos brutos. Relatório de atividade em uma única chamada, planejado versus executado por etapa (também para eventos excluídos e pedais estendidos além do plano), subidas e descidas, verificação do segundo medidor de potência, melhores esforços, intervalos semelhantes, treinos repetidos ao longo do tempo, eficiência potência-frequência cardíaca, resistência à fadiga, carga de treino (razão agudo:crônico, monotonia, tensão), distribuição de intensidade em três zonas com índice de polarização, resistência aeróbica, projeção de carga sobre o plano, resumo de recuperação com linhas de base de 42 dias, tendências e correlações de bem-estar, tendências de nutrição e peso, resumos semanais e mensais. Estatísticas com seus tamanhos de amostra; a interpretação fica com o treinador.
  • Eficiente em tokens. detail_level (compact, standard, full) e output_format="json" nas ferramentas pesadas, nove prompts de treino prontos e dois recursos MCP.
  • Acesso remoto seguro. Servidor OAuth 2.1 integrado com login "Continuar com Intervals.icu", uma página de consentimento com permissões por conexão, documentos de metadados do cliente com private_key_jwt (ChatGPT), PKCE e RFC 9207. HTTP Streamable (/mcp) e SSE em um único processo.
  • Somente leitura por padrão. As ferramentas são agrupadas em classes de permissão (read, write, destructive, admin) aplicadas no servidor; apenas read está ativa a menos que você habilite mais.
  • Testado. Mais de 400 testes com dados sintéticos, ruff, mypy, CodeQL, GitHub Actions fixado, testes de smoke de build e Docker em cada pull request.

Funciona com o Garmin Intervals Bridge

Garmin device ──► Garmin Connect ──► official sync ──► Intervals.icu activity (filtered FIT)
                        │                                     ▲
                        └── Garmin Intervals Bridge ──────────┘  restores custom fields, streams, wellness
                                                              │
                                              Futureweb Intervals MCP (this project)
                                                              │
                                                 ChatGPT / Claude / any MCP client

O Garmin Intervals Bridge grava as métricas que a Garmin filtra nos campos personalizados de atividade, streams personalizados e campos de bem-estar que você definiu no Intervals.icu. O MCP lê essas definições em tempo de execução, então cada valor restaurado aparece nas ferramentas automaticamente:

Restaurado pelo bridgeOnde o MCP mostra
Efeito de treino, EPOC, carga de treino Garmin, tempo de recuperação, VO₂max, condição de desempenho, stamina início/fim, perda de suor, temperaturasget_activity_details, get_activity_report, get_training_summary, get_training_load (cargas do dispositivo separadas da carga do Intervals.icu), get_fueling_analysis (perda de suor por hora), get_activity_data_audit (quais campos ainda têm um placeholder zero ou nenhum valor)
Stamina e stamina potencial, segundo medidor de potência, velocidade ajustada por inclinação, seleção de marcha, streams de dinâmica de corridaget_activity_streams, get_activity_intervals, analyze_workout_execution, analyze_climbs, compare_power_streams
SpO₂ noturno, respiração, FC durante o sono, detalhes de FCV, Body Battery, estágios de sono e estresse, prontidão, nutriçãoget_wellness_data, get_recovery_snapshot, get_wellness_trends, get_nutrition_summary

O MCP nunca contata a Garmin; o bridge é opcional e outros dispositivos ou ferramentas de sincronização que preenchem itens personalizados recebem o mesmo tratamento. Exemplos práticos e notas sobre como ler as métricas do dispositivo corretamente: docs/GARMIN_BRIDGE.md.

Ferramentas

67 ferramentas; 52 delas apenas leem. Ferramentas de escrita são marcadas com ✎ (write), ✖ (destructive) ou ⚙ (admin) e ficam ocultas a menos que sua classe esteja habilitada. A maioria das ferramentas aceita output_format="json" e detail_level (compact primeiro). As ferramentas nunca recebem chave de API: as credenciais vêm apenas do ambiente do servidor.

O catálogo é mantido pequeno para o cliente de IA: descrições curtas que dizem quando usar uma ferramenta, uma descrição e (onde os valores são fixos) um enum para cada parâmetro, e resultados em texto sem uma cópia estruturada duplicada. Detalhes de métodos e o formato de treino ficam nos recursos MCP (intervals://methods/<topic>, intervals://workout-syntax) e em get_guide(topic) para clientes que só chamam ferramentas. tools/list tem cerca de 22,7 mil tokens em MCP_PERMISSIONS=read,write (era 42,0 mil; cl100k); veja Conjuntos de ferramentas para um conjunto menor.

Análise de atividade

FerramentaO que faz
get_activity_reportAnálise completa em uma chamada: visão geral com abastecimento (carboidratos usados/ingeridos por hora, perda de suor, energia), clima (temperatura, sensação térmica, vento, parcela de vento contra/a favor), e saldo de W′ (depleção máxima, tempo abaixo de 75/50/25 % do W′), plano vs execução ou intervalos, verificação do segundo medidor de potência, subidas, notas de qualidade de dados (fonte, horários de upload e análise, paradas de gravação, placeholders zero); include_route_history compara atividades anteriores na mesma rota do Intervals.icu (tempo, potência, W/kg, FC, clima, stamina); detail_level compacto (números principais, uma linha de contexto e principais descobertas, cerca de 2-2,5 mil caracteres), padrão ou completo
get_activity_data_auditProveniência e qualidade de dados de uma atividade: fonte e arquivo (sincronização Garmin, exportação Garmin ou upload via bridge, stub do Strava), horários de upload e análise, duplicatas filtradas, paradas de gravação e lacunas, voltas FIT vs intervalos e edições manuais, identidade do dispositivo e sensores, streams usuais para o esporte mas ausentes, cobertura por stream, campos personalizados com valor / placeholder zero / nenhum e o que o Garmin Intervals Bridge poderia preencher; sem uma atividade, a cobertura de dados por esporte de um período
analyze_workout_executionPlanejado vs executado por etapa (duração, aderência ao alvo, tempo na faixa, resposta da FC, queda, deriva Pw:FC com o sinal de desacoplamento do Intervals.icu, stamina). Uma etapa pode abranger qualquer número de voltas; com voltas automáticas do dispositivo, os limites de etapas dentro das voltas são colocados na mudança de intensidade (os toques de volta são mantidos), etapas sem volta própria são encontradas entre suas vizinhas, e uma ressalva com alignment_confidence diz até onde os resultados por etapa podem ser confiáveis. Alvos abertos (zona superior) são limites inferiores, etapas de distância são comparadas por distância. As etapas são limitadas à duração planejada, intervalos mais longos são divididos para a análise, e pedalar além do plano é reportado separadamente com sua carga e esforços extras. Tolerâncias para deslocamento de início, pausas e comprimento de etapa; planned_workout_doc para eventos excluídos; eventos correspondentes sugeridos somente leitura
analyze_climbsSubidas, descidas e pausas com potência, NP, FC, VAM e streams personalizados por segmento; inclinação suavizada em uma janela de distância (inclinação bruta opcional), confiança de inclinação alta/média/baixa por segmento (sem inclinação abaixo da distância horizontal mínima, bruta incluída), pausas reais vs movimento lento, perfis de esporte para ciclismo, corrida e caminhada, sinalizadores de qualidade de dados
compare_power_streamsComparação alinhada por amostra de dois medidores de potência: deslocamento, faixas de potência, janelas estáveis, deriva, atraso; sem activity_id (intervalo de datas ou activity_ids) cada pedalada com um segundo stream de potência é comparada individualmente e resumida por bicicleta, indoor/outdoor, medidor principal e segunda fonte de potência com n, mediana, DP entre pedaladas e faixa (geral, por faixa de potência, janelas estáveis), deriva, atraso, outliers e pedaladas longe da mediana; nunca um fator de correção
get_best_effortsMelhores esforços de uma atividade por durações ou distâncias, com suas janelas de tempo decorrido (índice final exclusivo); janelas que cruzam uma pausa de gravação são sinalizadas
get_activity_histogramDistribuição de tempo de potência, frequência cardíaca, ritmo ou GAP

Atividades e streams

FerramentaO que faz
get_activitiesLista com filtros de esporte, equipamento e medidor de potência, ordenação, paginação, saída compacta ou JSON; sem start_date os 30 dias antes de end_date (ou hoje)
get_activity_detailsResumo, limiares usados (FTP, eFTP, LTHR, zonas), dispositivo e medidor de potência, dinâmica de corrida, todos os campos personalizados com unidades, abastecimento, clima, saldo de W′ e fonte/frescor
get_activity_intervalsIntervalos e grupos, campos personalizados de intervalos, estatísticas por intervalo de qualquer stream, opcionalmente o tipo de etapa planejada ao lado do tipo do Intervals.icu
list_activity_streams, get_activity_streamsDescubra e busque qualquer stream: resumo, CSV ou JSON, fatiamento, redução de amostragem, paginação (2000 amostras por página por padrão)
get_activity_messages, add_activity_message ✎, update_activity ✎Notas e comentários, PSE, sensação, nome, descrição (dry_run mostra a solicitação exata)

Desempenho ao longo do tempo

FerramentaO que faz
compare_best_effortsMelhores esforços em todas as atividades (IDs, intervalo de datas, esporte, equipamento) lado a lado; IDs são deduplicados e limitados ao teto antes de qualquer solicitação
find_similar_intervalsAtividades com intervalos comparáveis, a partir de uma atividade de referência ou de um comprimento e intensidade determinados; mesma família de esporte por padrão, classificadas por comparabilidade, com contexto de equipamento e medidor de potência; com uma referência, os 365 dias anteriores a ela por padrão (janela exibida, start_date para qualquer intervalo)
compare_workoutsTreinos repetidos ao longo do tempo, comparando apenas intervalos de trabalho comparáveis (atividade de referência, família de esporte, comprimento, intensidade, repetições, faixa de FTP); a atividade de referência é sempre buscada e sempre o padrão, com uma busca por nome nos 365 dias anteriores listados; picos mantidos separados, médias ponderadas no tempo, tendências de potência, FC, cadência e PSE da atividade inteira, sinalizações de equipamento e medidor de potência
get_power_hr_efficiencyWatts por batimento cardíaco por faixa de potência e bicicleta ao longo do tempo, com tamanhos mínimos de amostra e filtros para equipamento, indoor/outdoor e posição do intervalo
get_fatigue_resistanceMelhor potência fresco vs. após os limites de kJ do atleta; sem limites configurados, explica a configuração e sugere valores em vez de mostrar pseudo-resultados
get_long_ride_fatigue_profileFC, W/bpm, cadência e resistência Garmin em potência correspondente em segmentos estáveis antes vs. depois dos limites de trabalho (padrão 750 / 1.500 kJ, ou kJ/kg), para passeios determinados ou os passeios longos de um período; trabalho anterior em cada limite e subida (kJ, kJ/kg, kJ e tempo acima do FTP, esforços acima do FTP), subidas após N horas com resistência no início e no fim, mediana e intervalo entre passeios, método declarado, amostras pequenas sinalizadas
get_submax_test_trendsTestes de fadiga submáximos detectados pelo Intervals.icu (#SFT) com filtro de validade (tolerância alvo, CV, ignorados, detectados dentro de um treino regular, pedalada dura antes, recuperação de FC opcional) e motivos para cada teste excluído; FC no final, fator de eficiência, HRRc e tendência do curso de FC por família de esporte e tipo de teste (potência e ritmo nunca combinados) e semana ISO apenas sobre os testes válidos
get_training_loadCarga aguda e crônica, razão aguda:crônica, monotonia e tensão de Foster (dias de descanso como 0), semanas tipo deload, por esporte com o esporte principal, tabela de semana ISO, CTL/ATL/forma/rampa; cargas de dispositivo mantidas separadas; faixas de referência com fontes, sem veredito
get_intensity_distributionDistribuição de três zonas a partir de zonas de potência, FC ou ritmo (mapeamento por contagem de zonas; tempos de zona GAP onde o Intervals.icu os usa), índice de polarização segundo Treff et al. 2019, classe, sessões e dias difíceis, deriva entre as metades, por esporte e semana, cobertura de zonas, uma ressalva quando os totais misturam zonas de potência e FC
get_durabilityDesacoplamento aeróbico de sessões longas e estáveis após um filtro de qualidade (sessões excluídas por motivo), mediana e contagem acima de 5 %, recente vs. janela com banda de estabilidade, tendência do fator de eficiência; parcela qualificada por esporte, menos de 8 sessões sinalizadas, indoor/outdoor misto, bicicletas ou medidores de potência apontados; filtro de calor no sensor do dispositivo ou na temperatura do clima / sensação térmica da atividade (temperature_source), lista de sessões com ambas as temperaturas
get_load_projectionCTL, ATL e forma projetados sobre os treinos planejados (modelo de 42/7 dias), cargas planejadas ausentes relatadas, dias de corrida, projeção própria do Intervals.icu e uma verificação de modelo para comparação; diz de forma destacada quando nada está planejado. Simulação de cenário "e se" (scenario): sessões ou modelos semanais que não estão no calendário (carga dada ou estimada como horas x IF² x 100), adicionadas ao plano ou substituindo-o, comparadas com o plano do calendário; forma em um dia alvo ou no próximo RACE_A e uma busca em grade para a carga dos últimos dias que atinge uma faixa de forma determinada; estatísticas do plano por semana (rampa, monotonia, sessão mais longa, dias de descanso) com faixas comumente citadas e fontes. Nada é escrito
get_athlete_power_curves, get_hr_curves, get_pace_curvesCurvas de temporada e intervalo de datas
get_training_summaryTotais por semana, mês, esporte ou equipamento com a carga do Intervals.icu (potência, senão FC, senão ritmo por atividade) e as somas sobrepostas por método, tempo em zonas de potência (sweet spot à parte) e zonas de FC, CTL/ATL no final de cada semana ou mês; campos personalizados agregados por unidades e significado (somas apenas onde fazem sentido, caso contrário média, mediana, intervalo ou mudança); um detail_level explícito também seleciona as partes JSON (sem ele, o JSON é completo)
get_weekly_summary, get_plan_complianceRevisão semanal e visão geral planejado vs. realizado

Bem-estar e recuperação

FerramentaO que faz
get_recovery_snapshotHoje e os dias anteriores, linhas de base de 42 dias, carga recente e sessões planejadas em uma única chamada; nomeia os campos usuais de bem-estar que o registro de hoje ainda não tem (ainda não disponível, não normal)
get_coach_contextPrimeira chamada recomendada para uma análise semanal: visão geral em cerca de 2-2,5 mil caracteres com carga, condicionamento, distribuição de intensidade (divisão por esporte quando as bases de zona se misturam), VFC / FC de repouso / sono com médias de 7 dias contra os 42 dias anteriores (z contra a variação semana a semana dos 90 dias anteriores), durabilidade, principais sessões, o plano dos próximos 7 dias, campos de bem-estar ainda não disponíveis hoje e uma linha de método (janelas, ACWR acoplado, threshold_as, regra de sessão difícil); um detail_level explícito também seleciona as partes JSON (sem ele, o JSON é completo)
get_wellness_trendsMédias móveis, linhas de base, outliers, mudanças semana a semana, correlações, eFTP por esporte; período solicitado, lookback e janela de linha de base declarados separadamente, amostras pequenas sinalizadas
get_nutrition_summaryIngestão, gasto do dispositivo, balanço energético em dias registrados, tendência de peso, carga de treino por dia
get_fueling_analysisAbastecimento de uma atividade ou das sessões longas de um período: carboidratos usados (estimativa do Intervals.icu) e ingeridos por hora em movimento, parcela ingerida do usado, energia, ingestão de líquidos, sódio e perda de suor a partir de campos personalizados encontrados por unidades e nome (zeros de arquivos de dispositivo tratados como placeholders); por família de esporte, e dentro dela por duração e intensidade, com tamanhos de amostra, cobertura de registro e correlações de Spearman a partir de 8 sessões; sem metas
get_wellness_data, update_wellness ✎Registros diários (include_all_fields adiciona todo campo personalizado de bem-estar; sem start_date, os 30 dias antes de end_date ou hoje), com uma linha nomeando os campos usuais que o registro de hoje ainda não tem (valores de noite/manhã, métricas diárias como VO2max ou pontuação de resistência, e totais do dia à parte); pontuações subjetivas (dry_run mostra a solicitação exata)

Atleta, equipamento, calendário e treinos

FerramentaO que faz
get_athlete_profile, get_sport_settings, get_training_zonesPerfil, limiares por esporte, zonas com faixas absolutas
update_sport_settings ⚙Alteração validada de FTP, LTHR, FC máxima ou ritmo de limiar (ritmo com sua unidade, ex.: 4:30/km); dry_run mostra a solicitação com os valores atuais
get_gear_list, get_gear_detailsBicicletas, tênis e componentes com quilometragem e lembretes de manutenção
get_events, get_event_by_id, get_training_planCalendário com o documento completo do treino; fases do plano, metas semanais, corridas
validate_workout, preview_workoutVerificar e renderizar um documento de treino antes de escrevê-lo
add_or_update_event ✎, add_or_update_note ✎, add_events_bulk ⚙, delete_event ✖, delete_events_by_date_range ✖Mudanças no calendário: treinos são validados antes de serem escritos, dry_run retorna a solicitação exata, um novo evento é recusado quando aquele dia já tem o mesmo (allow_duplicate), a resposta relê o que o Intervals.icu armazenou e analisou (etapas analisadas vs. enviadas, avisos de análise); exclusões nomeiam o que foi excluído; a exclusão por intervalo mostra prévia por padrão
get_workout_library, get_library_workout, create_library_workout ✎, add_event_from_library ✎, delete_library_workout ✖Biblioteca de treinos (execução seca, verificação de duplicidade ao agendar, releitura, exclusões nomeiam o que foi excluído)

Itens personalizados e servidor

FerramentaO que faz
get_custom_items, get_custom_item_by_id, create_custom_item ⚙, update_custom_item ⚙, delete_custom_item ✖Definições de campo personalizado, stream e gráfico (create_custom_item e update_custom_item com dry_run; atualização: o conteúdo após a mesclagem)
get_server_statusVersão, permissões habilitadas, conjunto de ferramentas, ferramentas ocultas, transporte e modo de login, verificação de API (também --doctor)
get_guideGuia de uso, sintaxe de treino e guias de método (os recursos abaixo) para clientes que só chamam ferramentas

Prompts: recovery_check, workout_deep_dive, weekly_training_review, training_load_review, performance_progression, long_ride_climbing_analysis, nutrition_weight_trend, power_meter_comparison, workout_planning_validation, race_week (afunilamento e forma no dia da corrida, plano de abastecimento a partir do histórico, clima, logística), fueling_review, plan_health_check (projeção de carga e cenário "e se" das semanas planejadas) e coach_handoff (resumo compacto para outro treinador ou sessão). Recursos: intervals://guide (como usar as ferramentas), intervals://workout-syntax (o formato de treino estruturado), intervals://methods/<topic> (como uma análise funciona: dados de atividade, execução, subidas, medidores de potência, carga, intensidade, durabilidade, resumo, comparações, fadiga, bem-estar, abastecimento), intervals://custom-items (suas definições de itens personalizados). O servidor também envia instruções curtas na resposta do MCP initialize (comece com get_coach_context ou get_activity_report, compacto primeiro, valores ausentes não são normais, escritas apenas sob solicitação após uma prévia), e seu ícone e site em serverInfo. Os transportes HTTP servem o ícone sem autenticação em /favicon.ico, /favicon.png, /icon.png, /icon.svg e /apple-touch-icon.png (também usado na página de login).

Conjuntos de ferramentas

MCP_TOOLSET=full (padrão) registra toda ferramenta das classes de permissão habilitadas. MCP_TOOLSET=core registra um conjunto selecionado de 23 ferramentas para clientes com um orçamento pequeno de ferramentas (cerca de 9,4 mil tokens em MCP_PERMISSIONS=read,write); MCP_PERMISSIONS ainda se aplica dentro do conjunto:

PropósitoFerramentas principais
Orientaçãoget_server_status, get_guide
Revisão semanal, carga e planoget_coach_context, get_training_summary, get_load_projection, get_events, get_event_by_id, get_training_plan
Uma atividadeget_activities, get_activity_report, get_activity_details, get_activity_intervals, get_best_efforts, get_fueling_analysis
Recuperaçãoget_recovery_snapshot, get_wellness_data, get_wellness_trends
Planejamentoget_sport_settings, validate_workout, preview_workout
Escritas (classe write)add_or_update_event ✎, update_wellness ✎, update_activity ✎

get_server_status e --doctor mostram o conjunto de ferramentas ativo e quantas ferramentas ele deixa de fora; descrições de ferramentas, prompts e guias marcam as ferramentas fora do conjunto "(conjunto completo de ferramentas)". Após uma atualização do servidor que muda ferramentas ou conjuntos de ferramentas, atualize a lista de ferramentas no cliente (ChatGPT: a atualização do conector nas configurações do aplicativo; Claude: reconecte o conector).

Convenções de saída: horários de início são mostrados no horário local com o nome do fuso quando o Intervals.icu armazena um, caso contrário com o deslocamento UTC derivado do início local e UTC, mais UTC; cadência de corrida, caminhada e trilha em passos por minuto (spm, 2 x o valor por perna que o Intervals.icu armazena, que é mostrado como armazenado), cadência de bicicleta em rpm; temperaturas em °C (um campo personalizado de temperatura sem unidades assume a unidade que seus campos irmãos de temperatura concordam); valores ausentes são n/a, nunca 0.

Início rápido

Requisitos: uma chave de API do Intervals.icu (Configurações → Configurações de Desenvolvedor) e seu ID de atleta (i123456); para o pacote Python uv (ou Python 3.12+ e pip), para a imagem de contêiner Docker. Cada instalação executa seu próprio servidor com suas próprias credenciais; não há serviço hospedado. Tagged releases são publicados como o pacote PyPI futureweb-intervals-mcp, as imagens de contêiner ghcr.io/futureweb/intervals-mcp-server e futurewebat/futureweb-intervals-mcp (Docker Hub), um pacote Claude Desktop (.mcpb) no GitHub release e uma entrada no registro oficial do MCP.

Beta: 1.0.0b1 é um pré-lançamento. Nomeie a versão (uvx futureweb-intervals-mcp@1.0.0b1, pip install futureweb-intervals-mcp==1.0.0b1) ou permita pré-lançamentos (uvx --prerelease allow futureweb-intervals-mcp, pip install --pre futureweb-intervals-mcp). uv e pip escolhem um pré-lançamento por conta própria apenas enquanto não existe uma versão final; a partir de 1.0.0, uvx futureweb-intervals-mcp simples obtém a versão final mais recente.

Do PyPI (uvx ou pip)

export API_KEY=your-api-key ATHLETE_ID=i123456        # or put both into a .env file
uvx futureweb-intervals-mcp@1.0.0b1 --doctor          # checks configuration and API access
uvx futureweb-intervals-mcp@1.0.0b1                   # starts the server on stdio

Com pip, em um ambiente virtual:

pip install futureweb-intervals-mcp==1.0.0b1
futureweb-intervals-mcp --doctor

Do código-fonte

git clone https://github.com/futureweb/intervals-mcp-server.git
cd intervals-mcp-server
uv sync --locked
cp .env.example .env                       # set API_KEY and ATHLETE_ID
uv run futureweb-intervals-mcp --doctor    # checks configuration and API access
uv run futureweb-intervals-mcp             # starts the server on stdio

Sem clonar:

uvx --from git+https://github.com/futureweb/intervals-mcp-server futureweb-intervals-mcp --version

Docker

Lançamentos com tag publicam a mesma imagem multi-arquitetura (amd64, arm64) no GitHub Container Registry e no Docker Hub (latest apenas para versões finais, tags beta como 1.0.0b1 explicitamente):

docker run --rm -i -e API_KEY=... -e ATHLETE_ID=i123456 ghcr.io/futureweb/intervals-mcp-server:1.0.0b1
docker run --rm -i -e API_KEY=... -e ATHLETE_ID=i123456 futurewebat/futureweb-intervals-mcp:1.0.0b1

Com MCP_AUTH=oauth, monte um volume em /data (a imagem mantém OAUTH_STATE_FILE lá), por exemplo, -v intervals-mcp:/data; caso contrário, todo contêiner recriado desconecta todos os clientes.

Pacote Claude Desktop (.mcpb)

Todo GitHub release carrega futureweb-intervals-mcp-<version>.mcpb. Abra-o com o Claude Desktop (clique duplo, ou Settings → Extensions → Install Extension…) e insira a chave da API (armazenada como segredo), o ID do atleta e, opcionalmente, as permissões (read por padrão) e o conjunto de ferramentas. O pacote contém os fontes e o arquivo de bloqueio; o Claude Desktop o inicia com uv (uv run --frozen), que instala as dependências bloqueadas no primeiro início. Ele precisa de uma versão do Claude Desktop que suporte o manifesto MCPB 0.4 (uv tipo de servidor).

Registro MCP

Os lançamentos estão listados no registro oficial do MCP como io.github.futureweb/intervals-mcp-server, com o pacote PyPI e a imagem GHCR e as variáveis de ambiente de que precisam. Clientes que leem o registro podem instalar o servidor a partir de lá. A entrada lista apenas pacotes: cada usuário executa uma instância própria com suas próprias credenciais do Intervals.icu.

Conecte um cliente de IA

Claude Desktop e Claude Code (local, stdio)

Além do pacote acima, o Claude Desktop pode iniciar o servidor a partir do PyPI com uvx (adicione a claude_desktop_config.json; o Claude Desktop precisa do caminho completo para uvx se ele não estiver em seu PATH, por exemplo, /Users/you/.local/bin/uvx):

{
  "mcpServers": {
    "intervals-icu": {
      "command": "uvx",
      "args": ["futureweb-intervals-mcp@1.0.0b1"],
      "env": { "API_KEY": "your-api-key", "ATHLETE_ID": "i123456", "MCP_PERMISSIONS": "read" }
    }
  }
}

Com Docker em vez disso (os valores vêm de env, -e NAME os passa para o contêiner):

{
  "mcpServers": {
    "intervals-icu": {
      "command": "docker",
      "args": ["run", "--rm", "-i", "-e", "API_KEY", "-e", "ATHLETE_ID", "-e", "MCP_PERMISSIONS",
               "ghcr.io/futureweb/intervals-mcp-server:1.0.0b1"],
      "env": { "API_KEY": "your-api-key", "ATHLETE_ID": "i123456", "MCP_PERMISSIONS": "read" }
    }
  }
}

A partir de um checkout do código-fonte:

{
  "mcpServers": {
    "intervals-icu": {
      "command": "uv",
      "args": ["--directory", "/path/to/intervals-mcp-server", "run", "futureweb-intervals-mcp"],
      "env": { "API_KEY": "your-api-key", "ATHLETE_ID": "i123456", "MCP_PERMISSIONS": "read" }
    }
  }
}

Claude Code: claude mcp add intervals-icu -e API_KEY=your-api-key -e ATHLETE_ID=i123456 -- uvx futureweb-intervals-mcp@1.0.0b1, ou a partir de um checkout claude mcp add intervals-icu -- uv --directory /path/to/intervals-mcp-server run futureweb-intervals-mcp.

ChatGPT, Claude.ai e outros clientes remotos (OAuth)

Clientes remotos precisam de um endpoint HTTPS. Execute o servidor atrás de um proxy reverso TLS com OAuth:

MCP_TRANSPORT=http+sse FASTMCP_HOST=127.0.0.1 FASTMCP_PORT=8001 \
MCP_AUTH=oauth MCP_PUBLIC_URL=https://mcp.example.com \
INTERVALS_OAUTH_CLIENT_ID=... INTERVALS_OAUTH_CLIENT_SECRET=... \
MCP_PERMISSIONS=read,write \
uv run futureweb-intervals-mcp
  1. Escolha o login: sem configurações adicionais, você entra com sua chave da API do Intervals.icu (opcionalmente mais um código autenticador, OAUTH_TOTP_SECRET). Para Continuar com Intervals.icu, crie um aplicativo OAuth em https://intervals.icu/oauth/apply com a URL de redirecionamento https://mcp.example.com/oauth/intervals/callback; uma senha de servidor é a terceira opção.
  2. No ChatGPT (modo desenvolvedor), adicione uma conexão com a URL https://mcp.example.com/mcp e autenticação OAuth; deixe o ID do cliente e o segredo vazios. Claude.ai: Adicionar conector personalizado com a mesma URL.
  3. Na página de consentimento, escolha as permissões para esta conexão e entre. Com Intervals.icu, apenas os atletas em OAUTH_ALLOWED_ATHLETES (padrão ATHLETE_ID) podem entrar.
  4. Após atualizações do servidor, use Atualizar na conexão do ChatGPT para recarregar as ferramentas.

Tudo sobre o servidor OAuth, o proxy reverso (exemplos Apache e nginx) e o modelo de segurança: docs/REMOTE_ACCESS.md. Clientes sem OAuth podem usar um caminho de endpoint secreto em vez disso (FASTMCP_SSE_PATH=/mcp-<random>/sse).

Compartilhando o servidor com amigos

Por padrão, o servidor é de usuário único (MCP_TENANCY=single): toda chamada de ferramenta usa o API_KEY e ATHLETE_ID do servidor. Quem tiver permissão para conectar vê seus dados, então neste modo o servidor se recusa a iniciar quando OAUTH_ALLOWED_ATHLETES nomeia qualquer pessoa além de você (suas outras contas do Intervals.icu podem ser listadas em OAUTH_OWNER_ACCOUNTS).

Para permitir que alguns amigos usem a mesma implantação com seus próprios dados do Intervals.icu, mude para o modo opcional multiusuário:

MCP_TENANCY=single (padrão)MCP_TENANCY=multi
Acesso a dadoso API_KEY do servidor para cada conexãocada conexão com sua própria credencial
Amigos entram com– (eles veriam seus dados)"Continuar com Intervals.icu" (a única forma para não proprietários)
Token do Intervals.icu delesusado para a verificação de identidade, nunca armazenadoarmazenado criptografado (AES-256-GCM) por conexão
Suas próprias conexõesChave da APIChave da API, somente depois que você entrou (Intervals.icu como ATHLETE_ID, ou senha / chave da API mais código autenticador)
Argumentos athlete_idqualquer atleta que a chave possa lerapenas o atleta da própria conexão (0 = próprio); qualquer outra coisa é recusada antes de uma solicitação
Caches, orçamentos de solicitaçãoumpor conexão / por atleta, parte justa do limite do aplicativo

Configuração (detalhes em docs/REMOTE_ACCESS.md):

# 1. While still in single-user mode: confirm once that your existing connections are yours
futureweb-intervals-mcp grants list
futureweb-intervals-mcp grants adopt-legacy --owner
# 2. A key for the stored tokens (mode 0600, owned by the service user; back it up separately)
futureweb-intervals-mcp token-key --file /etc/intervals-mcp/token.key
# 3. Settings, then restart and check
MCP_TENANCY=multi
OAUTH_TOKEN_KEY_FILE=/etc/intervals-mcp/token.key
OAUTH_LOGIN=intervals                     # you sign in with Intervals.icu as ATHLETE_ID (or add OAUTH_TOTP_SECRET for a password)
OAUTH_ALLOWED_ATHLETES=i123456,i234567,i345678   # you plus your friends
futureweb-intervals-mcp --doctor

Execute os comandos grants e token-key como o usuário de serviço com o ambiente do servidor (OAUTH_STATE_FILE, ATHLETE_ID), por exemplo, docker exec -u <uid> no contêiner. Como root, eles se recusam a alterar um diretório de estado que pertence a outro usuário (--allow-root substitui; eles nunca seguem links lá). Conexões do modo de usuário único que não foram adotadas são recusadas no modo multiusuário, nunca tratadas como suas. Se você reverter para um lançamento mais antigo após este, ele descarta os atletas registrados novamente: conexões criadas ou atualizadas nesse meio tempo precisam de grants adopt-legacy --owner mais uma vez antes da próxima troca (até então, elas são recusadas).

Seus amigos adicionam a mesma URL de conector no ChatGPT ou Claude, escolhem as permissões na página de consentimento e aprovam o aplicativo Intervals.icu. As permissões do Intervals.icu solicitadas correspondem às classes que eles escolhem (read pede acesso de leitura a ACTIVITY, WELLNESS, CALENDAR, LIBRARY e SETTINGS; write e superiores adicionam os escopos de escrita que as ferramentas precisam). Comentários de atividades precisam da permissão CHATS do Intervals.icu, que também cobre chats privados: ela nunca é solicitada a menos que você defina INTERVALS_OAUTH_OFFER_CHATS=true e o atleta marque "Comentários de atividades" na página de consentimento; caso contrário, as duas ferramentas de comentário dizem que a permissão está faltando.

O que é armazenado. Por conexão, o arquivo de estado mantém o ID do atleta, o cliente MCP, as datas de criação e último uso, os escopos concedidos do Intervals.icu e o token de acesso do Intervals.icu do atleta, criptografado com a chave de OAUTH_TOKEN_KEY / OAUTH_TOKEN_KEY_FILE (sem a chave, o token não pode ser lido; mantenha a chave separada dos backups do arquivo de estado). No máximo OAUTH_MAX_GRANTS_PER_ATHLETE conexões (padrão 5) são mantidas por atleta; as suas próprias nunca são removidas. Dados não são armazenados em cache no disco; caches em memória expiram em minutos e são separados por conexão.

Privacidade. Dados de bem-estar, como FCV, sono, frequência cardíaca em repouso ou peso, são dados de saúde (na UE, uma categoria especial sob o Art. 9 do GDPR), e como operador você é responsável por eles. Convide apenas pessoas que concordem explicitamente, diga a elas em uma nota curta o que é armazenado (acima), quem pode ver ( você: o arquivo de estado e os logs do servidor com IDs de atletas, nomes de ferramentas, caminhos de solicitação e erros, nunca tokens ou corpos de dados), por quanto tempo os logs são mantidos (por exemplo, journalctl --vacuum-time=14d) e como sair. Mantenha a implantação atualizada. Se a chave ou o arquivo de estado pode ter vazado, coloque uma nova chave primeiro em OAUTH_TOKEN_KEY e peça aos seus amigos para revogar o aplicativo no Intervals.icu.

Exclusão. O token armazenado de uma conexão é excluído quando o cliente MCP revoga a conexão ao desconectar (/revoke; nem todo cliente faz isso), após OAUTH_REFRESH_TOKEN_TTL sem uso (padrão 30 dias; OAUTH_TOKEN_RETENTION_DAYS o torna mais curto), ou com o comando grants. Para remover um amigo completamente:

  1. futureweb-intervals-mcp grants remove <athlete id> (um servidor em execução descarta as conexões na próxima solicitação);
  2. remova o atleta de OAUTH_ALLOWED_ATHLETES e reinicie;
  3. o amigo revoga o aplicativo nas configurações do Intervals.icu (o servidor não pode revogar um token sem desconectar todas as conexões do atleta; até então, o token excluído ainda seria válido no Intervals.icu);
  4. opcionalmente, limpe linhas de log antigas (journalctl --vacuum-time=...).

Limites. Todos os atletas compartilham os limites de solicitação do único aplicativo OAuth do Intervals.icu: cada atleta tem um orçamento diário suave (MCP_ATHLETE_DAILY_REQUESTS, padrão 1000), todos juntos um orçamento de 15 minutos (MCP_APP_REQUESTS_PER_15MIN, padrão 2000) do qual um atleta pode usar no máximo MCP_ATHLETE_SHARE_PERCENT (padrão 25; 0 ainda permite uma solicitação por janela, 100 significa sem limite por atleta) e os outros deixam MCP_OWNER_RESERVED_PERCENT (padrão 20; 100 bloqueia todos os atletas, exceto você) para você; tentativas contam. O limite por chamada se aplica adicionalmente. get_server_status mostra o modo e o atleta da própria conexão de chamada, escopos e orçamento, nunca outros usuários. Voltar para single descarta as conexões e tokens dos outros atletas na próxima escrita; suas próprias conexões continuam funcionando em ambos os modos.

Configuração

Variáveis de ambiente; um arquivo .env no diretório de trabalho é carregado automaticamente (.env.example).

VariávelPadrãoSignificado
API_KEY–Chave da API do Intervals.icu (obrigatória)
ATHLETE_ID–ID do atleta, i123456 ou 123456 (obrigatório)
MCP_PERMISSIONSreadClasses de ferramentas habilitadas, ex.: read,write ou all
MCP_TOOLSETfullfull (todas as ferramentas das classes habilitadas) ou core (conjunto selecionado, veja Conjuntos de ferramentas)
CUSTOM_UNITS_OVERRIDES–Unidades de exibição por código de item personalizado, ex.: Stamina=%,RecoveryTime=h
CUSTOM_AGGREGATE_OVERRIDES–Agregação por código de campo personalizado em resumos (sum, device_load_sum, trend, mean, none), ex.: TrainingLoad=device_load_sum
MCP_TRANSPORTstdiostdio, sse, http ou http+sse (/mcp e /sse em um processo)
FASTMCP_HOST / FASTMCP_PORT127.0.0.1 / 8000Endereço de bind dos transportes HTTP
FASTMCP_SSE_PATH / FASTMCP_MESSAGE_PATH/sse / /messages/Caminhos dos endpoints SSE
FASTMCP_ALLOWED_HOSTS / FASTMCP_ALLOWED_ORIGINShost de MCP_PUBLIC_URLCabeçalhos de Host públicos aceitos atrás de um proxy reverso (proteção contra rebinding de DNS); obrigatório para um endpoint público sem OAuth
MCP_AUTHnoneoauth habilita o servidor OAuth 2.1 integrado
MCP_PUBLIC_URL–URL base pública, obrigatória com MCP_AUTH=oauth
INTERVALS_OAUTH_CLIENT_ID / INTERVALS_OAUTH_CLIENT_SECRET–Aplicativo OAuth do Intervals.icu para "Continuar com Intervals.icu"
OAUTH_LOGINintervals com um aplicativo, senão password se definido, senão apikeyMétodo(s) de login: intervals, password, apikey
OAUTH_TOTP_SECRET–Código do autenticador como segundo fator para login com senha e chave de API (python -m intervals_mcp_server.auth totp-secret)
OAUTH_ALLOWED_ATHLETESATHLETE_IDAtletas autorizados a entrar (* somente com MCP_TENANCY=multi e OAUTH_ALLOW_ANY_ATHLETE=true)
MCP_TENANCYsinglemulti: cada conexão usa sua própria credencial do Intervals.icu (Compartilhando o servidor com amigos)
OAUTH_TOKEN_KEY / OAUTH_TOKEN_KEY_FILE–Modo multiusuário (obrigatório): chave(s) que criptografam os tokens do Intervals.icu armazenados (futureweb-intervals-mcp token-key)
MCP_ATHLETE_DAILY_REQUESTS / MCP_APP_REQUESTS_PER_15MIN1000 / 2000Modo multiusuário: orçamento de solicitações por atleta e dia, e de todos os atletas juntos a cada 15 minutos (0 = desativado)
MCP_ATHLETE_SHARE_PERCENT / MCP_OWNER_RESERVED_PERCENT25 / 20Modo multiusuário: parcela do orçamento de 15 minutos que um atleta pode usar (0 = uma solicitação por janela, não desativado) e a parcela reservada ao proprietário (100 bloqueia todos os outros atletas)
INTERVALS_OAUTH_OFFER_CHATSfalseModo multiusuário: oferecer "Comentários de atividades" (Intervals.icu CHATS, que também cobre chats privados) na página de consentimento
OAUTH_MAX_GRANTS_PER_ATHLETE5Modo multiusuário: conexões mantidas por atleta (as menos usadas recentemente são revogadas; as do proprietário são isentas)
OAUTH_OWNER_ACCOUNTS–Suas outras contas do Intervals.icu; os únicos outros atletas que o modo monousuário aceita na lista de permissões
OAUTH_PASSWORD_HASH / OAUTH_USERNAME– / athleteLogin com senha (hash: python -m intervals_mcp_server.auth hash-password)
OAUTH_STATE_FILE./oauth_state.jsonClientes registrados e resumos de tokens de atualização
INTERVALS_API_BASE_URLhttps://intervals.icu/api/v1URL base da API
ATHLETE_TIMEZONEperfil do atletaFuso horário para "hoje" e intervalos de datas padrão, ex.: Europe/Vienna; server usa o relógio do servidor. Não definido: o timezone do perfil do atleta no Intervals.icu (consultado uma vez por dia)
MCP_TOOL_MAX_REQUESTS / MCP_TOOL_TIMEOUT_S300 / 120Limites de uma chamada de ferramenta (solicitações ao Intervals.icu, segundos); uma ferramenta que os atinge para e informa que seu resultado está incompleto
MCP_MAX_OUTPUT_CHARS100000Maior resultado de ferramenta; texto mais longo é cortado com uma nota sobre como obter o restante, em JSON as maiores listas são cortadas (truncated informa o que foi mantido)

Mais opções de OAuth (listas de permissões de host de cliente e redirecionamento, tempos de vida de token, limite de taxa) estão listadas em docs/REMOTE_ACCESS.md.

Permissões e segurança

ClasseFerramentasHabilitar com
readtudo que apenas lêpadrão
writeadd_or_update_event, add_or_update_note, add_activity_message, update_activity, update_wellness, create_library_workout, add_event_from_libraryMCP_PERMISSIONS=read,write
destructivedelete_event, delete_events_by_date_range, delete_custom_item, delete_library_workoutMCP_PERMISSIONS=read,write,destructive
admincreate_custom_item, update_custom_item, add_events_bulk, update_sport_settingsMCP_PERMISSIONS=all

Ferramentas de uma classe desabilitada não são registradas. Com OAuth, cada conexão adicionalmente recebe apenas as classes concedidas na página de consentimento (intervals:read, intervals:write, …); outras ferramentas ficam ocultas e são recusadas se chamadas.

Ferramentas de escrita que podem substituir valores existentes (add_or_update_event, add_or_update_note, update_activity, update_wellness) carregam a dica MCP destructiveHint: true, então os clientes perguntam antes de executá-las; a classe delas permanece write. Nada é criado, pareado, renomeado ou excluído automaticamente: delete_events_by_date_range primeiro apenas lista o que corresponde; exclui somente com dry_run=false e os ids confirmados dessa lista (confirm_ids), toca apenas nas categorias nomeadas (treinos planejados padrão), no máximo 31 dias, nunca treinos já pareados com uma atividade, a menos que solicitado. Valores vazios de um cliente nunca apagam texto ou treinos existentes.

Toda escrita é previsível e verificável (detalhes: segurança de escrita em intervals://guide):

  • dry_run=true em toda ferramenta de criar/atualizar (incluindo create_custom_item) retorna a solicitação exata (método, caminho, corpo após todos os padrões e mesclagens, como JSON compacto) e o resultado da validação; nenhuma solicitação de escrita é enviada (o servidor recusa toda solicitação não-GET durante uma execução de teste).

  • Criar um evento (único, em lote ou da biblioteca) primeiro lê os eventos da sua data (uma solicitação no intervalo de datas) e recusa uma duplicata (mesma categoria e esporte com o mesmo nome, ou o mesmo treino ou texto não trivial) a menos que allow_duplicate=true; um dia de tijolo ou um par AM/PM com nomes diferentes não é uma duplicata. A ferramenta em lote decide por entrada, lista as recusadas e cria sessões duplas planejadas (mesmo nome, conteúdo diferente).

  • Após toda escrita de evento ou treino da biblioteca, a resposta relê o que o Intervals.icu armazenou e analisou: data, nome, categoria, esporte, duração, carga, etapas analisadas vs. enviadas e avisos de análise (notas: data, nome, categoria, comprimento do texto).

  • delete_event, delete_library_workout e delete_custom_item leem o objeto primeiro e nomeiam o que foi excluído; um id ausente não exclui nada.

  • Credenciais nunca aparecem em logs ou saídas de ferramentas; no modo monousuário, o token de login do Intervals.icu é usado apenas para a verificação de identidade e nunca é armazenado (no modo multiusuário, é armazenado criptografado, veja acima).

  • Nunca exponha os transportes HTTP sem OAuth ou um caminho secreto, e sempre atrás de TLS.

  • No modo monousuário, uma implantação atende à chave de API de um atleta e a lista de permissões de login decide quem pode conectar; compartilhe uma implantação apenas no modo multiusuário.

Detalhes e como relatar uma vulnerabilidade: SECURITY.md.

Status do projeto e roteiro

1.0.0b1 é o primeiro beta público deste fork. O desenvolvimento acontece em pull requests revisados; main é protegido e toda mudança executa o CI completo.

Concluído

  • Campos personalizados, streams personalizados e estatísticas de intervalos para qualquer dado de dispositivo (também oferecido upstream como mvilanova/intervals-mcp-server#153)
  • Ferramentas de coaching, classes de permissão, correções upstream e pull requests da comunidade mesclados
  • Análise de desempenho, análise de execução para treinos excluídos e estendidos, níveis de detalhe, relatório de atividade em uma chamada, prompts e recursos
  • OAuth com "Continuar com Intervals.icu", permissões por conexão, documentos de metadados de cliente, HTTP streamable e SSE em um processo
  • Qualidade de análise: rides estendidos divididos corretamente, apenas intervalos comparáveis comparados, agregação de campos personalizados por significado, períodos de bem-estar claros, tamanhos mínimos de amostra para tendências de eficiência, resistência à fadiga honesta, graus de subida suavizados, relatório compacto
  • Carga de treino e intensidade: razão agudo:crônico, monotonia e tensão, distribuição em três zonas com índice de polarização, durabilidade aeróbica, projeção de carga e um contexto semanal de coach

Próximos

  • Primeira versão marcada: pacote PyPI, imagens GHCR e Docker Hub, entrada no MCP Registry e pacote Claude Desktop, tudo publicado pelo fluxo de release a partir de uma tag
  • Modo multi-atleta opcional que usa o token OAuth do Intervals.icu de cada atleta
  • Migração para o MCP SDK v2 quando estiver estável para os transportes usados aqui

Documentação

DocumentoConteúdo
docs/REMOTE_ACCESS.mdServidor OAuth, login no Intervals.icu, configuração do ChatGPT e Claude, proxy reverso, operações
docs/GARMIN_BRIDGE.mdTrabalhando com o Garmin Intervals Bridge, exemplos práticos, leitura de métricas de dispositivo
docs/FEATURE_COMPARISON.mdComparação com outros servidores MCP do Intervals.icu
docs/UPSTREAM_AUDIT.mdCada pull request upstream aberto e o que aconteceu com ele
docs/RELEASE_CHECKLIST.mdProcesso de release e portões
RELEASING.mdPublicando um release (PyPI, GHCR, Docker Hub, MCP Registry, pacote Claude Desktop) e o que fazer quando uma etapa falha
CHANGELOG.mdMudanças por versão
SECURITY.mdPolítica de segurança e relato de vulnerabilidades

Desenvolvimento

uv sync --all-extras --locked
uv run --locked pytest                 # synthetic fixtures, no credentials needed
uv run --locked ruff check .
uv run --locked mypy src tests
uv run --locked --with pylint pylint --disable=C0301 $(git ls-files '*.py')   # advisory

O CI executa ruff, mypy e pytest em Python 3.12 e 3.13, constrói e importa a wheel e o sdist, constrói e testa a imagem Docker e o pacote Claude Desktop, valida server.json contra o esquema do MCP Registry, faz lint dos workflows, e o CodeQL escaneia o código. Todas as GitHub Actions estão fixadas em SHAs de commit; o Dependabot mantém elas e as dependências atualizadas. Releases são construídos a partir de tags (docs/RELEASE_CHECKLIST.md, RELEASING.md); tags beta tornam-se pré-releases no GitHub.

Contribuições são bem-vindas: veja CONTRIBUTING.md. Nunca coloque dados reais de atletas, chaves de API ou hostnames em issues, fixtures ou logs.

Créditos e licença

Projeto original por Marc Vilanova e contribuidores: mvilanova/intervals-mcp-server. Este fork integra pull requests da comunidade por arnold-maderthaner (#140, #142 a #147), biochaos (#131) e kokostitiahah (#149), e correções relatadas e as métricas de carga de treino e intensidade propostas por morritter (#150); obrigado. Mantido por Futureweb, junto com o Garmin Intervals Bridge.

Licenciado sob a GNU General Public License v3.0, veja LICENSE. Intervals.icu e Garmin são marcas registradas de seus respectivos proprietários e são usadas apenas para descrever compatibilidade.