npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@advlex/mcp-lex

v0.2.0

Published

Conector MCP da AdvLex — dá ao Claude do escritório acesso de leitura à instância Lex (conversas, clientes, processos, prazos, modelos).

Readme

MCP Lex — conector do Claude do cliente (tarefa #34)

Permite 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.

Instruções para o comprador: INSTALACAO.md.

Arquitetura (decidida 13/08/2026, implementada 13/08/2026)

  • Servidor MCP stdio em Node (@modelcontextprotocol/sdk), instalado na máquina do cliente via npx mcp-lex.
  • Autentica na instância com LEX_URL + LEX_API_KEY (a automation_api_key da instância).
  • Sem estado próprio: tudo é HTTP contra a instância do comprador. Uma instância, uma chave.
  • Ferramentas v1 (src/index.js), com o cliente HTTP em src/lex-client.js:
    1. listar_conversas(filtro?, numero?, limite?) — junta WA1 + WA2, com estágio/área
    2. ler_conversa(telefone, numero?, limite?) — histórico completo + URLs de mídia
    3. baixar_midia(telefone, numero?, tipos?, pasta?) — salva os arquivos em disco e devolve os caminhos
    4. dados_cliente(nome_ou_telefone) — cadastro + processos + prazos + últimas mensagens
    5. gerar_documento(cliente, tipo, objeto) — usa o gerador existente (client-documents.js) e salva .docx
    6. listar_modelos(tipo?, area?) — modelos do escritório

Detalhes que valem lembrar:

  • 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.
  • 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>/.
  • 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.

Backend — o que mudou

  • 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.
  • 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).
  • Settings.tsx: bloco "Conector do Claude — chave de automação", com mostrar/copiar/rotacionar.
  • 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.

Backups no VPS dos arquivos tocados: *.bak-mcp34.

Resolvido em 24/08/2026

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.

  • 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.
  • 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.
  • 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.
  • Testado em produção: sem token 401, token inválido 401, token válido 200, nos dois números.
  • Backups: src/routes/*.bak-media-20260824-1131.

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.

⚠️ 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.

Conferido 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.

Versão 0.2.0 (25/08/2026)

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:

  • 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.
  • 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.

O 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.

Nota 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.

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.

  • 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.
  • 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.
  • Backups no VPS: src/routes/*.bak-search-20260825-1510.

Testado 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.

Pontos em aberto

  • Publicado em 13/08/2026 como @advlex/[email protected] (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.
  • 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.

Status

  • [x] Rotas de leitura por automation_api_key (com checagem de método)
  • [x] Server MCP (6 ferramentas)
  • [x] Teste contra a instância real (lex.tiagoholanda.com) — as 6 ferramentas
  • [x] Instruções de instalação pro cliente (INSTALACAO.md)
  • [x] Publicado no npm: @advlex/[email protected], testado por npx a partir do registro público