{"_id":"@advlex/mcp-lex","_rev":"2-0423eef7dd727f55ff5b6cbd14b1494b","name":"@advlex/mcp-lex","dist-tags":{"latest":"0.2.0"},"versions":{"0.1.0":{"name":"@advlex/mcp-lex","version":"0.1.0","keywords":["mcp","advlex","lex","advocacia"],"author":{"name":"TH PUBLICACOES LEGAIS LTDA"},"license":"UNLICENSED","_id":"@advlex/mcp-lex@0.1.0","maintainers":[{"name":"advlex","email":"tpholanda@gmail.com"}],"homepage":"https://advlex.com.br","bin":{"mcp-lex":"src/index.js"},"dist":{"shasum":"b7d2385a3c2d376f28468ec8254557bbd0d66bb8","tarball":"https://registry.npmjs.org/@advlex/mcp-lex/-/mcp-lex-0.1.0.tgz","fileCount":5,"integrity":"sha512-3fO1Ach9mN1N5+lejzQvsjAzOOPhKjv1Aaf/FcTqkXtGcZnQz1df4AvB3K2dfaF5681F/TIoDLO8x6pbIfZbzQ==","signatures":[{"sig":"MEQCIDCTYylVJhNAjpEExmA0ygD6n89351aNURxIq8uU1SI/AiBwEf3zkdlO8K40yTPpmX5c4HqvIaZa7FkjD+6UP7McOw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":33091},"main":"src/index.js","type":"commonjs","engines":{"node":">=18"},"_npmUser":{"name":"advlex","email":"tpholanda@gmail.com"},"_npmVersion":"12.0.2","description":"Conector MCP da AdvLex — dá ao Claude do escritório acesso de leitura à instância Lex (conversas, clientes, processos, prazos, modelos).","directories":{},"_nodeVersion":"22.23.2","dependencies":{"zod":"^3.23.8","@modelcontextprotocol/sdk":"^1.30.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/mcp-lex_0.1.0_1786635458955_0.11234244666311866","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"_id":"@advlex/mcp-lex@0.2.0","bin":{"mcp-lex":"src/index.js"},"dist":{"shasum":"e8d6428cb256cc0a803470a4d8d5267dea990361","tarball":"https://registry.npmjs.org/@advlex/mcp-lex/-/mcp-lex-0.2.0.tgz","integrity":"sha512-rXioK/g678IRjcqS0/c4yfX31Fd+Puf9BlZVcxLTCPkgMj+Sk7a/hr8zQIISopKc/yyIV48appvQMayRtJ5KFA==","fileCount":5,"unpackedSize":42514,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIDcEkajlng6+C/y0KaPkPytHNUDJNDvhByshS1Cq8qXiAiBI1+FB8dzlTFRHqGKwMbFCzubiGebUo5gn5uQEbbTqhg=="}]},"main":"src/index.js","name":"@advlex/mcp-lex","type":"commonjs","author":{"name":"TH PUBLICACOES LEGAIS LTDA"},"engines":{"node":">=18"},"gitHead":"15d27f5c4eaec00ac6f07533ffa17c27a0fa78ef","license":"UNLICENSED","version":"0.2.0","_npmUser":{"name":"advlex","email":"tpholanda@gmail.com","approver":{"name":"advlex","email":"tpholanda@gmail.com"}},"homepage":"https://advlex.com.br","keywords":["mcp","advlex","lex","advocacia"],"_npmVersion":"12.0.2","description":"Conector MCP da AdvLex — dá ao Claude do escritório acesso de leitura à instância Lex (conversas, clientes, processos, prazos, modelos).","directories":{},"maintainers":[{"name":"advlex","email":"tpholanda@gmail.com"}],"_nodeVersion":"22.23.2","dependencies":{"zod":"^3.23.8","@modelcontextprotocol/sdk":"^1.30.0"},"publishConfig":{"access":"public"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/mcp-lex_0.2.0_1787683993566_0.979368894248325"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-13T15:37:38.753Z","modified":"2026-08-25T18:53:14.015Z","0.1.0":"2026-08-13T15:37:39.104Z","0.2.0":"2026-08-25T18:53:13.650Z"},"author":{"name":"TH PUBLICACOES LEGAIS LTDA"},"license":"UNLICENSED","homepage":"https://advlex.com.br","keywords":["mcp","advlex","lex","advocacia"],"description":"Conector MCP da AdvLex — dá ao Claude do escritório acesso de leitura à instância Lex (conversas, clientes, processos, prazos, modelos).","maintainers":[{"name":"advlex","email":"tpholanda@gmail.com"}],"readme":"# MCP Lex — conector do Claude do cliente (tarefa #34)\n\nPermite que o comprador use o Claude dele (\"veja a conversa do número X, monte a pasta de protocolo\") conectado à própria instância Lex.\n\nInstruções para o comprador: [INSTALACAO.md](INSTALACAO.md).\n\n## Arquitetura (decidida 13/08/2026, implementada 13/08/2026)\n- Servidor MCP **stdio** em Node (`@modelcontextprotocol/sdk`), instalado na máquina do cliente via `npx mcp-lex`.\n- Autentica na instância com `LEX_URL` + `LEX_API_KEY` (a `automation_api_key` da instância).\n- Sem estado próprio: tudo é HTTP contra a instância do comprador. Uma instância, uma chave.\n- Ferramentas v1 (`src/index.js`), com o cliente HTTP em `src/lex-client.js`:\n  1. `listar_conversas(filtro?, numero?, limite?)` — junta WA1 + WA2, com estágio/área\n  2. `ler_conversa(telefone, numero?, limite?)` — histórico completo + URLs de mídia\n  3. `baixar_midia(telefone, numero?, tipos?, pasta?)` — salva os arquivos em disco e devolve os caminhos\n  4. `dados_cliente(nome_ou_telefone)` — cadastro + processos + prazos + últimas mensagens\n  5. `gerar_documento(cliente, tipo, objeto)` — usa o gerador existente (client-documents.js) e salva .docx\n  6. `listar_modelos(tipo?, area?)` — modelos do escritório\n\nDetalhes que valem lembrar:\n- O telefone digitado é resolvido pelo **sufixo de 8 dígitos** contra a lista de conversas, porque o banco guarda `55 + DDD + número` e o nono dígito nem sempre está lá. Máscara (\"(85) 98650-0579\") funciona.\n- `baixar_midia` grava em disco em vez de devolver base64: áudio e PDF estourariam o contexto do Claude, e o caso de uso é justamente montar a pasta do cliente. Padrão `~/Downloads/lex-midias/<nome>_<telefone>/`.\n- `gerar_documento` sempre gera procuração **e** contrato no servidor (duas chamadas ao Claude, sequenciais, ~1 min); o parâmetro `tipo` só escolhe qual sai em .docx. Timeout do cliente em 5 min.\n\n## Backend — o que mudou\n- `middleware/auth.js`: além das 4 rotas de envio, a `x-automation-key` agora abre `AUTOMATION_READ_PATHS` (conversas, mensagens, clientes, processos, prazos, modelos) **só em GET**, e `AUTOMATION_ACTION_PATHS` (geração e exportação de documento) só em POST. A checagem de método é essencial: o allowlist casa apenas o caminho, então liberar `/clients` sem olhar o método abriria POST/PUT/DELETE na mesma rota.\n- `routes/auth.js`: `GET /api/auth/automation-key` e `POST /api/auth/automation-key/rotate`, ambos exigindo login (a chave de automação não lê a si mesma).\n- `Settings.tsx`: bloco \"Conector do Claude — chave de automação\", com mostrar/copiar/rotacionar.\n- `services/document-export.js`: corrigido `getOffice is not defined` (usado no alt text do logo, nunca importado). Isso quebrava com 500 **toda** exportação de .docx, inclusive a do painel.\n\nBackups no VPS dos arquivos tocados: `*.bak-mcp34`.\n\n## Resolvido em 24/08/2026\n\n**Mídia agora exige link assinado.** As rotas `/api/whatsapp/media/*` e `/api/whatsapp2/media/*` continuam fora do `requireAuth`, porque `<img>`/`<audio>` realmente não mandam header, mas passaram a validar por conta própria: ou a requisição já está autenticada (JWT ou chave de automação), ou a URL traz uma assinatura HMAC válida. Sem isso, 401.\n\n- Helper em `src/utils/media-token.js`. Segredo derivado do JWT, então rotacionar o JWT invalida os links antigos junto. Validade de 7 dias.\n- As rotas `/messages` dos dois números devolvem `media_url` já assinada (`assinarMensagens`). **O frontend não mudou**, porque sempre consumiu a URL que a API entrega.\n- **O conector MCP também não precisou mudar**: ele lê as mensagens por `/messages`, que é rota liberada para a chave de automação, e recebe as URLs assinadas prontas.\n- Testado em produção: sem token 401, token inválido 401, token válido 200, nos dois números.\n- Backups: `src/routes/*.bak-media-20260824-1131`.\n\n**`pickTemplates` não usa mais modelo de tema alheio.** Um modelo cujo nome carrega tema próprio (Consórcio, Divórcio, INSS, Consignação, Negativação, Protesto, Trabalhista, Pensão) só é escolhido quando o objeto do caso é daquele tema; caso contrário a busca cai no modelo geral. Acrescentado hint para consignado, que não existia.\n\n⚠️ **A gravidade desse segundo item era menor do que este README dizia.** Conferindo os conteúdos por hash, o \"Contrato de Honorários Consórcio\" é **byte a byte idêntico** ao \"Contrato de Honorários (Geral)\" e não menciona consórcio no texto. O mesmo vale para as procurações: Geral, Divórcio, INSS/BPC e Consórcio são o **mesmo documento**, coerente com a decisão de unificar a procuração num modelo único. Ou seja, o defeito era de **rótulo**, não de conteúdo: o cliente de consignado nunca recebeu contrato de consórcio. A correção vale para manter o registro coerente e para o dia em que algum desses modelos passar a ser de fato específico.\n\nConferido de passagem: a variante de contrato para trabalhista/consumidor/maternidade está correta no banco, com \"não havendo cobrança de honorários sobre prestações vincendas\", e a previdenciária tem as 12 vincendas e o art. 50 do CED. Nada a cadastrar.\n\n## Versão 0.2.0 (25/08/2026)\n\n**Ferramenta nova: `enviar_mensagem`.** O Claude do comprador passa a poder responder um cliente pelo WhatsApp do escritório (\"responde o Emerson pedindo o extrato da cota\"). Duas travas, e as duas são consequência do desenho, não código extra:\n\n- **Só envia para quem já tem conversa aberta na instância.** O `resolverConversa` é o caminho: telefone que não casa com nenhuma conversa é recusado. Isso elimina o pior cenário, que é disparo para um número inventado ou digitado errado.\n- **Ambiguidade nunca é resolvida por conta própria.** \"Emerson\" casava com ele e com a esposa: a ferramenta lista as opções e não envia.\n\nO retorno ecoa destinatário, número de origem e o **texto integral enviado**, que fica no transcrito do Claude e serve de auditoria do que saiu em nome do advogado.\n\nNota de segurança que vale registrar: as 4 rotas de envio **já estavam liberadas** para a `automation_api_key` desde a v0.1.0, em qualquer método. Não ter a ferramenta nunca foi uma restrição, era só ausência de conveniência. Se um dia for preciso restringir de verdade, o controle tem que ser no servidor, não no conector.\n\n**Corrigido: o conector enxergava só os 100 contatos mais recentes.** As rotas `GET /conversations` dos dois números tinham `LIMIT 100` fixo, sem parâmetro. Na instância do escritório isso significava **483 de 683 conversas invisíveis, 71% do acervo**. Afetava `ler_conversa`, `baixar_midia`, `dados_cliente` e teria afetado a ferramenta nova: um cliente de dois meses atrás simplesmente \"não existia\" para o Claude.\n\n- Backend: as duas rotas passam a aceitar `?search=` (casa sufixo de 8 dígitos do telefone **ou** nome) e `?limit=` (padrão 100, teto 2000). **Sem parâmetro o comportamento é idêntico ao anterior**, então o painel não mudou.\n- Conector: `resolverConversa` manda o termo como `?search=`. O filtro local continua valendo como segunda rede, porque instância que ainda não atualizou ignora o parâmetro e devolve os 100 de sempre.\n- Backups no VPS: `src/routes/*.bak-search-20260825-1510`.\n\nTestado em produção: sem parâmetro 100 conversas, busca por telefone e por nome achando contato fora dos 100, `?limit=2000` trazendo 438 no WA1 e 245 no WA2, e envio real chegando ao destino.\n\n## Pontos em aberto\n- Publicado em 13/08/2026 como `@advlex/mcp-lex@0.1.0` (público, escopo pessoal do usuário `advlex`, versão solta no manual durante os fundadores). Validado pelo caminho do comprador: `npx -y @advlex/mcp-lex` com cache zerado, no Node 20.\n- **Como publicar as próximas versões:** o npm não cadastra mais aplicativo autenticador, então a conta usa chave de acesso e não existe código de 6 dígitos. O `npm publish` precisa da versão nova (Node 22 + npm 12, instalados ao lado em `~/.nvm/versions/node/v22.23.2`), que abre o navegador para confirmar com Touch ID. Isso exige terminal interativo, então quem roda é o Dr. Tiago: `export PATH=\"$HOME/.nvm/versions/node/v22.23.2/bin:$PATH\" && cd ~/juridico-app/mcp-lex && npm publish`. Alternativa a partir de agora que o pacote existe: `npm stage publish` (não pede 2FA, pode ser rodado pelo Claude) e o Dr. Tiago aprova no site em Pacotes por etapas, sem abrir terminal.\n\n## Status\n- [x] Rotas de leitura por automation_api_key (com checagem de método)\n- [x] Server MCP (6 ferramentas)\n- [x] Teste contra a instância real (lex.tiagoholanda.com) — as 6 ferramentas\n- [x] Instruções de instalação pro cliente (INSTALACAO.md)\n- [x] Publicado no npm: `@advlex/mcp-lex@0.1.0`, testado por `npx` a partir do registro público\n","readmeFilename":"README.md"}