Woovi Pix MCP
README.md
# Woovi Pix MCP
Servidor MCP local em Go para consultar e, opcionalmente, criar cobranças Pix
Woovi. A ferramenta `pix_create_charge` fica desativada por padrão. Não há Pix
Out, transferências, reembolsos ou cancelamentos financeiros.
Stack: Go 1.27.3, MCP Go SDK v1.8.0, SQLite embutido e Goose v3 para migrações
SQL. Quando escrita está habilitada, o servidor cria o banco privado e aplica
as migrações ao iniciar. Não requer PostgreSQL nem Docker.
CLI local: setup, perfis, stdio, doctor, instalação segura em clientes JSON e
Litestream opcional. Transporte remoto, distribuição pública e operações Pix
Out estão fora do escopo. Validação externa no sandbox Woovi ainda não realizada.
## Licença
Copyright 2026 Lucas Eufrasio e contribuidores.
Licenciado sob a [Apache License 2.0](LICENSE).
Projeto independente, não oficial da Woovi. A licença cobre o código deste
repositório, não concede direitos sobre marcas de terceiros e não substitui
os termos de uso da API Woovi. Dependências mantêm suas próprias licenças.
## Configurar pela CLI
```sh
go build -o ./bin/woovi-pix-mcp ./cmd/woovi-pix-mcp
./bin/woovi-pix-mcp setup --profile sandbox
./bin/woovi-pix-mcp doctor --profile sandbox
```
O assistente interativo permite selecionar entre sandbox
(`https://api.woovi-sandbox.com`), produção (`https://api.woovi.com`) e o
simulador local (`http://127.0.0.1:8081`), informa o identificador estável da
conta e mantém criação de cobranças desativada por padrão. O AppID é digitado
mascarado e salvo no cofre de credenciais do sistema. Se o
cofre não estiver disponível, o setup falha: não há fallback silencioso. Use
`setup --profile sandbox --secret-file` somente se aceitar guardar o segredo
sem criptografia em arquivo restrito ao usuário. Permissões POSIX são validadas;
ACLs Windows ainda precisam validação antes de recomendar esse fallback lá.
Perfis existentes não são sobrescritos: use outro nome para nova configuração.
Configure seu cliente com o caminho absoluto do binário e argumentos
`["stdio", "--profile", "sandbox"]`. Não inclua AppID na configuração do cliente.
`doctor` é diagnóstico local; não chama Woovi nem cria cobrança.
## Instalar
No Linux ou macOS, instale a release mais recente em `~/.local/bin`:
```sh
curl -fsSL https://github.com/lucaswilliameufrasio/woovi-pix-mcp/releases/latest/download/woovi-pix-mcp-installer.sh | sh
```
Para instalar uma versão específica, baixe o instalador da release e informe a
tag. Exemplo com `v0.1.2`:
```sh
curl -fsSL https://github.com/lucaswilliameufrasio/woovi-pix-mcp/releases/download/v0.1.2/woovi-pix-mcp-installer.sh | sh -s -- --tag v0.1.2
```
No Windows PowerShell, para a release mais recente:
```powershell
Invoke-WebRequest https://github.com/lucaswilliameufrasio/woovi-pix-mcp/releases/latest/download/woovi-pix-mcp-installer.ps1 -OutFile woovi-pix-mcp-installer.ps1
.\woovi-pix-mcp-installer.ps1
```
Passe `-Tag v0.1.2` para fixar uma versão no Windows.
Os instaladores verificam o SHA-256 do pacote antes da instalação. É necessário
adicionar `~/.local/bin` ao `PATH` se ainda não estiver configurado.
`profiles` lista os nomes configurados sem carregar ou exibir credenciais.
O identificador de conta precisa ser estável e corresponder à conta do AppID:
o servidor não consegue verificar isso offline. Dois perfis da mesma conta e
ambiente compartilham o histórico de idempotência, inclusive após trocar AppID.
Ao executar `woovi-pix-mcp` sem argumentos pela primeira vez em um terminal,
sem as duas variáveis legadas completas, o CLI abre o assistente Bubble Tea para
criar o perfil `sandbox`: use ↑/↓ para escolher o ambiente, Enter para avançar
e Esc para cancelar. Depois de salvar, ele mostra os comandos para validar e
conectar o cliente. Se já houver perfis, use `profiles` para escolher
explicitamente; o perfil `sandbox` é iniciado automaticamente quando existir e
nenhum par completo de variáveis de ambiente estiver configurado. Sem terminal,
o CLI não solicita segredos: mostra como executar `setup` interativamente.
## Instalar no cliente MCP
Sem `--client`, o CLI abre um seletor Bubble Tea com cinco clientes. O arquivo
do projeto atual é sugerido; preview é o padrão e `--apply` salva com backup,
preservando entradas alheias. Exemplo:
```sh
./bin/woovi-pix-mcp install-mcp --profile sandbox --client opencode --config ~/.config/opencode/opencode.json
./bin/woovi-pix-mcp install-mcp --profile sandbox --client opencode --config ~/.config/opencode/opencode.json --apply
```
Suporta OpenCode **V2**, Claude Code, Cursor, Codex CLI e Gemini CLI. JSONC,
arquivos de configuração não privados ou symlinks são recusados; uma entrada
diferente com o mesmo nome não é sobrescrita. Codex TOML recebe a entrada ao
final para preservar comentários e tabelas existentes.
## Comandos de desenvolvimento
`make help` lista os comandos disponíveis. Exemplos:
Para `make fmt`/`make check`, além de Go, instale golangci-lint 2.14.0, Python
3.12+ e uv. Ruff é resolvido na versão fixa 0.16.10. O lint também verifica
espaçamento entre blocos Go; não basta passar no `gofmt`.
```sh
make test
make check
make migrate-create name=add_charge_metadata
```
Os testes usam arquivos SQLite reais temporários, inclusive processos separados.
As novas migrations são timestamped e criadas pela
Goose CLI. Não há target `migrate-down`/`reset`: a migration Down remove as
tabelas de operação/auditoria e pode apagar evidência de idempotência.
## Processo de release
**Prepare Release** abre um PR de changelog; após revisão/CI e merge, uma tag
`vX.Y.Z` dispara **Release**, que repete os checks e cria um **draft** com binários
Linux/macOS/Windows (amd64/arm64) e checksums SHA-256. Publicar o draft continua
sendo uma decisão manual. Nenhuma release é disparada ao adicionar os workflows.
Veja [docs/releases.md](docs/releases.md) para configuração, preparação,
tagueamento, verificação de artefatos e limitações de plataforma. Para validar
o empacotamento local sem publicar: `make release-snapshot` (GoReleaser 2.18.2).
## Executar
```sh
./bin/woovi-pix-mcp stdio --profile sandbox
```
Para compilar um binário local sem instalá-lo globalmente:
```sh
go build -o ./bin/woovi-pix-mcp ./cmd/woovi-pix-mcp
```
Execute o binário com `stdio --profile sandbox` para iniciar o servidor. Sem
argumentos, a primeira execução em um terminal orienta a configuração. Se já
houver um perfil `sandbox`, o comando sem argumentos inicia esse perfil; se
houver apenas perfis com outros nomes, o CLI abre um seletor interativo. Em
execuções sem terminal, escolha explicitamente com `stdio --profile NAME`. O
diretório `bin/` é apenas uma saída local e não deve ser versionado.
O AppID fica no processo servidor e nunca é um argumento ou resultado MCP. Logs
operacionais vão para stderr; stdout fica reservado ao protocolo stdio. O host
Woovi de produção é `https://api.woovi.com`, mas o servidor aceita apenas HTTPS
para hosts remotos.
Criação é uma capacidade explicitamente opt-in. Requer identificador fixo da
conta autorizada e limite máximo de R$ 100.000 por cobrança, sem banco externo:
No `setup`, responda `yes` somente se quiser habilitar criação. Para automação,
o modo legado sem subcomando ainda aceita `WOOVI_API_BASE_URL`, `WOOVI_APP_ID`,
`WOOVI_ACCOUNT_ID` e `WOOVI_ENABLE_CHARGE_CREATION`; injete o segredo pelo cofre
da automação, nunca em argv, histórico do shell ou configuração dos clientes.
Cada referência é usada como `correlationID` Woovi e chave idempotente local.
Repetir o mesmo payload retorna resultado já persistido; outra carga para a
mesma referência conflita. Uma chamada com resultado incerto permanece `UNKNOWN`
e não é reenviada automaticamente: a ferramenta primeiro consulta a Woovi pela
referência e só fecha a operação quando referência e valor batem. Se não for
encontrada, permanece `UNKNOWN`. O valor explícito está limitado a R$ 100.000 e
expiração de 300 a 2.592.000 segundos. Tentativas e resultados são auditados no
SQLite sem persistir AppID ou conteúdo do QR no log de auditoria. Esta fatia
não implementa approval workflow.
O arquivo SQLite é criado sob o diretório de configuração do usuário, em
`woovi-pix-mcp/state/<escopo>/operations.db`; o escopo separa URL/ambiente e conta.
`WOOVI_DATABASE_PATH` permite indicar outro arquivo privado. Nunca apague o
arquivo para resolver um erro: ele guarda a evidência das tentativas anteriores.
SQLite usa WAL, synchronous FULL e espera limitada para escritores concorrentes.
Não há DATABASE_URL nem importação PostgreSQL; esse MCP não teve usuários legados.
## Teste rápido local — sem chamar a Woovi
Execute os comandos na raiz deste repositório, com Go 1.27.3 instalado. Este
roteiro usa somente dados fictícios e não precisa de conta Woovi ou Docker.
### 1. Terminal 1: subir o simulador
```sh
mise exec go@1.27.3 -- go run ./cmd/woovi-simulator
```
Deixe esse terminal aberto. O simulador escuta em `127.0.0.1:8081`.
### 2. Terminal 2: compilar e configurar
```sh
go build -o ./bin/woovi-pix-mcp ./cmd/woovi-pix-mcp
./bin/woovi-pix-mcp setup --profile teste
```
Responda ao assistente:
- Ambiente: `simulator`
- Conta: `conta-teste`
- Habilitar criação: `no`
- AppID: `simulator` (a entrada fica oculta)
Se o cofre do sistema estiver indisponível, repita o setup com o fallback
explícito abaixo. Ele guarda o AppID sem criptografia em arquivo privado 0600:
```sh
./bin/woovi-pix-mcp setup --profile teste --secret-file
```
Se o perfil já existir, reutilize-o ou escolha outro nome; não há sobrescrita.
### 3. Conferir a configuração
```sh
./bin/woovi-pix-mcp doctor --profile teste
```
**Esperado:** ambiente `simulator`, credencial disponível sem exibir AppID e
criação desabilitada. O banco pode aparecer como não inicializado: isso é normal
em modo somente leitura. `doctor` não consulta nem mesmo o simulador.
### 4. Conectar ao OpenCode V2
Para configurar um cliente no projeto atual, execute o seletor interativo:
```sh
./bin/woovi-pix-mcp install-mcp --profile teste
```
Ele oferece OpenCode, Claude Code, Cursor, Codex CLI e Gemini CLI, usando os
arquivos de configuração **do projeto atual** por padrão. O primeiro comando
faz preview; revise e repita com `--apply` para gravar. Também é possível
escolher cliente e arquivo explicitamente:
```sh
./bin/woovi-pix-mcp install-mcp --profile teste --client opencode --config opencode.json
./bin/woovi-pix-mcp install-mcp --profile teste --client opencode --config opencode.json --apply
```
Os caminhos padrão são `opencode.json`, `.mcp.json`, `.cursor/mcp.json`,
`.codex/config.toml` e `.gemini/settings.json`, respectivamente. JSONC não é
reescrito; TOML do Codex recebe a entrada ao final do arquivo. O instalador faz
backup antes de aplicar e recusa sobrescrever uma entrada Woovi conflitante.
Ele registra somente binário e perfil, **nunca AppID**; mantenha o binário no
caminho usado na instalação.
Instale também o skill e os avisos de segurança específicos dos hosts suportados
no projeto atual. Revise o preview antes de aplicar:
```sh
./bin/woovi-pix-mcp install-agent-assets
./bin/woovi-pix-mcp install-agent-assets --apply
```
Isso instala o skill em `.agents/skills/` e `.claude/skills/`, o hook
`SessionStart` do Claude Code e um plugin do OpenCode que acrescenta o aviso ao
contexto de cada chamada. O aviso não bloqueia ferramentas nem substitui
autorização; `pix_create_charge` é uma operação de escrita opcional. Nenhuma
configuração global dos clientes é alterada.
### 5. Consultar a cobrança fictícia
Reabra o OpenCode para carregar o servidor `woovi-pix-teste` e peça:
> Use o servidor woovi-pix-teste para consultar a cobrança `demo-charge` com
> `pix_get_charge`. Não use outros servidores nem crie cobranças.
**Esperado:** ID `demo-charge`, referência `demo-order-001`, estado `ACTIVE` e
valor `1250` centavos (**R$ 12,50**), com código Pix fictício. Nenhuma chamada
Woovi ou operação financeira real é feita. Termine o simulador com Ctrl+C.
O simulador também mantém uma assinatura sintética `demo-subscription` em memória
para validar cancelamento, leitura do snapshot e paginação local:
```sh
curl -i -X PUT http://127.0.0.1:8081/api/v1/subscriptions/demo-subscription/cancel \
-H 'Authorization: simulator'
curl -sS http://127.0.0.1:8081/api/v1/subscriptions/demo-subscription \
-H 'Authorization: simulator'
curl -sS 'http://127.0.0.1:8081/api/v1/subscriptions/demo-subscription/installments?skip=0&limit=1' \
-H 'Authorization: simulator'
curl -sS 'http://127.0.0.1:8081/api/v1/subscriptions/demo-subscription/installments?skip=1&limit=1' \
-H 'Authorization: simulator'
```
O primeiro comando retorna `204`; o segundo mostra `status: CANCELED`. O estado
é sintético, vive apenas na memória do processo e volta a `APPROVED` após restart.
O GET da assinatura devolve somente IDs e estado fictícios; os GETs de parcelas
aceitam `skip` e `limit` de 1 a 100 e retornam `pageInfo`. A primeira página
inclui uma parcela `COMPLETED`, a segunda uma `SCHEDULED`.
Esse endpoint existe para exercitar adapters locais, não é ferramenta MCP, não
cria uma recorrência Woovi e não chama nem cancela uma assinatura real.
O simulador manual de cobrança também aceita consulta/criação em memória; criação
e idempotência são cobertas adicionalmente pelos testes automatizados. Para rodar
a suíte e as verificações do projeto:
```sh
make check
```
## Teste com o sandbox da própria Woovi
Este roteiro usa a API de teste externa da Woovi, **não o simulador local**.
Não é necessário executar `woovi-simulator`. Execute apenas com autorização
para usar essa conta; os passos abaixo não foram executados pela implementação
ou pela CI. Não use credenciais de produção nem faça pagamentos reais.
### 1. Preparar a conta e uma cobrança de teste
- Acesse [app.woovi-sandbox.com](https://app.woovi-sandbox.com/). O sandbox tem
cadastro separado: dados de produção não funcionam nele.
- No painel **do sandbox**, obtenha um AppID da sua conta. A documentação de
autenticação indica `Admin Panel > Permissions > APIs` para gerar a chave,
com permissão de administrador. Use os escopos necessários para consulta.
- Tenha uma cobrança criada no sandbox pelo painel e copie seu ID ou
`correlationID`. `demo-charge` é exclusivo do simulador e não deve ser usado aqui.
Referências oficiais: [ambiente de teste](https://developers.woovi.com/docs/test-environment)
e [criação da chave API](https://developers.woovi.com/en/docs/apis/api-getting-started).
### 2. Compilar e configurar o perfil sandbox
```sh
go build -o ./bin/woovi-pix-mcp ./cmd/woovi-pix-mcp
./bin/woovi-pix-mcp setup --profile sandbox
```
Responda:
- Ambiente: `sandbox` (seleciona `https://api.woovi-sandbox.com`)
- Conta: um identificador estável dessa conta, por exemplo `minha-conta-sandbox`
- Habilitar criação: `no`, para começar somente com consulta
- AppID: **o AppID do sandbox**, no prompt oculto; nunca cole no chat ou no cliente
A conta é o escopo local de idempotência, não outro segredo; mantenha o mesmo
identificador ao criar perfis para essa conta. Se o cofre estiver indisponível e
você aceitar o arquivo privado sem criptografia, use explicitamente:
```sh
./bin/woovi-pix-mcp setup --profile sandbox --secret-file
```
### 3. Conferir e conectar ao cliente
```sh
./bin/woovi-pix-mcp doctor --profile sandbox
./bin/woovi-pix-mcp install-mcp --profile sandbox \
--client opencode --config ~/.config/opencode/opencode.json
./bin/woovi-pix-mcp install-mcp --profile sandbox \
--client opencode --config ~/.config/opencode/opencode.json --apply
```
Valem os requisitos de JSON e permissões do roteiro local. **Esperado no doctor:**
ambiente `sandbox`, credencial disponível e criação desabilitada. Isso valida
apenas a configuração local, **não autenticação ou conectividade com a Woovi**.
### 4. Consultar uma cobrança do sandbox
Reabra o cliente e substitua `<ID_OU_CORRELATION_ID>` pelo identificador copiado
do painel. Se houver outros perfis instalados, selecione `woovi-pix-sandbox`:
> Use somente o servidor woovi-pix-sandbox para chamar `pix_get_charge` com
> `id` igual a `<ID_OU_CORRELATION_ID>`. Não crie nem pague cobranças.
**Esperado:** a cobrança da sua conta sandbox, com ID/referência, estado e valor
em centavos coerentes com o painel, sem AppID ou dados do pagador. Estado e
valor dependem da cobrança escolhida; não há resultado fixo de R$ 12,50 aqui.
Essa consulta é a verificação efetiva de API, credencial e escopo da conta.
### 5. Opcional: testar criação e idempotência no sandbox
Somente se quiser testar escrita e tiver autorização, siga o roteiro detalhado
em [docs/sandbox.md](docs/sandbox.md#criação-e-idempotência-opcionais). Ele cria
outro perfil com opt-in explícito e explica como repetir o mesmo payload e
verificar conflito. Não pague o QR gerado, não use produção e não invente outra
referência para contornar um timeout ou resultado incerto.
## Contrato Woovi verificado
- Autenticação por `Authorization: <AppID>`; API retorna/aceita JSON e requer
HTTPS. Limite documentado: 10 requisições por segundo.
- Consulta: `GET /api/v1/charge/{id}`; `id` aceita identificador da cobrança ou
`correlationID`.
- O retorno MCP é minimizado a identificador, referência, estado, centavos BRL,
expiração e código Pix; dados do pagador e payloads brutos são descartados.
- O cliente aplica limiter local conservador de 10 req/s (sem rajada) para
respeitar o limite publicado pela Woovi.
- Referências: [Autenticação e limites](https://developers.woovi.com/en/docs/apis/api-getting-started),
[API Redoc](https://developers.woovi.com/en/api-redoc),
[Correlation ID/idempotência](https://developers.woovi.com/en/docs/concepts/correlation-id).
O simulador de teste também suporta POST e mantém cobranças idempotentes pela
referência em memória; nunca use credencial ou host de produção nos testes.
Todos os testes de persistência SQLite executam automaticamente em `make test`,
sem credenciais ou infraestrutura externa.
## Litestream opcional e recuperação
Instale separadamente [Litestream 0.5.12+ (série 0.5.x)](https://litestream.io/install/), validado
com 0.5.17. Não é iniciado automaticamente e o MCP funciona sem ele.
```sh
./bin/woovi-pix-mcp replica-setup --profile sandbox --replica-url file:///absolute/private/backup/sandbox
# Alternativa: S3 ou compatível; access key e secret key entram em prompts sem eco.
./bin/woovi-pix-mcp replica-setup --profile sandbox --replica-url s3://my-bucket/account-specific-prefix --region us-east-1
./bin/woovi-pix-mcp replica-run --profile sandbox
```
Use apenas um dos destinos; configuração existente não é sobrescrita. Para S3
compatível use `--endpoint https://...`. Credenciais usam cofre do sistema ou
`--secret-file` explicitamente; não coloque credenciais na URL. O processo filho
recebe somente as credenciais da réplica, não o AppID. Prefira discos privados e
criptografia/controle de acesso do bucket: a réplica contém dados de cobranças.
Inicie stdio uma vez para inicializar o banco antes da primeira réplica.
`replica-run` fica em foreground; Ctrl+C o encerra. Um lock impede duas réplicas
gerenciadas para o mesmo banco. `replica-status` verifica o estado local via
Litestream; **não atesta sincronização remota nem atraso zero**. Saída bruta do
processo externo é suprimida para evitar vazamento em mensagens de erro.
Para recuperar: pare todos os processos MCP e réplica; arquive manualmente o
banco e seus sidecars, sem excluí-los. O destino e sidecars precisam estar
ausentes; não existe opção force/overwrite nesta CLI.
```sh
./bin/woovi-pix-mcp replica-restore --profile sandbox --acknowledge-stale-state
./bin/woovi-pix-mcp doctor --profile sandbox
```
A restauração faz integrity check completo e cria `operations.db.recovered`,
que bloqueia inicialização com criação habilitada. **Não remova esse marcador
antes de conferir o histórico da Woovi e reconciliar operações possivelmente
ausentes na cópia**. Se não conseguir reconciliar, permaneça em leitura. Não há
importação automática de histórico PSP nem botão de desbloqueio automático.
Uma falha de restore pode deixar arquivos parciais: arquive-os e investigue,
não reinicie com estado vazio. O marcador também permanece em caso de falha.
Litestream replica de forma assíncrona: RPO depende do último envio confirmado;
RTO depende da recuperação manual. Não oferece HA automática ou multiwriter.
Uma cópia antiga pode esquecer uma criação já efetivada no provedor; restaurar
o banco não autoriza repetir pedidos financeiros com novas referências.
Integração real de réplica em arquivo e armazenamento S3 local (SeaweedFS):
```sh
TEST_LITESTREAM_BINARY=/absolute/path/litestream make test-litestream
```
Esse target precisa Docker somente para os testes opcionais de réplica; uso
normal continua sem Docker. CI executa ambos os backends e valida o checksum
do binário fixado. Não chama Woovi nem usa credenciais reais.
Roteiro e troubleshooting: [docs/sandbox.md](docs/sandbox.md).
This server cannot be deployed
Maintenance
ActivityNo data
ResponsivenessSyncing