@maxwellmezadre/kotas-mcp 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Maxwell Mezadre
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,210 @@
1
+ # kotas-mcp
2
+
3
+ [![MIT](https://img.shields.io/badge/licença-MIT-blue.svg)](LICENSE)
4
+ [![Bun ≥ 1.3](https://img.shields.io/badge/bun-%E2%89%A5%201.3-black.svg)](https://bun.sh)
5
+ [![TypeScript strict](https://img.shields.io/badge/typescript-strict-3178c6.svg)](tsconfig.json)
6
+ [![CI](https://github.com/maxwellmezadre/kotas-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/maxwellmezadre/kotas-mcp/actions/workflows/ci.yml)
7
+
8
+ CLI e servidor MCP para as suas assinaturas compartilhadas no
9
+ [Kotas](https://kotas.com.br): grupos, o que você paga em cada um, faturas,
10
+ créditos, cauções, repasses recebidos como administrador, saldo, economia
11
+ acumulada e o histórico completo — inclusive das assinaturas que você já
12
+ encerrou. Tudo em um cache local, para que uma pergunta como *"quanto já gastei
13
+ no Kotas?"* seja respondida sem abrir o site.
14
+
15
+ O Kotas não tem API pública de cliente. Este projeto conversa com a mesma API
16
+ que o app `app.kotas.com.br` usa, com a sua própria sessão, **somente leitura**:
17
+ nenhuma tool cancela assinatura, saca, paga ou muda um valor.
18
+
19
+ ## Sumário
20
+
21
+ - [Instalação](#instalação)
22
+ - [Login](#login)
23
+ - [Uso — CLI](#uso--cli)
24
+ - [Uso — MCP](#uso--mcp)
25
+ - [Variáveis de ambiente](#variáveis-de-ambiente)
26
+ - [Tools](#tools)
27
+ - [Como funciona](#como-funciona)
28
+ - [Troubleshooting](#troubleshooting)
29
+ - [Documentação](#documentação)
30
+ - [Licença](#licença)
31
+
32
+ ## Instalação
33
+
34
+ ### Tudo de uma vez (Claude Code)
35
+
36
+ ```sh
37
+ bun run setup
38
+ ```
39
+
40
+ Compila o binário, instala em `~/.local/bin/kotas`, registra o servidor MCP no
41
+ escopo de usuário do `~/.claude.json` e instala a Skill em
42
+ `~/.claude/skills/kotas-mcp/`.
43
+
44
+ ### npm
45
+
46
+ ```sh
47
+ npm install -g @maxwellmezadre/kotas-mcp
48
+ ```
49
+
50
+ ### Binário único
51
+
52
+ Baixe o executável do seu sistema na [página de
53
+ releases](https://github.com/maxwellmezadre/kotas-mcp/releases) e ponha no
54
+ `PATH`. Não precisa de runtime instalado.
55
+
56
+ ## Login
57
+
58
+ Três caminhos, todos gravando o mesmo `session.enc` cifrado:
59
+
60
+ ```sh
61
+ kotas login # e-mail e senha (pergunta, ou KOTAS_EMAIL/KOTAS_SENHA)
62
+ kotas login --from-browser chrome # importa a sessão de um navegador já logado (macOS)
63
+ kotas login --paste # cola os três valores do localStorage
64
+ ```
65
+
66
+ O login do Kotas não tem captcha, então o caminho por senha é HTTP puro e não
67
+ precisa de navegador. A senha é usada uma vez e **nunca é gravada**: só ficam os
68
+ dois tokens e o identificador do dispositivo.
69
+
70
+ Se a conta tiver verificação em duas etapas, passe o código:
71
+
72
+ ```sh
73
+ kotas login --pin 123456
74
+ ```
75
+
76
+ Se o Kotas pedir liberação de dispositivo (HTTP 412), ele manda um e-mail, SMS
77
+ ou mensagem no Telegram. Confirme e rode `kotas login` de novo — o identificador
78
+ já foi salvo, então não troque de máquina no meio do processo.
79
+
80
+ ## Uso — CLI
81
+
82
+ ```sh
83
+ kotas sync # baixa o histórico para o cache (repete os blocos sozinho)
84
+ kotas subscriptions # as assinaturas que você tem hoje
85
+ kotas history # tudo que você já assinou, inclusive o que encerrou
86
+ kotas spending --by month # quanto por mês
87
+ kotas payouts # o que você recebe como administrador
88
+ kotas balance # saldo e economia acumulada
89
+ kotas invoices --status pago --from 2026-01-01
90
+ kotas subscription 397075 # plano, rateio, vagas e participantes
91
+ kotas export history --format csv
92
+ ```
93
+
94
+ Todo comando aceita `--json`, que imprime o mesmo objeto que a tool MCP devolve.
95
+
96
+ ## Uso — MCP
97
+
98
+ ```sh
99
+ claude mcp add -s user kotas -- /Users/você/.local/bin/kotas mcp
100
+ ```
101
+
102
+ Ou à mão, no `~/.claude.json`:
103
+
104
+ ```json
105
+ {
106
+ "mcpServers": {
107
+ "kotas": {
108
+ "type": "stdio",
109
+ "command": "/Users/você/.local/bin/kotas",
110
+ "args": ["mcp"]
111
+ }
112
+ }
113
+ }
114
+ ```
115
+
116
+ Use o caminho absoluto: clientes MCP não herdam o `PATH` do seu shell. Depois é
117
+ só perguntar: *"quanto já gastei no Kotas?"*, *"quais assinaturas eu tenho e
118
+ quanto pago em cada uma?"*, *"quanto vou receber como administrador este mês?"*
119
+
120
+ ## Variáveis de ambiente
121
+
122
+ | Variável | Default | Para quê |
123
+ | --- | --- | --- |
124
+ | `KOTAS_CONFIG_DIR` | `~/.config/kotas-mcp` | Onde ficam sessão, chave e cache |
125
+ | `KOTAS_SESSION_KEY` | — | Chave AES em base64 de 32 bytes; sem ela, uma é gerada em `session.key` |
126
+ | `KOTAS_EXPORT_DIR` | `~/Downloads/kotas-export` | O único diretório onde `export` escreve |
127
+ | `KOTAS_READ_ONLY` | `0` | Não registra `login`, `sync` e `export` |
128
+ | `KOTAS_COMPACT` | `0` | Respostas mínimas por padrão, para economizar contexto |
129
+ | `KOTAS_EMAIL` / `KOTAS_SENHA` | — | Só para o bootstrap do `login`; nunca são gravadas |
130
+ | `KOTAS_IMPORT_BROWSER` | — | `arc` \| `chrome` \| `chromium` \| `brave` \| `edge` |
131
+ | `KOTAS_APP_VERSION` | `1.127.0.0` | Header `versao`; se a API responder 426, atualize |
132
+ | `KOTAS_API_TOKEN` | (chave do front) | Chave estática da API, igual para todo mundo |
133
+ | `KOTAS_MIN_INTERVAL_MS` | `300` | Intervalo mínimo entre requisições |
134
+ | `KOTAS_JITTER_MS` | `200` | Variação aleatória somada ao intervalo |
135
+ | `KOTAS_HTTP_TIMEOUT_MS` | `30000` | Timeout de cada requisição |
136
+ | `KOTAS_LOG_FILE` | — | Espelha o log (que sai no stderr) em um arquivo |
137
+ | `KOTAS_BASE_URL` | `https://api-front.kotas.com.br` | Só para testes |
138
+
139
+ ## Tools
140
+
141
+ | Tool | Comando | Rede |
142
+ | --- | --- | --- |
143
+ | `auth_status` | `kotas status [--verify]` | 0 (1 com `--verify`) |
144
+ | `login` | `kotas login` | 1–2 |
145
+ | `doctor` | `kotas doctor` | ≈ 6 (3 com `--shallow`) |
146
+ | `sync` | `kotas sync [--full\|--reparse]` | em blocos |
147
+ | `list_subscriptions` | `kotas subscriptions` | 0 |
148
+ | `get_subscription` | `kotas subscription <id>` | 0 (1 se não estiver no cache) |
149
+ | `list_invoices` | `kotas invoices` | 0 |
150
+ | `get_invoice` | `kotas invoice <id>` | 0 (1 se faltarem os itens) |
151
+ | `list_credits` | `kotas credits` | 0 |
152
+ | `balance` | `kotas balance` | 2 |
153
+ | `list_payouts` | `kotas payouts` | 0 |
154
+ | `purchase_history` | `kotas history` | 0 |
155
+ | `spending_summary` | `kotas spending --by …` | 0 |
156
+ | `search_services` | `kotas search <termo>` | 1 |
157
+ | `export` | `kotas export <escopo>` | 0 |
158
+ | `raw_get` | `kotas raw <rota>` | 1 |
159
+
160
+ Referência completa dos parâmetros em [`docs/TOOLS.md`](docs/TOOLS.md), gerada a
161
+ partir do registry.
162
+
163
+ ## Como funciona
164
+
165
+ 1. **Sessão.** Dois tokens JWT (acesso e renovação) mais o identificador do
166
+ dispositivo, cifrados com AES-256-GCM em `~/.config/kotas-mcp/session.enc`,
167
+ modo 0600. O token de acesso dura 15 minutos e é renovado sozinho.
168
+ 2. **Um funil só.** Toda requisição passa por `src/core/http.ts`, que serializa
169
+ as chamadas, respeita um intervalo mínimo com jitter, faz backoff em 429/5xx
170
+ e cuida da renovação do token.
171
+ 3. **Faturas como raiz.** Um grupo cancelado some da API, então o histórico é
172
+ reconstruído a partir da descrição das faturas
173
+ (`Fatura grupo <produto> #<id>`). É por isso que `purchase_history` enxerga
174
+ assinaturas que o site já não mostra.
175
+ 4. **Cache local.** SQLite em `~/.config/kotas-mcp/cache.db`, com o payload cru
176
+ guardado ao lado do dado interpretado — assim `sync --reparse` reprocessa
177
+ todo o histórico sem gastar uma requisição.
178
+
179
+ ## Troubleshooting
180
+
181
+ | Sintoma | O que fazer |
182
+ | --- | --- |
183
+ | `Nenhuma sessão do Kotas salva` | `kotas login` ou `kotas login --from-browser chrome` |
184
+ | `O Kotas pediu a liberação do dispositivo` (412) | Confirme o e-mail/SMS/Telegram e rode `kotas login` de novo |
185
+ | `A conta tem verificação em duas etapas` | `kotas login --pin 123456` |
186
+ | `sync` devolve `done: false` | É esperado: chame de novo até `done: true` (o CLI já faz isso) |
187
+ | Listas vazias | O cache está vazio: rode `kotas sync` |
188
+ | HTTP 426 | A versão do front mudou: ajuste `KOTAS_APP_VERSION` |
189
+ | HTTP 400 em um grupo | O grupo foi encerrado e não existe mais na API; use `kotas history` |
190
+ | Algo quebrou de um jeito estranho | `kotas doctor` diz qual camada |
191
+
192
+ ## Documentação
193
+
194
+ | Arquivo | Conteúdo |
195
+ | --- | --- |
196
+ | [`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) | Camadas, regras duras e por que cada uma existe |
197
+ | [`docs/CONFIGURATION.md`](docs/CONFIGURATION.md) | Variáveis, arquivos em disco e registro no Claude Code |
198
+ | [`docs/USAGE.md`](docs/USAGE.md) | Do zero à primeira pergunta |
199
+ | [`docs/CLI.md`](docs/CLI.md) | Referência dos comandos |
200
+ | [`docs/TOOLS.md`](docs/TOOLS.md) | Referência das tools (gerada) |
201
+ | [`docs/LOGIN.md`](docs/LOGIN.md) | Os três caminhos de login e o que fica gravado |
202
+ | [`docs/DATA-MODEL.md`](docs/DATA-MODEL.md) | Modelo de domínio e schema do cache |
203
+ | [`docs/INTERNAL-API.md`](docs/INTERNAL-API.md) | A API do Kotas e as armadilhas confirmadas |
204
+ | [`docs/REDISCOVERY.md`](docs/REDISCOVERY.md) | O que fazer quando o Kotas mudar |
205
+ | [`docs/adr/`](docs/adr) | Uma decisão por arquivo |
206
+ | [`test/fixtures/README.md`](test/fixtures/README.md) | O que as fixtures são e o que a anonimização faz |
207
+
208
+ ## Licença
209
+
210
+ MIT. Veja [LICENSE](LICENSE).
package/SKILL.md ADDED
@@ -0,0 +1,122 @@
1
+ ---
2
+ name: kotas-mcp
3
+ description: >-
4
+ Assinaturas compartilhadas do Kotas da conta do usuário via MCP `kotas`:
5
+ grupos, o que ele paga em cada um, faturas, créditos, cauções, repasses
6
+ recebidos como administrador, saldo, economia acumulada e o histórico
7
+ completo — inclusive das assinaturas já encerradas. Use para perguntas como
8
+ "quanto já gastei no Kotas", "quais assinaturas eu tenho e quanto pago",
9
+ "quanto vou receber como administrador", "quando eu assinei a Netflix e por
10
+ quanto tempo". Triggers: kotas, assinatura, assinaturas, grupo, kota, rateio,
11
+ vaga, fatura, mensalidade, quanto gastei, quanto pago, repasse, recebimento,
12
+ administrador, membro, crédito, caução, saldo, economia, saque, fidelidade,
13
+ Netflix, Spotify, Google One, SetApp, 1Password, Canva, Disney, HBO,
14
+ Youtube Premium.
15
+ ---
16
+
17
+ # Kotas — assinaturas compartilhadas
18
+
19
+ MCP `kotas` (`mcp__kotas__*`), 16 tools. Referência completa de parâmetros em
20
+ `TOOLS.md`, ao lado deste arquivo.
21
+
22
+ O Kotas é o serviço onde várias pessoas dividem uma assinatura. Cada assinatura
23
+ é um **grupo**, cada vaga é uma **kota**, e cada pessoa paga a sua parte. Quem
24
+ cria o grupo é o **administrador**: paga o serviço por fora e recebe o rateio
25
+ dos membros.
26
+
27
+ ## Leia antes de responder
28
+
29
+ 1. **Comece por `auth_status` quando qualquer coisa falhar.** Ele responde sem
30
+ rede e diz se há sessão, de quem é, até quando o token vale e o que já está
31
+ no cache. O token de acesso dura 15 minutos, então `accessTokenExpired: true`
32
+ é normal — ele é renovado sozinho na chamada seguinte.
33
+
34
+ 2. **O cache responde quase tudo.** `list_subscriptions`, `list_invoices`,
35
+ `list_credits`, `list_payouts`, `purchase_history` e `spending_summary` não
36
+ usam a rede. Se vierem vazios, rode `sync`.
37
+
38
+ 3. **`sync` trabalha em blocos.** Se devolver `done: false`, chame de novo com
39
+ os mesmos parâmetros até `done: true`. Não aumente `max_requests` para
40
+ "acelerar" e não chame em paralelo: o ritmo existe para o uso ficar parecido
41
+ com o de uma pessoa. Um histórico de ~260 faturas leva ~305 requisições e
42
+ uns 2 minutos.
43
+
44
+ 4. **Fatura cancelada ou estornada NÃO é gasto.** Só `status: "pago"` é dinheiro
45
+ que saiu. `spending_summary` já conta só as pagas; se você somar à mão, some
46
+ `total`, nunca `amount` — `total` é o que de fato saiu, com juros, reajuste
47
+ e desconto embutidos.
48
+
49
+ 5. **Grupo encerrado não existe mais na API.** `get_subscription` responde erro
50
+ para ele, e `list_subscriptions` só mostra os que continuam ativos. O
51
+ histórico das assinaturas antigas vive **nas faturas**, e é isso que
52
+ `purchase_history` reconstrói. Para "o que eu já assinei", use
53
+ `purchase_history`, nunca `list_subscriptions`.
54
+
55
+ 6. **Nos créditos, use `available`, não `amount`.** A API zera o valor de face
56
+ de todo lançamento já consumido, então `amount` vem 0 em quase tudo.
57
+ `available` é a cifra que existe e é a que fecha com o saldo da carteira.
58
+
59
+ 7. **Saldo bloqueado não é dinheiro perdido.** São as cauções das inscrições
60
+ (crédito tipo 96): ficam retidas enquanto a assinatura durar e voltam quando
61
+ ela é encerrada.
62
+
63
+ 8. **Grupo que o usuário administra não gera fatura.** Ele paga o serviço por
64
+ fora e recebe o rateio, então aparece em `purchase_history` com
65
+ `monthsPaid: 0` e `totalPaid: null`, e o dinheiro dele está em
66
+ `receivedAsAdmin` e em `list_payouts`. Não diga que ele "não pagou nada".
67
+
68
+ 9. **Repasse com status `Cancelado` não vai mais acontecer.** Só some no
69
+ previsto o que está `Agendado` — é o que `scheduledTotal` já faz.
70
+
71
+ 10. **`search_services` é o catálogo, não o histórico.** Serve para "quanto
72
+ custa o plano X no Kotas", não para "o que eu assino".
73
+
74
+ 11. **As credenciais do serviço compartilhado (login e senha da Netflix, do
75
+ Spotify…) não são acessíveis por aqui, de propósito.** Não existe tool para
76
+ elas e a rota é bloqueada. Se pedirem, diga que estão no app do Kotas.
77
+
78
+ 12. **Este servidor nunca altera a conta.** Não cancela assinatura, não saca,
79
+ não paga, não muda valor de grupo. Se pedirem, explique que é só leitura.
80
+
81
+ ## Tools ↔ CLI
82
+
83
+ | Tool | Comando | Para quê |
84
+ | --- | --- | --- |
85
+ | `auth_status` | `kotas status [--verify]` | Sessão, perfil, validade do token, cache |
86
+ | `login` | `kotas login [--from-browser chrome]` | Salva a sessão cifrada em disco |
87
+ | `doctor` | `kotas doctor [--shallow]` | Diz qual camada quebrou |
88
+ | `sync` | `kotas sync [--full\|--reparse]` | Baixa o histórico para o cache |
89
+ | `list_subscriptions` | `kotas subscriptions [--role]` | As assinaturas que ainda existem |
90
+ | `get_subscription` | `kotas subscription <id>` | Plano, rateio, vagas, participantes |
91
+ | `list_invoices` | `kotas invoices [--status --from --to]` | As faturas |
92
+ | `get_invoice` | `kotas invoice <id>` | Uma fatura com os itens |
93
+ | `list_credits` | `kotas credits [--kind]` | Cauções, repasses, adições, estornos |
94
+ | `balance` | `kotas balance` | Saldo e economia acumulada (ao vivo) |
95
+ | `list_payouts` | `kotas payouts [--group]` | O que se recebe como administrador |
96
+ | `purchase_history` | `kotas history [--active]` | Tudo que já foi assinado, inclusive encerrado |
97
+ | `spending_summary` | `kotas spending --by month` | Gastos por mês, ano, produto ou situação |
98
+ | `search_services` | `kotas search <termo>` | Catálogo de serviços e planos |
99
+ | `export` | `kotas export <escopo>` | CSV/JSON em `~/Downloads/kotas-export` |
100
+ | `raw_get` | `kotas raw <rota> [-q k=v]` | Válvula de escape para redescoberta |
101
+
102
+ ## Receitas
103
+
104
+ | Pergunta | O que chamar |
105
+ | --- | --- |
106
+ | "quanto já gastei no Kotas?" | `spending_summary` com `by: "year"` |
107
+ | "quanto gasto por mês?" | `spending_summary` com `by: "month"` |
108
+ | "o que eu mais paguei?" | `spending_summary` com `by: "product"` |
109
+ | "quais assinaturas eu tenho?" | `list_subscriptions` |
110
+ | "o que eu já assinei um dia?" | `purchase_history` |
111
+ | "por quanto tempo tive a Canva?" | `purchase_history`, campo `monthsPaid` |
112
+ | "quanto vou receber este mês?" | `list_payouts`, campo `scheduledTotal` |
113
+ | "quanto tenho de saldo?" | `balance` |
114
+ | "quem está no meu grupo?" | `get_subscription` do grupo administrado |
115
+ | "quanto economizei?" | `balance`, campo `saved` |
116
+
117
+ ## Avisos
118
+
119
+ - Somente leitura. Nenhuma tool altera a conta.
120
+ - Ritmo próximo ao de uma pessoa (~2 requisições por segundo). Não force.
121
+ - `KOTAS_READ_ONLY=1` remove `login`, `sync` e `export` do registro.
122
+ - O refresh token é o segredo de verdade: não o mostre nem o peça em texto.