mcp-pdv-demo
by LuanV1udes
README.md
# mcp-pdv-demo
Servidor **MCP (Model Context Protocol)** que conecta um assistente de IA ao banco de um PDV — ponto de venda de varejo e food service.
Em vez de expor um `executar_sql` genérico, ele expõe **perguntas de negócio**: qual foi o faturamento, o que dá mais margem, o que está encalhado no estoque, se o caixa fechou certo. O modelo escolhe a ferramenta; o SQL fica do lado de cá, escrito e testado.
> Banco 100% sintético, gerado por seed determinístico. Nenhum dado real de cliente.
```
Claude / Cursor / qualquer host MCP
│ stdio
▼
mcp-pdv-demo ──► Prisma ──► SQLite
(6 tools de leitura + 1 de escrita, sob flag)
```
## Rodando
```bash
npm install
npm run setup # cria o banco e gera ~96 produtos, 90 dias, ~3.700 vendas
npm run dev # sobe o servidor MCP no stdio
```
### Conectando no Claude Code
```bash
claude mcp add pdv-demo -- npx tsx /caminho/para/mcp-pdv-demo/src/server.ts
```
### Conectando no Claude Desktop
Em `claude_desktop_config.json`:
```json
{
"mcpServers": {
"pdv-demo": {
"command": "npx",
"args": ["tsx", "/caminho/para/mcp-pdv-demo/src/server.ts"],
"env": { "DATABASE_URL": "file:./pdv.db" }
}
}
}
```
## As ferramentas
| Tool | Responde |
|---|---|
| `consultar_produto` | "quanto custa X", "tem X em estoque", "qual o código de X" |
| `resumo_de_vendas` | "quanto vendi em maio", "qual meu ticket médio", "quanto entrou no pix" |
| `produtos_mais_vendidos` | "o que mais vendeu", "top 10 do mês", "meus carros-chefe" |
| `margem_por_categoria` | "o que dá mais lucro" — que não é a mesma pergunta que "o que mais vende" |
| `produtos_encalhados` | "o que está parado", "quanto de capital tem preso no estoque" |
| `fechamento_de_caixa` | "fecha o caixa de ontem", "teve diferença", "sobrou ou faltou dinheiro" |
| `ajustar_estoque` | escrita — só existe se `PDV_MCP_READONLY=false` |
### Saída real
`resumo_de_vendas`:
```
**Vendas de 2026-08-01 a 2026-08-31**
- Faturamento: **R$ 136.517,91**
- Vendas concluidas: 1345
- Ticket medio: R$ 101,50
- Descontos concedidos: R$ 1.484,56
- Vendas canceladas: 37
| Forma | Vendas | Valor | % do total |
| -------- | ------ | ------------ | ---------- |
| PIX | 459 | R$ 49.385,27 | 36.2% |
| DEBITO | 360 | R$ 36.350,09 | 26.6% |
| CREDITO | 336 | R$ 32.355,06 | 23.7% |
| DINHEIRO | 190 | R$ 18.427,49 | 13.5% |
```
`produtos_encalhados`:
```
5 produto(s) sem vender ha 30+ dias. Capital parado: **R$ 8.690,14**.
| Produto | Categoria | Estoque | Custo un. | Capital parado |
| ----------------- | --------- | ------- | --------- | -------------- |
| Polenta Frita ... | Porcoes | 100 | R$ 28,21 | R$ 2.821,00 |
| Misto Quente ... | Lanches | 92 | R$ 30,21 | R$ 2.779,32 |
| Creme Dental | Higiene | 96 | R$ 18,31 | R$ 1.757,76 |
```
## Decisões de projeto
**Dinheiro é `Int` em centavos, nunca `Float`.** `0.1 + 0.2 !== 0.3` — num PDV isso vira quebra de caixa. A conversão para reais acontece só na formatação da saída.
**Read-only por padrão.** As tools de escrita não são apenas bloqueadas: elas não são *registradas*. Se `PDV_MCP_READONLY` não for explicitamente `"false"`, `ajustar_estoque` não aparece no `listTools` — o modelo não pode chamar o que não sabe que existe. A decisão fica no ambiente, fora do alcance do prompt.
**Preço e custo são congelados no item da venda.** `ItemVenda` guarda `precoUnitario` e `custoUnitario` do momento da venda. Sem isso, mudar o preço de um produto reescreveria o histórico de margem — um relatório de março passaria a mentir porque o custo subiu em agosto.
**A saída é markdown, não JSON.** O consumidor é um modelo de linguagem. Tabela formatada com R$ e percentual gasta menos contexto e produz menos erro de leitura do que um array de objetos com valores em centavos.
**Nada de `executar_sql`.** Uma tool que aceita SQL arbitrário transfere para o modelo a responsabilidade de entender o schema, e transfere para o usuário o risco de um `DELETE`. Cada tool aqui é uma pergunta fechada com uma query revisada atrás.
**Log vai para stderr.** No transporte stdio, o stdout *é* o canal do protocolo — um `console.log` perdido corrompe a sessão inteira.
## Testes
```bash
npm test
```
18 testes que sobem um cliente MCP real ligado ao servidor por transporte em memória — exercitam o protocolo inteiro, não as funções por dentro. Cobrem o contrato (toda tool tem descrição; a de escrita não aparece em modo leitura), a corretude dos números contra o banco, parsing de data em dois formatos, e os casos vazios.
## Stack
TypeScript · [MCP SDK](https://github.com/modelcontextprotocol/typescript-sdk) · Prisma · SQLite · Zod · Vitest
## Licença
MIT
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues