Ekyte MCP
Ekyte MCP / Ekyte MCP
Servidor MCP + CLI que responde quem lançou e quem não lançou horas no Ekyte, e quanto do pacote mensal de manutenção cada projeto já consumiu. Código canônico:
mukutu-mono/apps/ekyte-mcp(privado). Duas superfícies, uma mesma lógica de negócio (src/hours.ts). Fonte: mukutu-mono.
Números deste documento são ilustrativos
Consumo por projeto e nome de cliente são dado comercial e não entram no brain (este site é público). Os exemplos abaixo usam projetos fictícios; o dado real sai da ferramenta, na hora.
Esta página tinha sido apagada — restaurada em 24/09
Arquivado em 28/08, apagado do monorepo e do wiki em 03/09 (3ceb2461) com a justificativa de que o MCP oficial do Ekyte tornava um MCP próprio redundante. A justificativa estava certa sobre a ponte (acesso à API) e errada sobre a política (regras de negócio da Mukutu) — as duas saíram juntas. O que o arquivamento não previu: três rotinas agendadas e um workflow do mkt_central (apontamento-em-massa, coleta-horas-manutencao, verificacao-apontamento-delta, Z99_alerta_franquia_manutencao) dependiam destas ferramentas, sem substituto no oficial — e continuaram rodando de um clone órfão na máquina da Ana (manager-genesis/, já listado como candidato a limpeza de disco). O app foi restaurado ao monorepo em 23/09/2026 (PR #241 política + PR #242 deploy), a partir do commit anterior ao apagamento — que já trazia a correção de cálculo do PR #184 (ver abaixo). Esta nota do vault só foi refeita em 24/09, ao notar o link quebrado durante outra ingestão.
O que faz / What it does
Deriva o time automaticamente (quem tem apontamento nos últimos 30 dias — EKYTE_MCP_ROSTER_WINDOW_DAYS), aplica a meta de horas por pessoa e um calendário de dias úteis, e devolve o semáforo 🔴🟡🟢. / Answers who logged hours and who didn’t.
O semáforo: soma as horas de apontamentos Concluídos (status 20) cujo dia de trabalho é a data avaliada, dentro do escopo. Então:
- 🔴 vermelho —
horas = 0, não lançou nada. - 🟡 amarelo —
0 < horas < meta, lançou abaixo da meta. - 🟢 verde —
horas ≥ meta.
Meta: por pessoa, em config/thresholds.json — hoje 6h para todo o time, sem overrides cadastrados. Ajustar alguém para meio-período é editar esse arquivo, sem tocar no código.
Anti-falso-alarme: janela de atraso de ~4 dias (lançamento tardio ainda conta no dia trabalhado); só dias úteis contam como “faltou” (src/workday.ts + config/holidays.json); fuso America/São_Paulo.
Não é a ponte — é a política / Not the bridge — the policy on top
O MCP oficial do Ekyte (api.ekyte.com/mcp) tem 105 ferramentas de CRUD cru (medido em 23/09/2026) — é para onde vai quem precisa escrever (criar tarefa, apontar hora, mover etapa). Este app não compete com ele; sabe o que o oficial não sabe:
| MCP oficial do Ekyte | ekyte-mcp (este) | |
|---|---|---|
| Papel | acesso à API | política da casa sobre os mesmos dados |
| Escreve? | sim, em produção | nunca — a REST por trás é GET-only |
| Sabe o que é “meta de 6h/dia”? | não | sim |
| Sabe o que é pacote de manutenção? | não | sim |
As duas superfícies / The two surfaces
CLI muk-ekyte — saída em tabela colorida no terminal, JSON quando redirecionada (para jq, scripts):
muk-ekyte hours # time todo, hoje — 🔴🟡🟢
muk-ekyte hours --status red,yellow # só quem está devendo horas
muk-ekyte hours --workspace muk --status red,yellow # escopo Mukutu
muk-ekyte hours --date 2026-07-15 --format json | jq '.people'
muk-ekyte person "Nome" --period 14 # histórico de 14 dias
MCP ekyte-mcp no Claude Code — registrado no escopo user (vale em todos os projetos). Pergunta em linguagem natural: “quem não lançou horas hoje?”, “status de horas do time em 15/07/2026”, “quem está vermelho ou amarelo no escopo mukutu?”, “status das manutenções deste mês”.
As 6 ferramentas / The 6 tools
| Ferramenta | Pergunta que responde |
|---|---|
ekyte_hours_status(date?) | Time inteiro num dia: horas lançadas vs. meta, com semáforo. |
ekyte_missing(date?) | Só quem ficou abaixo da meta naquele dia (🔴 + 🟡). |
ekyte_person(name, period_days?) | Histórico dia a dia de uma pessoa numa janela recente. |
ekyte_maintenance_status(month?, workspace?, match?) | Por projeto de manutenção: horas do mês vs. o pacote mensal lido do nome do projeto. |
ekyte_person_projects(name, month?) | De uma pessoa: horas por projeto no mês, em 3 baldes transparentes (cliente / interno Mukutu / não-mapeado). |
ekyte_fill_hours_plan(entries) | Caminho de escrita (preencher horas) — inerte por design: devolve um plano, nunca escreve. ⚠️ dívida conhecida: o oficial já escreve de verdade com create_time_tracking; esta ferramenta é candidata a sair, mantida por ora para não fragmentar a restauração. |
Escopo Mukutu / Mukutu scope
Use --workspace muk. O substring muk casa os ~35 workspaces Mukutu* (incluindo os “Mukutu - Cliente”) e um workspace com erro de digitação no nome — e nenhum outro workspace contém “muk”, então não há falso positivo. Verificado em 17/07/2026: 15 pessoas no escopo. Manutenção semanal: revarrer /workspaces da API e conferir se surgiu workspace Mukutu fora do padrão.
Manutenção: horas do mês vs. pacote / Maintenance packages
Pergunta diferente do semáforo diário: o semáforo é pessoa × dia, este é projeto × mês. Feito para relatório de cliente e diretoria.
- Pacote — lido do nome do projeto (
… - 8h→ 8h/mês, regex/(\d+)\s*h\b/). Projeto semNhno nome vem comono_package. - Consumido — a soma bruta dos apontamentos do mês, o mesmo número que a tela “Estatísticas de Apontamento” do próprio Ekyte mostra. ⚠️ Isto mudou desde a versão anterior desta nota: até o PR #184 (18/08), o cálculo passava pelo join
apontamento → tarefa → projeto, que subcontava horas de tarefa já arquivada (caso validado: um projeto leu 18,8h pelo join contra 20h47 reais). O join foi abandonado — hoje, em workspace “puro” de manutenção todo apontamento conta; em workspace “misto” (tem também projeto de site ativo), só conta o que a tarefa nomeia como manutenção. - Status —
over(estourou o pacote) ·ok(dentro) ·unused(0h no mês) ·no_package.
Exemplo de formato do retorno (projetos fictícios):
| Projeto | Pacote/mês | Consumido | % | Status |
|---|---|---|---|---|
| Cliente A · Manutenção | 8h | 5,0h | 63% | ok |
| Cliente B · Manutenção | 12h | 4,8h | 40% | ok |
| Cliente C · Manutenção | 20h | 24,2h | 121% | over |
| Cliente D · Manutenção | 8h | 0h | 0% | unused |
O retorno completo traz ainda remaining_hours, end_date, expired, summary (contagem por status) e coverage.
Flag expired: vários projetos de manutenção têm data de término no passado e continuam recebendo horas — renovação não atualizada no Ekyte. O campo marca o caso sem somar nada silenciosamente: o pacote continua válido (a comparação de consumo vale), mas o registro precisa ser corrigido no Ekyte.
ekyte_person_projects nunca devolve um número só: o split cliente × interno é heurística sobre o título da tarefa e pode errar, então vem como balde sinalizado e jamais é somado ao total de cliente. ⚠️ Comportamento conhecido e aceito (24/09): o workspace interno Mukutu cai inteiro no balde de manutenção quando a linha não tem pacote contratado — não é bug, é a regra de hoje.
O frescor viaja dentro da resposta
Toda ferramenta de leitura retorna meta { generated_at, timezone, scope, up_to_date, alert }. Quando up_to_date = false (hoje ainda aberto, mês em andamento, data futura ou janela de lançamento tardio), o alert explica por que o número é provisório — e o aviso é sempre repassado a quem perguntou. O sinal não depende de memória nem de reinício: é a correção durável para “estou olhando dado parcial?”. Lógica em src/format.ts.
Datas: as ferramentas MCP aceitam dd/mm/aaaa ou ISO AAAA-MM-DD (mês mm/aaaa ou AAAA-MM) e sempre retornam dd/mm/aaaa. A CLI ainda usa ISO na flag --date e na saída JSON até ser recompilada.
Escrita de horas: inerte por design / Write path
ekyte_fill_hours_plan é a costura para preencher horas — a API REST do Ekyte é GET-only, então escrever de verdade significa dirigir a UI web via browser (pydoll). A v1 entrega a ferramenta deliberadamente inerte: valida e devolve {status: "plan_only", items, note}, sem abrir browser nem escrever, mesmo se pedirem. O MCP oficial já escreve de verdade (create_time_tracking) — é por isso que esta ferramenta é dívida conhecida, candidata a sair numa limpeza futura.
O serviço hospedado / The hosted service
ekyte-mcp.mukutu.cloud segue no ar (respondeu 400 em /mcp e 200 em /gestores.html em 23/09/2026) — o container nunca foi desligado, mesmo com o app apagado do git por três semanas. Dockerfile, deploy/docker-compose.yml, deploy/traefik-ekyte-mcp.yml.example e scripts/deploy.sh foram recuperados junto (PR #242) — quem hospeda o app consegue reconstruir o container a partir do próprio monorepo de novo. O workflow do GitHub que disparava deploy automático não voltou — de propósito, para o serviço não ganhar vida própria de novo sem decisão humana. O roteiro de encerramento formal (5 passos, GO humano em cada) nunca passou do passo 1.
Fontes de dados / Data sources
Duas camadas, em ordem de prioridade: (1) SurrealDB Mukutu ek_mart_daily — ainda não implantada em produção; (2) API REST do Ekyte /v1.0/time-trackings — o caminho que roda hoje. src/surreal.ts degrada para [] em qualquer erro (nunca lança), então o MCP funciona pela API hoje e passa a usar o mart sozinho quando ele subir.
Segurança da chave / Key handling
EKYTE_API_KEY (credencial da REST, escopo empresa) fica como variável de ambiente do usuário — fora de arquivo versionável, nunca commitada. É diferente do EKYTE_MCP_TOKEN do MCP oficial (de usuário); confundir as duas custa tempo. O servidor MCP herda a chave no momento em que o Claude Code inicia.
Por que importa para a Nova Mukutu / Why it matters
- Substitui a checagem manual na UI do Ekyte por uma pergunta em linguagem natural — caso de uso direto de Automacoes de IA com dado interno real.
- O relatório de pacote de manutenção é insumo de cobrança e diretoria: mostra estouro de escopo mês a mês, ligando a Modelo de Orçamento de Produto.
- Episódio didático de governança: um app pode ser apagado com boa justificativa parcial e continuar vivo, sem registro, sustentado por um clone órfão numa máquina pessoal — o risco que Governança Mukutu e o AI SDLC tentam fechar.
Perguntas a responder / Questions to answer
ekyte_fill_hours_plansai de vez, ou fica como fallback quando o oficial não cobrir algum caso?- Quando o
ek_mart_dailysobe no SurrealDB (tira a dependência da API REST)? - O roteiro de encerramento do serviço hospedado — os 4 passos que faltam — ainda é a decisão certa, ou a restauração de 23/09 muda o plano?
Relacionado / Related
- Ouvinte do Google Chat
- Skills da Equipe Mukutu
- Automacoes de IA
- Governança Mukutu
- AI SDLC
- mukutu-mono
Fontes / Sources
mukutu-mono/apps/ekyte-mcp/README.md+src/(origin/main, lido em 24/09/2026) — 6 tools registradas, comparação com o oficial (105 tools).- Commits
3ceb2461(apagamento, 03/09),c8eecd8/PR #241 (política volta, 23/09),236122a/PR #242 (deploy volta, 23/09) —mktvirtual/mukutu-mono. docs/mukutu-atividades/levantamento-iniciativas-mukutu.md(mukutu-mono) — item 7.1, revisão de 23/09.